diff options
author | Tobias Weimer <wishmaster51@googlemail.com> | 2015-07-12 14:10:16 +0000 |
---|---|---|
committer | Tobias Weimer <wishmaster51@googlemail.com> | 2015-07-12 14:10:16 +0000 |
commit | f4ce2b5c214cce406dbd7a73dc7f35ae409546ad (patch) | |
tree | 533cc821ffc9c5664c075930be6a40fde9593aba | |
parent | 71a88c6d8c4578ca24e02a5c6f4860c206e7c6da (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
292 files changed, 96631 insertions, 0 deletions
diff --git a/plugins/Clist_ng/AGG/include/agg_alpha_mask_u8.h b/plugins/Clist_ng/AGG/include/agg_alpha_mask_u8.h new file mode 100644 index 0000000000..4a99a94e12 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_alpha_mask_u8.h @@ -0,0 +1,505 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_ALPHA_MASK_U8_INCLUDED
+#define AGG_ALPHA_MASK_U8_INCLUDED
+
+#include <string.h>
+#include "agg_basics.h"
+#include "agg_rendering_buffer.h"
+
+namespace agg
+{
+ //===================================================one_component_mask_u8
+ struct one_component_mask_u8
+ {
+ static unsigned calculate(const int8u* p) { return *p; }
+ };
+
+
+ //=====================================================rgb_to_gray_mask_u8
+ template<unsigned R, unsigned G, unsigned B>
+ struct rgb_to_gray_mask_u8
+ {
+ static unsigned calculate(const int8u* p)
+ {
+ return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
+ }
+ };
+
+ //==========================================================alpha_mask_u8
+ template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
+ class alpha_mask_u8
+ {
+ public:
+ typedef int8u cover_type;
+ typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
+ enum cover_scale_e
+ {
+ cover_shift = 8,
+ cover_none = 0,
+ cover_full = 255
+ };
+
+ alpha_mask_u8() : m_rbuf(0) {}
+ explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
+
+ void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
+
+ MaskF& mask_function() { return m_mask_function; }
+ const MaskF& mask_function() const { return m_mask_function; }
+
+
+ //--------------------------------------------------------------------
+ cover_type pixel(int x, int y) const
+ {
+ if(x >= 0 && y >= 0 &&
+ x < (int)m_rbuf->width() &&
+ y < (int)m_rbuf->height())
+ {
+ return (cover_type)m_mask_function.calculate(
+ m_rbuf->row_ptr(y) + x * Step + Offset);
+ }
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ cover_type combine_pixel(int x, int y, cover_type val) const
+ {
+ if(x >= 0 && y >= 0 &&
+ x < (int)m_rbuf->width() &&
+ y < (int)m_rbuf->height())
+ {
+ return (cover_type)((cover_full + val *
+ m_mask_function.calculate(
+ m_rbuf->row_ptr(y) + x * Step + Offset)) >>
+ cover_shift);
+ }
+ return 0;
+ }
+
+
+ //--------------------------------------------------------------------
+ void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ int xmax = m_rbuf->width() - 1;
+ int ymax = m_rbuf->height() - 1;
+
+ int count = num_pix;
+ cover_type* covers = dst;
+
+ if(y < 0 || y > ymax)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+
+ if(x < 0)
+ {
+ count += x;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers, 0, -x * sizeof(cover_type));
+ covers -= x;
+ x = 0;
+ }
+
+ if(x + count > xmax)
+ {
+ int rest = x + count - xmax - 1;
+ count -= rest;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers + count, 0, rest * sizeof(cover_type));
+ }
+
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *covers++ = (cover_type)m_mask_function.calculate(mask);
+ mask += Step;
+ }
+ while(--count);
+ }
+
+
+ //--------------------------------------------------------------------
+ void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ int xmax = m_rbuf->width() - 1;
+ int ymax = m_rbuf->height() - 1;
+
+ int count = num_pix;
+ cover_type* covers = dst;
+
+ if(y < 0 || y > ymax)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+
+ if(x < 0)
+ {
+ count += x;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers, 0, -x * sizeof(cover_type));
+ covers -= x;
+ x = 0;
+ }
+
+ if(x + count > xmax)
+ {
+ int rest = x + count - xmax - 1;
+ count -= rest;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers + count, 0, rest * sizeof(cover_type));
+ }
+
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *covers = (cover_type)((cover_full + (*covers) *
+ m_mask_function.calculate(mask)) >>
+ cover_shift);
+ ++covers;
+ mask += Step;
+ }
+ while(--count);
+ }
+
+ //--------------------------------------------------------------------
+ void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ int xmax = m_rbuf->width() - 1;
+ int ymax = m_rbuf->height() - 1;
+
+ int count = num_pix;
+ cover_type* covers = dst;
+
+ if(x < 0 || x > xmax)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+
+ if(y < 0)
+ {
+ count += y;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers, 0, -y * sizeof(cover_type));
+ covers -= y;
+ y = 0;
+ }
+
+ if(y + count > ymax)
+ {
+ int rest = y + count - ymax - 1;
+ count -= rest;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers + count, 0, rest * sizeof(cover_type));
+ }
+
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *covers++ = (cover_type)m_mask_function.calculate(mask);
+ mask += m_rbuf->stride();
+ }
+ while(--count);
+ }
+
+ //--------------------------------------------------------------------
+ void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ int xmax = m_rbuf->width() - 1;
+ int ymax = m_rbuf->height() - 1;
+
+ int count = num_pix;
+ cover_type* covers = dst;
+
+ if(x < 0 || x > xmax)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+
+ if(y < 0)
+ {
+ count += y;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers, 0, -y * sizeof(cover_type));
+ covers -= y;
+ y = 0;
+ }
+
+ if(y + count > ymax)
+ {
+ int rest = y + count - ymax - 1;
+ count -= rest;
+ if(count <= 0)
+ {
+ memset(dst, 0, num_pix * sizeof(cover_type));
+ return;
+ }
+ memset(covers + count, 0, rest * sizeof(cover_type));
+ }
+
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *covers = (cover_type)((cover_full + (*covers) *
+ m_mask_function.calculate(mask)) >>
+ cover_shift);
+ ++covers;
+ mask += m_rbuf->stride();
+ }
+ while(--count);
+ }
+
+
+ private:
+ alpha_mask_u8(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ rendering_buffer* m_rbuf;
+ MaskF m_mask_function;
+ };
+
+
+ typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
+
+ typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
+ typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
+ typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
+
+ typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
+ typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
+ typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
+
+ typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
+ typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
+ typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
+ typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
+
+ typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
+ typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
+ typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
+ typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
+
+ typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
+ typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
+ typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
+ typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
+
+ typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
+ typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
+ typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
+ typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
+
+ typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
+ typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
+ typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
+ typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
+ typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
+ typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
+
+
+
+ //==========================================================amask_no_clip_u8
+ template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
+ class amask_no_clip_u8
+ {
+ public:
+ typedef int8u cover_type;
+ typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
+ enum cover_scale_e
+ {
+ cover_shift = 8,
+ cover_none = 0,
+ cover_full = 255
+ };
+
+ amask_no_clip_u8() : m_rbuf(0) {}
+ explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
+
+ void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
+
+ MaskF& mask_function() { return m_mask_function; }
+ const MaskF& mask_function() const { return m_mask_function; }
+
+
+ //--------------------------------------------------------------------
+ cover_type pixel(int x, int y) const
+ {
+ return (cover_type)m_mask_function.calculate(
+ m_rbuf->row_ptr(y) + x * Step + Offset);
+ }
+
+
+ //--------------------------------------------------------------------
+ cover_type combine_pixel(int x, int y, cover_type val) const
+ {
+ return (cover_type)((cover_full + val *
+ m_mask_function.calculate(
+ m_rbuf->row_ptr(y) + x * Step + Offset)) >>
+ cover_shift);
+ }
+
+
+ //--------------------------------------------------------------------
+ void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *dst++ = (cover_type)m_mask_function.calculate(mask);
+ mask += Step;
+ }
+ while(--num_pix);
+ }
+
+
+
+ //--------------------------------------------------------------------
+ void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *dst = (cover_type)((cover_full + (*dst) *
+ m_mask_function.calculate(mask)) >>
+ cover_shift);
+ ++dst;
+ mask += Step;
+ }
+ while(--num_pix);
+ }
+
+
+ //--------------------------------------------------------------------
+ void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *dst++ = (cover_type)m_mask_function.calculate(mask);
+ mask += m_rbuf->stride();
+ }
+ while(--num_pix);
+ }
+
+
+ //--------------------------------------------------------------------
+ void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
+ {
+ const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
+ do
+ {
+ *dst = (cover_type)((cover_full + (*dst) *
+ m_mask_function.calculate(mask)) >>
+ cover_shift);
+ ++dst;
+ mask += m_rbuf->stride();
+ }
+ while(--num_pix);
+ }
+
+ private:
+ amask_no_clip_u8(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ rendering_buffer* m_rbuf;
+ MaskF m_mask_function;
+ };
+
+
+ typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
+
+ typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
+ typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g
+ typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b
+
+ typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r
+ typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g
+ typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b
+
+ typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
+ typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
+ typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
+ typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
+
+ typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
+ typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
+ typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
+ typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
+
+ typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
+ typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
+ typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
+ typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
+
+ typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
+ typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
+ typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
+ typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
+
+ typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray
+ typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray
+ typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
+ typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
+ typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
+ typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
+
+
+}
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_arc.h b/plugins/Clist_ng/AGG/include/agg_arc.h new file mode 100644 index 0000000000..6ff919e582 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_arc.h @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_ARC_INCLUDED
+#define AGG_ARC_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //=====================================================================arc
+ //
+ // See Implementation agg_arc.cpp
+ //
+ class arc
+ {
+ public:
+ arc() : m_scale(1.0), m_initialized(false) {}
+ arc(double x, double y,
+ double rx, double ry,
+ double a1, double a2,
+ bool ccw=true);
+
+ void init(double x, double y,
+ double rx, double ry,
+ double a1, double a2,
+ bool ccw=true);
+
+ void approximation_scale(double s);
+ double approximation_scale() const { return m_scale; }
+
+ void rewind(unsigned);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ void normalize(double a1, double a2, bool ccw);
+
+ double m_x;
+ double m_y;
+ double m_rx;
+ double m_ry;
+ double m_angle;
+ double m_start;
+ double m_end;
+ double m_scale;
+ double m_da;
+ bool m_ccw;
+ bool m_initialized;
+ unsigned m_path_cmd;
+ };
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_array.h b/plugins/Clist_ng/AGG/include/agg_array.h new file mode 100644 index 0000000000..81ed4dd822 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_array.h @@ -0,0 +1,1129 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_ARRAY_INCLUDED
+#define AGG_ARRAY_INCLUDED
+
+#include <stddef.h>
+#include <string.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //-------------------------------------------------------pod_array_adaptor
+ template<class T> class pod_array_adaptor
+ {
+ public:
+ typedef T value_type;
+ pod_array_adaptor(T* array, unsigned size) :
+ m_array(array), m_size(size) {}
+
+ unsigned size() const { return m_size; }
+ const T& operator [] (unsigned i) const { return m_array[i]; }
+ T& operator [] (unsigned i) { return m_array[i]; }
+ const T& at(unsigned i) const { return m_array[i]; }
+ T& at(unsigned i) { return m_array[i]; }
+ T value_at(unsigned i) const { return m_array[i]; }
+
+ private:
+ T* m_array;
+ unsigned m_size;
+ };
+
+
+ //---------------------------------------------------------pod_auto_array
+ template<class T, unsigned Size> class pod_auto_array
+ {
+ public:
+ typedef T value_type;
+ typedef pod_auto_array<T, Size> self_type;
+
+ pod_auto_array() {}
+ explicit pod_auto_array(const T* c)
+ {
+ memcpy(m_array, c, sizeof(T) * Size);
+ }
+
+ const self_type& operator = (const T* c)
+ {
+ memcpy(m_array, c, sizeof(T) * Size);
+ return *this;
+ }
+
+ static unsigned size() { return Size; }
+ const T& operator [] (unsigned i) const { return m_array[i]; }
+ T& operator [] (unsigned i) { return m_array[i]; }
+ const T& at(unsigned i) const { return m_array[i]; }
+ T& at(unsigned i) { return m_array[i]; }
+ T value_at(unsigned i) const { return m_array[i]; }
+
+ private:
+ T m_array[Size];
+ };
+
+
+ //--------------------------------------------------------pod_auto_vector
+ template<class T, unsigned Size> class pod_auto_vector
+ {
+ public:
+ typedef T value_type;
+ typedef pod_auto_vector<T, Size> self_type;
+
+ pod_auto_vector() : m_size(0) {}
+
+ void remove_all() { m_size = 0; }
+ void clear() { m_size = 0; }
+ void add(const T& v) { m_array[m_size++] = v; }
+ void push_back(const T& v) { m_array[m_size++] = v; }
+ void inc_size(unsigned size) { m_size += size; }
+
+ unsigned size() const { return m_size; }
+ const T& operator [] (unsigned i) const { return m_array[i]; }
+ T& operator [] (unsigned i) { return m_array[i]; }
+ const T& at(unsigned i) const { return m_array[i]; }
+ T& at(unsigned i) { return m_array[i]; }
+ T value_at(unsigned i) const { return m_array[i]; }
+
+ private:
+ T m_array[Size];
+ unsigned m_size;
+ };
+
+
+ //---------------------------------------------------------------pod_array
+ template<class T> class pod_array
+ {
+ public:
+ typedef T value_type;
+ typedef pod_array<T> self_type;
+
+ ~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); }
+ pod_array() : m_array(0), m_size(0) {}
+
+ pod_array(unsigned size) :
+ m_array(pod_allocator<T>::allocate(size)),
+ m_size(size)
+ {}
+
+ pod_array(const self_type& v) :
+ m_array(pod_allocator<T>::allocate(v.m_size)),
+ m_size(v.m_size)
+ {
+ memcpy(m_array, v.m_array, sizeof(T) * m_size);
+ }
+
+ void resize(unsigned size)
+ {
+ if(size != m_size)
+ {
+ pod_allocator<T>::deallocate(m_array, m_size);
+ m_array = pod_allocator<T>::allocate(m_size = size);
+ }
+ }
+ const self_type& operator = (const self_type& v)
+ {
+ resize(v.size());
+ memcpy(m_array, v.m_array, sizeof(T) * m_size);
+ return *this;
+ }
+
+ unsigned size() const { return m_size; }
+ const T& operator [] (unsigned i) const { return m_array[i]; }
+ T& operator [] (unsigned i) { return m_array[i]; }
+ const T& at(unsigned i) const { return m_array[i]; }
+ T& at(unsigned i) { return m_array[i]; }
+ T value_at(unsigned i) const { return m_array[i]; }
+
+ const T* data() const { return m_array; }
+ T* data() { return m_array; }
+ private:
+ T* m_array;
+ unsigned m_size;
+ };
+
+
+
+ //--------------------------------------------------------------pod_vector
+ // A simple class template to store Plain Old Data, a vector
+ // of a fixed size. The data is continous in memory
+ //------------------------------------------------------------------------
+ template<class T> class pod_vector
+ {
+ public:
+ typedef T value_type;
+
+ ~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); }
+ pod_vector() : m_size(0), m_capacity(0), m_array(0) {}
+ pod_vector(unsigned cap, unsigned extra_tail=0);
+
+ // Copying
+ pod_vector(const pod_vector<T>&);
+ const pod_vector<T>& operator = (const pod_vector<T>&);
+
+ // Set new capacity. All data is lost, size is set to zero.
+ void capacity(unsigned cap, unsigned extra_tail=0);
+ unsigned capacity() const { return m_capacity; }
+
+ // Allocate n elements. All data is lost,
+ // but elements can be accessed in range 0...size-1.
+ void allocate(unsigned size, unsigned extra_tail=0);
+
+ // Resize keeping the content.
+ void resize(unsigned new_size);
+
+ void zero()
+ {
+ memset(m_array, 0, sizeof(T) * m_size);
+ }
+
+ void add(const T& v) { m_array[m_size++] = v; }
+ void push_back(const T& v) { m_array[m_size++] = v; }
+ void insert_at(unsigned pos, const T& val);
+ void inc_size(unsigned size) { m_size += size; }
+ unsigned size() const { return m_size; }
+ unsigned byte_size() const { return m_size * sizeof(T); }
+ void serialize(int8u* ptr) const;
+ void deserialize(const int8u* data, unsigned byte_size);
+ const T& operator [] (unsigned i) const { return m_array[i]; }
+ T& operator [] (unsigned i) { return m_array[i]; }
+ const T& at(unsigned i) const { return m_array[i]; }
+ T& at(unsigned i) { return m_array[i]; }
+ T value_at(unsigned i) const { return m_array[i]; }
+
+ const T* data() const { return m_array; }
+ T* data() { return m_array; }
+
+ void remove_all() { m_size = 0; }
+ void clear() { m_size = 0; }
+ void cut_at(unsigned num) { if(num < m_size) m_size = num; }
+
+ private:
+ unsigned m_size;
+ unsigned m_capacity;
+ T* m_array;
+ };
+
+ //------------------------------------------------------------------------
+ template<class T>
+ void pod_vector<T>::capacity(unsigned cap, unsigned extra_tail)
+ {
+ m_size = 0;
+ if(cap > m_capacity)
+ {
+ pod_allocator<T>::deallocate(m_array, m_capacity);
+ m_capacity = cap + extra_tail;
+ m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class T>
+ void pod_vector<T>::allocate(unsigned size, unsigned extra_tail)
+ {
+ capacity(size, extra_tail);
+ m_size = size;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T>
+ void pod_vector<T>::resize(unsigned new_size)
+ {
+ if(new_size > m_size)
+ {
+ if(new_size > m_capacity)
+ {
+ T* data = pod_allocator<T>::allocate(new_size);
+ memcpy(data, m_array, m_size * sizeof(T));
+ pod_allocator<T>::deallocate(m_array, m_capacity);
+ m_array = data;
+ }
+ }
+ else
+ {
+ m_size = new_size;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) :
+ m_size(0),
+ m_capacity(cap + extra_tail),
+ m_array(pod_allocator<T>::allocate(m_capacity)) {}
+
+ //------------------------------------------------------------------------
+ template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) :
+ m_size(v.m_size),
+ m_capacity(v.m_capacity),
+ m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0)
+ {
+ memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
+ }
+
+ //------------------------------------------------------------------------
+ template<class T> const pod_vector<T>&
+ pod_vector<T>::operator = (const pod_vector<T>&v)
+ {
+ allocate(v.m_size);
+ if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T> void pod_vector<T>::serialize(int8u* ptr) const
+ {
+ if(m_size) memcpy(ptr, m_array, m_size * sizeof(T));
+ }
+
+ //------------------------------------------------------------------------
+ template<class T>
+ void pod_vector<T>::deserialize(const int8u* data, unsigned byte_size)
+ {
+ byte_size /= sizeof(T);
+ allocate(byte_size);
+ if(byte_size) memcpy(m_array, data, byte_size * sizeof(T));
+ }
+
+ //------------------------------------------------------------------------
+ template<class T>
+ void pod_vector<T>::insert_at(unsigned pos, const T& val)
+ {
+ if(pos >= m_size)
+ {
+ m_array[m_size] = val;
+ }
+ else
+ {
+ memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T));
+ m_array[pos] = val;
+ }
+ ++m_size;
+ }
+
+ //---------------------------------------------------------------pod_bvector
+ // A simple class template to store Plain Old Data, similar to std::deque
+ // It doesn't reallocate memory but instead, uses blocks of data of size
+ // of (1 << S), that is, power of two. The data is NOT contiguous in memory,
+ // so the only valid access method is operator [] or curr(), prev(), next()
+ //
+ // There reallocs occure only when the pool of pointers to blocks needs
+ // to be extended (it happens very rarely). You can control the value
+ // of increment to reallocate the pointer buffer. See the second constructor.
+ // By default, the incremeent value equals (1 << S), i.e., the block size.
+ //------------------------------------------------------------------------
+ template<class T, unsigned S=6> class pod_bvector
+ {
+ public:
+ enum block_scale_e
+ {
+ block_shift = S,
+ block_size = 1 << block_shift,
+ block_mask = block_size - 1
+ };
+
+ typedef T value_type;
+
+ ~pod_bvector();
+ pod_bvector();
+ pod_bvector(unsigned block_ptr_inc);
+
+ // Copying
+ pod_bvector(const pod_bvector<T, S>& v);
+ const pod_bvector<T, S>& operator = (const pod_bvector<T, S>& v);
+
+ void remove_all() { m_size = 0; }
+ void clear() { m_size = 0; }
+ void free_all() { free_tail(0); }
+ void free_tail(unsigned size);
+ void add(const T& val);
+ void push_back(const T& val) { add(val); }
+ void modify_last(const T& val);
+ void remove_last();
+
+ int allocate_continuous_block(unsigned num_elements);
+
+ void add_array(const T* ptr, unsigned num_elem)
+ {
+ while(num_elem--)
+ {
+ add(*ptr++);
+ }
+ }
+
+ template<class DataAccessor> void add_data(DataAccessor& data)
+ {
+ while(data.size())
+ {
+ add(*data);
+ ++data;
+ }
+ }
+
+ void cut_at(unsigned size)
+ {
+ if(size < m_size) m_size = size;
+ }
+
+ unsigned size() const { return m_size; }
+
+ const T& operator [] (unsigned i) const
+ {
+ return m_blocks[i >> block_shift][i & block_mask];
+ }
+
+ T& operator [] (unsigned i)
+ {
+ return m_blocks[i >> block_shift][i & block_mask];
+ }
+
+ const T& at(unsigned i) const
+ {
+ return m_blocks[i >> block_shift][i & block_mask];
+ }
+
+ T& at(unsigned i)
+ {
+ return m_blocks[i >> block_shift][i & block_mask];
+ }
+
+ T value_at(unsigned i) const
+ {
+ return m_blocks[i >> block_shift][i & block_mask];
+ }
+
+ const T& curr(unsigned idx) const
+ {
+ return (*this)[idx];
+ }
+
+ T& curr(unsigned idx)
+ {
+ return (*this)[idx];
+ }
+
+ const T& prev(unsigned idx) const
+ {
+ return (*this)[(idx + m_size - 1) % m_size];
+ }
+
+ T& prev(unsigned idx)
+ {
+ return (*this)[(idx + m_size - 1) % m_size];
+ }
+
+ const T& next(unsigned idx) const
+ {
+ return (*this)[(idx + 1) % m_size];
+ }
+
+ T& next(unsigned idx)
+ {
+ return (*this)[(idx + 1) % m_size];
+ }
+
+ const T& last() const
+ {
+ return (*this)[m_size - 1];
+ }
+
+ T& last()
+ {
+ return (*this)[m_size - 1];
+ }
+
+ unsigned byte_size() const;
+ void serialize(int8u* ptr) const;
+ void deserialize(const int8u* data, unsigned byte_size);
+ void deserialize(unsigned start, const T& empty_val,
+ const int8u* data, unsigned byte_size);
+
+ template<class ByteAccessor>
+ void deserialize(ByteAccessor data)
+ {
+ remove_all();
+ unsigned elem_size = data.size() / sizeof(T);
+
+ for(unsigned i = 0; i < elem_size; ++i)
+ {
+ int8u* ptr = (int8u*)data_ptr();
+ for(unsigned j = 0; j < sizeof(T); ++j)
+ {
+ *ptr++ = *data;
+ ++data;
+ }
+ ++m_size;
+ }
+ }
+
+ template<class ByteAccessor>
+ void deserialize(unsigned start, const T& empty_val, ByteAccessor data)
+ {
+ while(m_size < start)
+ {
+ add(empty_val);
+ }
+
+ unsigned elem_size = data.size() / sizeof(T);
+ for(unsigned i = 0; i < elem_size; ++i)
+ {
+ int8u* ptr;
+ if(start + i < m_size)
+ {
+ ptr = (int8u*)(&((*this)[start + i]));
+ }
+ else
+ {
+ ptr = (int8u*)data_ptr();
+ ++m_size;
+ }
+ for(unsigned j = 0; j < sizeof(T); ++j)
+ {
+ *ptr++ = *data;
+ ++data;
+ }
+ }
+ }
+
+ const T* block(unsigned nb) const { return m_blocks[nb]; }
+
+ private:
+ void allocate_block(unsigned nb);
+ T* data_ptr();
+
+ unsigned m_size;
+ unsigned m_num_blocks;
+ unsigned m_max_blocks;
+ T** m_blocks;
+ unsigned m_block_ptr_inc;
+ };
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S> pod_bvector<T, S>::~pod_bvector()
+ {
+ if(m_num_blocks)
+ {
+ T** blk = m_blocks + m_num_blocks - 1;
+ while(m_num_blocks--)
+ {
+ pod_allocator<T>::deallocate(*blk, block_size);
+ --blk;
+ }
+ }
+ pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void pod_bvector<T, S>::free_tail(unsigned size)
+ {
+ if(size < m_size)
+ {
+ unsigned nb = (size + block_mask) >> block_shift;
+ while(m_num_blocks > nb)
+ {
+ pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size);
+ }
+ if(m_num_blocks == 0)
+ {
+ pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
+ m_blocks = 0;
+ m_max_blocks = 0;
+ }
+ m_size = size;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S> pod_bvector<T, S>::pod_bvector() :
+ m_size(0),
+ m_num_blocks(0),
+ m_max_blocks(0),
+ m_blocks(0),
+ m_block_ptr_inc(block_size)
+ {
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ pod_bvector<T, S>::pod_bvector(unsigned block_ptr_inc) :
+ m_size(0),
+ m_num_blocks(0),
+ m_max_blocks(0),
+ m_blocks(0),
+ m_block_ptr_inc(block_ptr_inc)
+ {
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ pod_bvector<T, S>::pod_bvector(const pod_bvector<T, S>& v) :
+ m_size(v.m_size),
+ m_num_blocks(v.m_num_blocks),
+ m_max_blocks(v.m_max_blocks),
+ m_blocks(v.m_max_blocks ?
+ pod_allocator<T*>::allocate(v.m_max_blocks) :
+ 0),
+ m_block_ptr_inc(v.m_block_ptr_inc)
+ {
+ unsigned i;
+ for(i = 0; i < v.m_num_blocks; ++i)
+ {
+ m_blocks[i] = pod_allocator<T>::allocate(block_size);
+ memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ const pod_bvector<T, S>&
+ pod_bvector<T, S>::operator = (const pod_bvector<T, S>& v)
+ {
+ unsigned i;
+ for(i = m_num_blocks; i < v.m_num_blocks; ++i)
+ {
+ allocate_block(i);
+ }
+ for(i = 0; i < v.m_num_blocks; ++i)
+ {
+ memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
+ }
+ m_size = v.m_size;
+ return *this;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void pod_bvector<T, S>::allocate_block(unsigned nb)
+ {
+ if(nb >= m_max_blocks)
+ {
+ T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc);
+
+ if(m_blocks)
+ {
+ memcpy(new_blocks,
+ m_blocks,
+ m_num_blocks * sizeof(T*));
+
+ pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
+ }
+ m_blocks = new_blocks;
+ m_max_blocks += m_block_ptr_inc;
+ }
+ m_blocks[nb] = pod_allocator<T>::allocate(block_size);
+ m_num_blocks++;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ inline T* pod_bvector<T, S>::data_ptr()
+ {
+ unsigned nb = m_size >> block_shift;
+ if(nb >= m_num_blocks)
+ {
+ allocate_block(nb);
+ }
+ return m_blocks[nb] + (m_size & block_mask);
+ }
+
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ inline void pod_bvector<T, S>::add(const T& val)
+ {
+ *data_ptr() = val;
+ ++m_size;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ inline void pod_bvector<T, S>::remove_last()
+ {
+ if(m_size) --m_size;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void pod_bvector<T, S>::modify_last(const T& val)
+ {
+ remove_last();
+ add(val);
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ int pod_bvector<T, S>::allocate_continuous_block(unsigned num_elements)
+ {
+ if(num_elements < block_size)
+ {
+ data_ptr(); // Allocate initial block if necessary
+ unsigned rest = block_size - (m_size & block_mask);
+ unsigned index;
+ if(num_elements <= rest)
+ {
+ // The rest of the block is good, we can use it
+ //-----------------
+ index = m_size;
+ m_size += num_elements;
+ return index;
+ }
+
+ // New block
+ //---------------
+ m_size += rest;
+ data_ptr();
+ index = m_size;
+ m_size += num_elements;
+ return index;
+ }
+ return -1; // Impossible to allocate
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ unsigned pod_bvector<T, S>::byte_size() const
+ {
+ return m_size * sizeof(T);
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void pod_bvector<T, S>::serialize(int8u* ptr) const
+ {
+ unsigned i;
+ for(i = 0; i < m_size; i++)
+ {
+ memcpy(ptr, &(*this)[i], sizeof(T));
+ ptr += sizeof(T);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void pod_bvector<T, S>::deserialize(const int8u* data, unsigned byte_size)
+ {
+ remove_all();
+ byte_size /= sizeof(T);
+ for(unsigned i = 0; i < byte_size; ++i)
+ {
+ T* ptr = data_ptr();
+ memcpy(ptr, data, sizeof(T));
+ ++m_size;
+ data += sizeof(T);
+ }
+ }
+
+
+ // Replace or add a number of elements starting from "start" position
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void pod_bvector<T, S>::deserialize(unsigned start, const T& empty_val,
+ const int8u* data, unsigned byte_size)
+ {
+ while(m_size < start)
+ {
+ add(empty_val);
+ }
+
+ byte_size /= sizeof(T);
+ for(unsigned i = 0; i < byte_size; ++i)
+ {
+ if(start + i < m_size)
+ {
+ memcpy(&((*this)[start + i]), data, sizeof(T));
+ }
+ else
+ {
+ T* ptr = data_ptr();
+ memcpy(ptr, data, sizeof(T));
+ ++m_size;
+ }
+ data += sizeof(T);
+ }
+ }
+
+
+ //---------------------------------------------------------block_allocator
+ // Allocator for arbitrary POD data. Most usable in different cache
+ // systems for efficient memory allocations.
+ // Memory is allocated with blocks of fixed size ("block_size" in
+ // the constructor). If required size exceeds the block size the allocator
+ // creates a new block of the required size. However, the most efficient
+ // use is when the average reqired size is much less than the block size.
+ //------------------------------------------------------------------------
+ class block_allocator
+ {
+ struct block_type
+ {
+ int8u* data;
+ unsigned size;
+ };
+
+ public:
+ void remove_all()
+ {
+ if(m_num_blocks)
+ {
+ block_type* blk = m_blocks + m_num_blocks - 1;
+ while(m_num_blocks--)
+ {
+ pod_allocator<int8u>::deallocate(blk->data, blk->size);
+ --blk;
+ }
+ pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
+ }
+ m_num_blocks = 0;
+ m_max_blocks = 0;
+ m_blocks = 0;
+ m_buf_ptr = 0;
+ m_rest = 0;
+ }
+
+ ~block_allocator()
+ {
+ remove_all();
+ }
+
+ block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
+ m_block_size(block_size),
+ m_block_ptr_inc(block_ptr_inc),
+ m_num_blocks(0),
+ m_max_blocks(0),
+ m_blocks(0),
+ m_buf_ptr(0),
+ m_rest(0)
+ {
+ }
+
+
+ int8u* allocate(unsigned size, unsigned alignment=1)
+ {
+ if(size == 0) return 0;
+ if(size <= m_rest)
+ {
+ int8u* ptr = m_buf_ptr;
+ if(alignment > 1)
+ {
+ unsigned align =
+ (alignment - unsigned((size_t)ptr) % alignment) % alignment;
+
+ size += align;
+ ptr += align;
+ if(size <= m_rest)
+ {
+ m_rest -= size;
+ m_buf_ptr += size;
+ return ptr;
+ }
+ allocate_block(size);
+ return allocate(size - align, alignment);
+ }
+ m_rest -= size;
+ m_buf_ptr += size;
+ return ptr;
+ }
+ allocate_block(size + alignment - 1);
+ return allocate(size, alignment);
+ }
+
+
+ private:
+ void allocate_block(unsigned size)
+ {
+ if(size < m_block_size) size = m_block_size;
+ if(m_num_blocks >= m_max_blocks)
+ {
+ block_type* new_blocks =
+ pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc);
+
+ if(m_blocks)
+ {
+ memcpy(new_blocks,
+ m_blocks,
+ m_num_blocks * sizeof(block_type));
+ pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
+ }
+ m_blocks = new_blocks;
+ m_max_blocks += m_block_ptr_inc;
+ }
+
+ m_blocks[m_num_blocks].size = size;
+ m_blocks[m_num_blocks].data =
+ m_buf_ptr =
+ pod_allocator<int8u>::allocate(size);
+
+ m_num_blocks++;
+ m_rest = size;
+ }
+
+ unsigned m_block_size;
+ unsigned m_block_ptr_inc;
+ unsigned m_num_blocks;
+ unsigned m_max_blocks;
+ block_type* m_blocks;
+ int8u* m_buf_ptr;
+ unsigned m_rest;
+ };
+
+
+
+
+
+
+
+
+ //------------------------------------------------------------------------
+ enum quick_sort_threshold_e
+ {
+ quick_sort_threshold = 9
+ };
+
+
+ //-----------------------------------------------------------swap_elements
+ template<class T> inline void swap_elements(T& a, T& b)
+ {
+ T temp = a;
+ a = b;
+ b = temp;
+ }
+
+
+ //--------------------------------------------------------------quick_sort
+ template<class Array, class Less>
+ void quick_sort(Array& arr, Less less)
+ {
+ if(arr.size() < 2) return;
+
+ typename Array::value_type* e1;
+ typename Array::value_type* e2;
+
+ int stack[80];
+ int* top = stack;
+ int limit = arr.size();
+ int base = 0;
+
+ for(;;)
+ {
+ int len = limit - base;
+
+ int i;
+ int j;
+ int pivot;
+
+ if(len > quick_sort_threshold)
+ {
+ // we use base + len/2 as the pivot
+ pivot = base + len / 2;
+ swap_elements(arr[base], arr[pivot]);
+
+ i = base + 1;
+ j = limit - 1;
+
+ // now ensure that *i <= *base <= *j
+ e1 = &(arr[j]);
+ e2 = &(arr[i]);
+ if(less(*e1, *e2)) swap_elements(*e1, *e2);
+
+ e1 = &(arr[base]);
+ e2 = &(arr[i]);
+ if(less(*e1, *e2)) swap_elements(*e1, *e2);
+
+ e1 = &(arr[j]);
+ e2 = &(arr[base]);
+ if(less(*e1, *e2)) swap_elements(*e1, *e2);
+
+ for(;;)
+ {
+ do i++; while( less(arr[i], arr[base]) );
+ do j--; while( less(arr[base], arr[j]) );
+
+ if( i > j )
+ {
+ break;
+ }
+
+ swap_elements(arr[i], arr[j]);
+ }
+
+ swap_elements(arr[base], arr[j]);
+
+ // now, push the largest sub-array
+ if(j - base > limit - i)
+ {
+ top[0] = base;
+ top[1] = j;
+ base = i;
+ }
+ else
+ {
+ top[0] = i;
+ top[1] = limit;
+ limit = j;
+ }
+ top += 2;
+ }
+ else
+ {
+ // the sub-array is small, perform insertion sort
+ j = base;
+ i = j + 1;
+
+ for(; i < limit; j = i, i++)
+ {
+ for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--)
+ {
+ swap_elements(*e1, *e2);
+ if(j == base)
+ {
+ break;
+ }
+ }
+ }
+ if(top > stack)
+ {
+ top -= 2;
+ base = top[0];
+ limit = top[1];
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+
+
+
+ //------------------------------------------------------remove_duplicates
+ // Remove duplicates from a sorted array. It doesn't cut the
+ // tail of the array, it just returns the number of remaining elements.
+ //-----------------------------------------------------------------------
+ template<class Array, class Equal>
+ unsigned remove_duplicates(Array& arr, Equal equal)
+ {
+ if(arr.size() < 2) return arr.size();
+
+ unsigned i, j;
+ for(i = 1, j = 1; i < arr.size(); i++)
+ {
+ typename Array::value_type& e = arr[i];
+ if(!equal(e, arr[i - 1]))
+ {
+ arr[j++] = e;
+ }
+ }
+ return j;
+ }
+
+ //--------------------------------------------------------invert_container
+ template<class Array> void invert_container(Array& arr)
+ {
+ int i = 0;
+ int j = arr.size() - 1;
+ while(i < j)
+ {
+ swap_elements(arr[i++], arr[j--]);
+ }
+ }
+
+ //------------------------------------------------------binary_search_pos
+ template<class Array, class Value, class Less>
+ unsigned binary_search_pos(const Array& arr, const Value& val, Less less)
+ {
+ if(arr.size() == 0) return 0;
+
+ unsigned beg = 0;
+ unsigned end = arr.size() - 1;
+
+ if(less(val, arr[0])) return 0;
+ if(less(arr[end], val)) return end + 1;
+
+ while(end - beg > 1)
+ {
+ unsigned mid = (end + beg) >> 1;
+ if(less(val, arr[mid])) end = mid;
+ else beg = mid;
+ }
+
+ //if(beg <= 0 && less(val, arr[0])) return 0;
+ //if(end >= arr.size() - 1 && less(arr[end], val)) ++end;
+
+ return end;
+ }
+
+ //----------------------------------------------------------range_adaptor
+ template<class Array> class range_adaptor
+ {
+ public:
+ typedef typename Array::value_type value_type;
+
+ range_adaptor(Array& array, unsigned start, unsigned size) :
+ m_array(array), m_start(start), m_size(size)
+ {}
+
+ unsigned size() const { return m_size; }
+ const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; }
+ value_type& operator [] (unsigned i) { return m_array[m_start + i]; }
+ const value_type& at(unsigned i) const { return m_array[m_start + i]; }
+ value_type& at(unsigned i) { return m_array[m_start + i]; }
+ value_type value_at(unsigned i) const { return m_array[m_start + i]; }
+
+ private:
+ Array& m_array;
+ unsigned m_start;
+ unsigned m_size;
+ };
+
+ //---------------------------------------------------------------int_less
+ inline bool int_less(int a, int b) { return a < b; }
+
+ //------------------------------------------------------------int_greater
+ inline bool int_greater(int a, int b) { return a > b; }
+
+ //----------------------------------------------------------unsigned_less
+ inline bool unsigned_less(unsigned a, unsigned b) { return a < b; }
+
+ //-------------------------------------------------------unsigned_greater
+ inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; }
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_arrowhead.h b/plugins/Clist_ng/AGG/include/agg_arrowhead.h new file mode 100644 index 0000000000..9c7c97c63a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_arrowhead.h @@ -0,0 +1,88 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_ARROWHEAD_INCLUDED
+#define AGG_ARROWHEAD_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //===============================================================arrowhead
+ //
+ // See implementation agg_arrowhead.cpp
+ //
+ class arrowhead
+ {
+ public:
+ arrowhead();
+
+ void head(double d1, double d2, double d3, double d4)
+ {
+ m_head_d1 = d1;
+ m_head_d2 = d2;
+ m_head_d3 = d3;
+ m_head_d4 = d4;
+ m_head_flag = true;
+ }
+
+ void head() { m_head_flag = true; }
+ void no_head() { m_head_flag = false; }
+
+ void tail(double d1, double d2, double d3, double d4)
+ {
+ m_tail_d1 = d1;
+ m_tail_d2 = d2;
+ m_tail_d3 = d3;
+ m_tail_d4 = d4;
+ m_tail_flag = true;
+ }
+
+ void tail() { m_tail_flag = true; }
+ void no_tail() { m_tail_flag = false; }
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ double m_head_d1;
+ double m_head_d2;
+ double m_head_d3;
+ double m_head_d4;
+ double m_tail_d1;
+ double m_tail_d2;
+ double m_tail_d3;
+ double m_tail_d4;
+ bool m_head_flag;
+ bool m_tail_flag;
+ double m_coord[16];
+ unsigned m_cmd[8];
+ unsigned m_curr_id;
+ unsigned m_curr_coord;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_basics.h b/plugins/Clist_ng/AGG/include/agg_basics.h new file mode 100644 index 0000000000..f673863b4a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_basics.h @@ -0,0 +1,539 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_BASICS_INCLUDED
+#define AGG_BASICS_INCLUDED
+
+#include <math.h>
+#include "agg_config.h"
+
+//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
+#ifdef AGG_CUSTOM_ALLOCATOR
+#include "agg_allocator.h"
+#else
+namespace agg
+{
+ // The policy of all AGG containers and memory allocation strategy
+ // in general is that no allocated data requires explicit construction.
+ // It means that the allocator can be really simple; you can even
+ // replace new/delete to malloc/free. The constructors and destructors
+ // won't be called in this case, however everything will remain working.
+ // The second argument of deallocate() is the size of the allocated
+ // block. You can use this information if you wish.
+ //------------------------------------------------------------pod_allocator
+ template<class T> struct pod_allocator
+ {
+ static T* allocate(unsigned num) { return new T [num]; }
+ static void deallocate(T* ptr, unsigned) { delete [] ptr; }
+ };
+
+ // Single object allocator. It's also can be replaced with your custom
+ // allocator. The difference is that it can only allocate a single
+ // object and the constructor and destructor must be called.
+ // In AGG there is no need to allocate an array of objects with
+ // calling their constructors (only single ones). So that, if you
+ // replace these new/delete to malloc/free make sure that the in-place
+ // new is called and take care of calling the destructor too.
+ //------------------------------------------------------------obj_allocator
+ template<class T> struct obj_allocator
+ {
+ static T* allocate() { return new T; }
+ static void deallocate(T* ptr) { delete ptr; }
+ };
+}
+#endif
+
+
+//-------------------------------------------------------- Default basic types
+//
+// If the compiler has different capacity of the basic types you can redefine
+// them via the compiler command line or by generating agg_config.h that is
+// empty by default.
+//
+#ifndef AGG_INT8
+#define AGG_INT8 signed char
+#endif
+
+#ifndef AGG_INT8U
+#define AGG_INT8U unsigned char
+#endif
+
+#ifndef AGG_INT16
+#define AGG_INT16 short
+#endif
+
+#ifndef AGG_INT16U
+#define AGG_INT16U unsigned short
+#endif
+
+#ifndef AGG_INT32
+#define AGG_INT32 int
+#endif
+
+#ifndef AGG_INT32U
+#define AGG_INT32U unsigned
+#endif
+
+#ifndef AGG_INT64
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define AGG_INT64 signed __int64
+#else
+#define AGG_INT64 signed long long
+#endif
+#endif
+
+#ifndef AGG_INT64U
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define AGG_INT64U unsigned __int64
+#else
+#define AGG_INT64U unsigned long long
+#endif
+#endif
+
+//------------------------------------------------ Some fixes for MS Visual C++
+#if defined(_MSC_VER)
+#pragma warning(disable:4786) // Identifier was truncated...
+#endif
+
+#if defined(_MSC_VER)
+#define AGG_INLINE __forceinline
+#else
+#define AGG_INLINE inline
+#endif
+
+namespace agg
+{
+ //-------------------------------------------------------------------------
+ typedef AGG_INT8 int8; //----int8
+ typedef AGG_INT8U int8u; //----int8u
+ typedef AGG_INT16 int16; //----int16
+ typedef AGG_INT16U int16u; //----int16u
+ typedef AGG_INT32 int32; //----int32
+ typedef AGG_INT32U int32u; //----int32u
+ typedef AGG_INT64 int64; //----int64
+ typedef AGG_INT64U int64u; //----int64u
+
+#if defined(AGG_FISTP)
+#pragma warning(push)
+#pragma warning(disable : 4035) //Disable warning "no return value"
+ AGG_INLINE int iround(double v) //-------iround
+ {
+ int t;
+ __asm fld qword ptr [v]
+ __asm fistp dword ptr [t]
+ __asm mov eax, dword ptr [t]
+ }
+ AGG_INLINE unsigned uround(double v) //-------uround
+ {
+ unsigned t;
+ __asm fld qword ptr [v]
+ __asm fistp dword ptr [t]
+ __asm mov eax, dword ptr [t]
+ }
+#pragma warning(pop)
+ AGG_INLINE unsigned ufloor(double v) //-------ufloor
+ {
+ return unsigned(floor(v));
+ }
+ AGG_INLINE unsigned uceil(double v) //--------uceil
+ {
+ return unsigned(ceil(v));
+ }
+#elif defined(AGG_QIFIST)
+ AGG_INLINE int iround(double v)
+ {
+ return int(v);
+ }
+ AGG_INLINE int uround(double v)
+ {
+ return unsigned(v);
+ }
+ AGG_INLINE unsigned ufloor(double v)
+ {
+ return unsigned(floor(v));
+ }
+ AGG_INLINE unsigned uceil(double v)
+ {
+ return unsigned(ceil(v));
+ }
+#else
+ AGG_INLINE int iround(double v)
+ {
+ return int((v < 0.0) ? v - 0.5 : v + 0.5);
+ }
+ AGG_INLINE int uround(double v)
+ {
+ return unsigned(v + 0.5);
+ }
+ AGG_INLINE unsigned ufloor(double v)
+ {
+ return unsigned(v);
+ }
+ AGG_INLINE unsigned uceil(double v)
+ {
+ return unsigned(ceil(v));
+ }
+#endif
+
+ //---------------------------------------------------------------saturation
+ template<int Limit> struct saturation
+ {
+ AGG_INLINE static int iround(double v)
+ {
+ if(v < double(-Limit)) return -Limit;
+ if(v > double( Limit)) return Limit;
+ return agg::iround(v);
+ }
+ };
+
+ //------------------------------------------------------------------mul_one
+ template<unsigned Shift> struct mul_one
+ {
+ AGG_INLINE static unsigned mul(unsigned a, unsigned b)
+ {
+ register unsigned q = a * b + (1 << (Shift-1));
+ return (q + (q >> Shift)) >> Shift;
+ }
+ };
+
+ //-------------------------------------------------------------------------
+ typedef unsigned char cover_type; //----cover_type
+ enum cover_scale_e
+ {
+ cover_shift = 8, //----cover_shift
+ cover_size = 1 << cover_shift, //----cover_size
+ cover_mask = cover_size - 1, //----cover_mask
+ cover_none = 0, //----cover_none
+ cover_full = cover_mask //----cover_full
+ };
+
+ //----------------------------------------------------poly_subpixel_scale_e
+ // These constants determine the subpixel accuracy, to be more precise,
+ // the number of bits of the fractional part of the coordinates.
+ // The possible coordinate capacity in bits can be calculated by formula:
+ // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
+ // 8-bits fractional part the capacity is 24 bits.
+ enum poly_subpixel_scale_e
+ {
+ poly_subpixel_shift = 8, //----poly_subpixel_shift
+ poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
+ poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask
+ };
+
+ //----------------------------------------------------------filling_rule_e
+ enum filling_rule_e
+ {
+ fill_non_zero,
+ fill_even_odd
+ };
+
+ //-----------------------------------------------------------------------pi
+ const double pi = 3.14159265358979323846;
+
+ //------------------------------------------------------------------deg2rad
+ inline double deg2rad(double deg)
+ {
+ return deg * pi / 180.0;
+ }
+
+ //------------------------------------------------------------------rad2deg
+ inline double rad2deg(double rad)
+ {
+ return rad * 180.0 / pi;
+ }
+
+ //----------------------------------------------------------------rect_base
+ template<class T> struct rect_base
+ {
+ typedef T value_type;
+ typedef rect_base<T> self_type;
+ T x1, y1, x2, y2;
+
+ rect_base() {}
+ rect_base(T x1_, T y1_, T x2_, T y2_) :
+ x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
+
+ void init(T x1_, T y1_, T x2_, T y2_)
+ {
+ x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
+ }
+
+ const self_type& normalize()
+ {
+ T t;
+ if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
+ if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
+ return *this;
+ }
+
+ bool clip(const self_type& r)
+ {
+ if(x2 > r.x2) x2 = r.x2;
+ if(y2 > r.y2) y2 = r.y2;
+ if(x1 < r.x1) x1 = r.x1;
+ if(y1 < r.y1) y1 = r.y1;
+ return x1 <= x2 && y1 <= y2;
+ }
+
+ bool is_valid() const
+ {
+ return x1 <= x2 && y1 <= y2;
+ }
+
+ bool hit_test(T x, T y) const
+ {
+ return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
+ }
+ };
+
+ //-----------------------------------------------------intersect_rectangles
+ template<class Rect>
+ inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
+ {
+ Rect r = r1;
+
+ // First process x2,y2 because the other order
+ // results in Internal Compiler Error under
+ // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
+ // case of "Maximize Speed" optimization option.
+ //-----------------
+ if(r.x2 > r2.x2) r.x2 = r2.x2;
+ if(r.y2 > r2.y2) r.y2 = r2.y2;
+ if(r.x1 < r2.x1) r.x1 = r2.x1;
+ if(r.y1 < r2.y1) r.y1 = r2.y1;
+ return r;
+ }
+
+
+ //---------------------------------------------------------unite_rectangles
+ template<class Rect>
+ inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
+ {
+ Rect r = r1;
+ if(r.x2 < r2.x2) r.x2 = r2.x2;
+ if(r.y2 < r2.y2) r.y2 = r2.y2;
+ if(r.x1 > r2.x1) r.x1 = r2.x1;
+ if(r.y1 > r2.y1) r.y1 = r2.y1;
+ return r;
+ }
+
+ typedef rect_base<int> rect_i; //----rect_i
+ typedef rect_base<float> rect_f; //----rect_f
+ typedef rect_base<double> rect_d; //----rect_d
+
+ //---------------------------------------------------------path_commands_e
+ enum path_commands_e
+ {
+ path_cmd_stop = 0, //----path_cmd_stop
+ path_cmd_move_to = 1, //----path_cmd_move_to
+ path_cmd_line_to = 2, //----path_cmd_line_to
+ path_cmd_curve3 = 3, //----path_cmd_curve3
+ path_cmd_curve4 = 4, //----path_cmd_curve4
+ path_cmd_curveN = 5, //----path_cmd_curveN
+ path_cmd_catrom = 6, //----path_cmd_catrom
+ path_cmd_ubspline = 7, //----path_cmd_ubspline
+ path_cmd_end_poly = 0x0F, //----path_cmd_end_poly
+ path_cmd_mask = 0x0F //----path_cmd_mask
+ };
+
+ //------------------------------------------------------------path_flags_e
+ enum path_flags_e
+ {
+ path_flags_none = 0, //----path_flags_none
+ path_flags_ccw = 0x10, //----path_flags_ccw
+ path_flags_cw = 0x20, //----path_flags_cw
+ path_flags_close = 0x40, //----path_flags_close
+ path_flags_mask = 0xF0 //----path_flags_mask
+ };
+
+ //---------------------------------------------------------------is_vertex
+ inline bool is_vertex(unsigned c)
+ {
+ return c >= path_cmd_move_to && c < path_cmd_end_poly;
+ }
+
+ //--------------------------------------------------------------is_drawing
+ inline bool is_drawing(unsigned c)
+ {
+ return c >= path_cmd_line_to && c < path_cmd_end_poly;
+ }
+
+ //-----------------------------------------------------------------is_stop
+ inline bool is_stop(unsigned c)
+ {
+ return c == path_cmd_stop;
+ }
+
+ //--------------------------------------------------------------is_move_to
+ inline bool is_move_to(unsigned c)
+ {
+ return c == path_cmd_move_to;
+ }
+
+ //--------------------------------------------------------------is_line_to
+ inline bool is_line_to(unsigned c)
+ {
+ return c == path_cmd_line_to;
+ }
+
+ //----------------------------------------------------------------is_curve
+ inline bool is_curve(unsigned c)
+ {
+ return c == path_cmd_curve3 || c == path_cmd_curve4;
+ }
+
+ //---------------------------------------------------------------is_curve3
+ inline bool is_curve3(unsigned c)
+ {
+ return c == path_cmd_curve3;
+ }
+
+ //---------------------------------------------------------------is_curve4
+ inline bool is_curve4(unsigned c)
+ {
+ return c == path_cmd_curve4;
+ }
+
+ //-------------------------------------------------------------is_end_poly
+ inline bool is_end_poly(unsigned c)
+ {
+ return (c & path_cmd_mask) == path_cmd_end_poly;
+ }
+
+ //----------------------------------------------------------------is_close
+ inline bool is_close(unsigned c)
+ {
+ return (c & ~(path_flags_cw | path_flags_ccw)) ==
+ (path_cmd_end_poly | path_flags_close);
+ }
+
+ //------------------------------------------------------------is_next_poly
+ inline bool is_next_poly(unsigned c)
+ {
+ return is_stop(c) || is_move_to(c) || is_end_poly(c);
+ }
+
+ //-------------------------------------------------------------------is_cw
+ inline bool is_cw(unsigned c)
+ {
+ return (c & path_flags_cw) != 0;
+ }
+
+ //------------------------------------------------------------------is_ccw
+ inline bool is_ccw(unsigned c)
+ {
+ return (c & path_flags_ccw) != 0;
+ }
+
+ //-------------------------------------------------------------is_oriented
+ inline bool is_oriented(unsigned c)
+ {
+ return (c & (path_flags_cw | path_flags_ccw)) != 0;
+ }
+
+ //---------------------------------------------------------------is_closed
+ inline bool is_closed(unsigned c)
+ {
+ return (c & path_flags_close) != 0;
+ }
+
+ //----------------------------------------------------------get_close_flag
+ inline unsigned get_close_flag(unsigned c)
+ {
+ return c & path_flags_close;
+ }
+
+ //-------------------------------------------------------clear_orientation
+ inline unsigned clear_orientation(unsigned c)
+ {
+ return c & ~(path_flags_cw | path_flags_ccw);
+ }
+
+ //---------------------------------------------------------get_orientation
+ inline unsigned get_orientation(unsigned c)
+ {
+ return c & (path_flags_cw | path_flags_ccw);
+ }
+
+ //---------------------------------------------------------set_orientation
+ inline unsigned set_orientation(unsigned c, unsigned o)
+ {
+ return clear_orientation(c) | o;
+ }
+
+ //--------------------------------------------------------------point_base
+ template<class T> struct point_base
+ {
+ typedef T value_type;
+ T x,y;
+ point_base() {}
+ point_base(T x_, T y_) : x(x_), y(y_) {}
+ };
+ typedef point_base<int> point_i; //-----point_i
+ typedef point_base<float> point_f; //-----point_f
+ typedef point_base<double> point_d; //-----point_d
+
+ //-------------------------------------------------------------vertex_base
+ template<class T> struct vertex_base
+ {
+ typedef T value_type;
+ T x,y;
+ unsigned cmd;
+ vertex_base() {}
+ vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
+ };
+ typedef vertex_base<int> vertex_i; //-----vertex_i
+ typedef vertex_base<float> vertex_f; //-----vertex_f
+ typedef vertex_base<double> vertex_d; //-----vertex_d
+
+ //----------------------------------------------------------------row_info
+ template<class T> struct row_info
+ {
+ int x1, x2;
+ T* ptr;
+ row_info() {}
+ row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
+ };
+
+ //----------------------------------------------------------const_row_info
+ template<class T> struct const_row_info
+ {
+ int x1, x2;
+ const T* ptr;
+ const_row_info() {}
+ const_row_info(int x1_, int x2_, const T* ptr_) :
+ x1(x1_), x2(x2_), ptr(ptr_) {}
+ };
+
+ //------------------------------------------------------------is_equal_eps
+ template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
+ {
+ return fabs(v1 - v2) <= double(epsilon);
+ }
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_bezier_arc.h b/plugins/Clist_ng/AGG/include/agg_bezier_arc.h new file mode 100644 index 0000000000..faca7b6912 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_bezier_arc.h @@ -0,0 +1,163 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_BEZIER_ARC_INCLUDED
+#define AGG_BEZIER_ARC_INCLUDED
+
+#include "agg_conv_transform.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------------------------------
+ void arc_to_bezier(double cx, double cy, double rx, double ry,
+ double start_angle, double sweep_angle,
+ double* curve);
+
+
+ //==============================================================bezier_arc
+ //
+ // See implemantaion agg_bezier_arc.cpp
+ //
+ class bezier_arc
+ {
+ public:
+ //--------------------------------------------------------------------
+ bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
+ bezier_arc(double x, double y,
+ double rx, double ry,
+ double start_angle,
+ double sweep_angle)
+ {
+ init(x, y, rx, ry, start_angle, sweep_angle);
+ }
+
+ //--------------------------------------------------------------------
+ void init(double x, double y,
+ double rx, double ry,
+ double start_angle,
+ double sweep_angle);
+
+ //--------------------------------------------------------------------
+ void rewind(unsigned)
+ {
+ m_vertex = 0;
+ }
+
+ //--------------------------------------------------------------------
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_vertex >= m_num_vertices) return path_cmd_stop;
+ *x = m_vertices[m_vertex];
+ *y = m_vertices[m_vertex + 1];
+ m_vertex += 2;
+ return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
+ }
+
+ // Supplemantary functions. num_vertices() actually returns doubled
+ // number of vertices. That is, for 1 vertex it returns 2.
+ //--------------------------------------------------------------------
+ unsigned num_vertices() const { return m_num_vertices; }
+ const double* vertices() const { return m_vertices; }
+ double* vertices() { return m_vertices; }
+
+ private:
+ unsigned m_vertex;
+ unsigned m_num_vertices;
+ double m_vertices[26];
+ unsigned m_cmd;
+ };
+
+
+
+ //==========================================================bezier_arc_svg
+ // Compute an SVG-style bezier arc.
+ //
+ // Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
+ // orientation of the ellipse are defined by two radii (rx, ry)
+ // and an x-axis-rotation, which indicates how the ellipse as a whole
+ // is rotated relative to the current coordinate system. The center
+ // (cx, cy) of the ellipse is calculated automatically to satisfy the
+ // constraints imposed by the other parameters.
+ // large-arc-flag and sweep-flag contribute to the automatic calculations
+ // and help determine how the arc is drawn.
+ class bezier_arc_svg
+ {
+ public:
+ //--------------------------------------------------------------------
+ bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
+
+ bezier_arc_svg(double x1, double y1,
+ double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double x2, double y2) :
+ m_arc(), m_radii_ok(false)
+ {
+ init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
+ }
+
+ //--------------------------------------------------------------------
+ void init(double x1, double y1,
+ double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double x2, double y2);
+
+ //--------------------------------------------------------------------
+ bool radii_ok() const { return m_radii_ok; }
+
+ //--------------------------------------------------------------------
+ void rewind(unsigned)
+ {
+ m_arc.rewind(0);
+ }
+
+ //--------------------------------------------------------------------
+ unsigned vertex(double* x, double* y)
+ {
+ return m_arc.vertex(x, y);
+ }
+
+ // Supplemantary functions. num_vertices() actually returns doubled
+ // number of vertices. That is, for 1 vertex it returns 2.
+ //--------------------------------------------------------------------
+ unsigned num_vertices() const { return m_arc.num_vertices(); }
+ const double* vertices() const { return m_arc.vertices(); }
+ double* vertices() { return m_arc.vertices(); }
+
+ private:
+ bezier_arc m_arc;
+ bool m_radii_ok;
+ };
+
+
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_bitset_iterator.h b/plugins/Clist_ng/AGG/include/agg_bitset_iterator.h new file mode 100644 index 0000000000..1337f78195 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_bitset_iterator.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_BITSET_ITERATOR_INCLUDED
+#define AGG_BITSET_ITERATOR_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ class bitset_iterator
+ {
+ public:
+ bitset_iterator(const int8u* bits, unsigned offset = 0) :
+ m_bits(bits + (offset >> 3)),
+ m_mask(0x80 >> (offset & 7))
+ {}
+
+ void operator ++ ()
+ {
+ m_mask >>= 1;
+ if(m_mask == 0)
+ {
+ ++m_bits;
+ m_mask = 0x80;
+ }
+ }
+
+ unsigned bit() const
+ {
+ return (*m_bits) & m_mask;
+ }
+
+ private:
+ const int8u* m_bits;
+ int8u m_mask;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_blur.h b/plugins/Clist_ng/AGG/include/agg_blur.h new file mode 100644 index 0000000000..26c36a8d2f --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_blur.h @@ -0,0 +1,1303 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// The Stack Blur Algorithm was invented by Mario Klingemann,
+// mario@quasimondo.com and described here:
+// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php
+// (search phrase "Stackblur: Fast But Goodlooking").
+// The major improvement is that there's no more division table
+// that was very expensive to create for large blur radii. Insted,
+// for 8-bit per channel and radius not exceeding 254 the division is
+// replaced by multiplication and shift.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_BLUR_INCLUDED
+#define AGG_BLUR_INCLUDED
+
+#include "agg_array.h"
+#include "agg_pixfmt_transposer.h"
+
+namespace agg
+{
+
+ template<class T> struct stack_blur_tables
+ {
+ static int16u const g_stack_blur8_mul[255];
+ static int8u const g_stack_blur8_shr[255];
+ };
+
+ //------------------------------------------------------------------------
+ template<class T>
+ int16u const stack_blur_tables<T>::g_stack_blur8_mul[255] =
+ {
+ 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
+ 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
+ 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
+ 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
+ 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
+ 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
+ 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
+ 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
+ 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
+ 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
+ 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
+ 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
+ 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
+ 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
+ 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
+ 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
+ };
+
+ //------------------------------------------------------------------------
+ template<class T>
+ int8u const stack_blur_tables<T>::g_stack_blur8_shr[255] =
+ {
+ 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
+ 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
+ };
+
+
+
+ //==============================================================stack_blur
+ template<class ColorT, class CalculatorT> class stack_blur
+ {
+ public:
+ typedef ColorT color_type;
+ typedef CalculatorT calculator_type;
+
+ //--------------------------------------------------------------------
+ template<class Img> void blur_x(Img& img, unsigned radius)
+ {
+ if(radius < 1) return;
+
+ unsigned x, y, xp, i;
+ unsigned stack_ptr;
+ unsigned stack_start;
+
+ color_type pix;
+ color_type* stack_pix;
+ calculator_type sum;
+ calculator_type sum_in;
+ calculator_type sum_out;
+
+ unsigned w = img.width();
+ unsigned h = img.height();
+ unsigned wm = w - 1;
+ unsigned div = radius * 2 + 1;
+
+ unsigned div_sum = (radius + 1) * (radius + 1);
+ unsigned mul_sum = 0;
+ unsigned shr_sum = 0;
+ unsigned max_val = color_type::base_mask;
+
+ if(max_val <= 255 && radius < 255)
+ {
+ mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[radius];
+ shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[radius];
+ }
+
+ m_buf.allocate(w, 128);
+ m_stack.allocate(div, 32);
+
+ for(y = 0; y < h; y++)
+ {
+ sum.clear();
+ sum_in.clear();
+ sum_out.clear();
+
+ pix = img.pixel(0, y);
+ for(i = 0; i <= radius; i++)
+ {
+ m_stack[i] = pix;
+ sum.add(pix, i + 1);
+ sum_out.add(pix);
+ }
+ for(i = 1; i <= radius; i++)
+ {
+ pix = img.pixel((i > wm) ? wm : i, y);
+ m_stack[i + radius] = pix;
+ sum.add(pix, radius + 1 - i);
+ sum_in.add(pix);
+ }
+
+ stack_ptr = radius;
+ for(x = 0; x < w; x++)
+ {
+ if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum);
+ else sum.calc_pix(m_buf[x], div_sum);
+
+ sum.sub(sum_out);
+
+ stack_start = stack_ptr + div - radius;
+ if(stack_start >= div) stack_start -= div;
+ stack_pix = &m_stack[stack_start];
+
+ sum_out.sub(*stack_pix);
+
+ xp = x + radius + 1;
+ if(xp > wm) xp = wm;
+ pix = img.pixel(xp, y);
+
+ *stack_pix = pix;
+
+ sum_in.add(pix);
+ sum.add(sum_in);
+
+ ++stack_ptr;
+ if(stack_ptr >= div) stack_ptr = 0;
+ stack_pix = &m_stack[stack_ptr];
+
+ sum_out.add(*stack_pix);
+ sum_in.sub(*stack_pix);
+ }
+ img.copy_color_hspan(0, y, w, &m_buf[0]);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class Img> void blur_y(Img& img, unsigned radius)
+ {
+ pixfmt_transposer<Img> img2(img);
+ blur_x(img2, radius);
+ }
+
+ //--------------------------------------------------------------------
+ template<class Img> void blur(Img& img, unsigned radius)
+ {
+ blur_x(img, radius);
+ pixfmt_transposer<Img> img2(img);
+ blur_x(img2, radius);
+ }
+
+ private:
+ pod_vector<color_type> m_buf;
+ pod_vector<color_type> m_stack;
+ };
+
+ //====================================================stack_blur_calc_rgba
+ template<class T=unsigned> struct stack_blur_calc_rgba
+ {
+ typedef T value_type;
+ value_type r,g,b,a;
+
+ AGG_INLINE void clear()
+ {
+ r = g = b = a = 0;
+ }
+
+ template<class ArgT> AGG_INLINE void add(const ArgT& v)
+ {
+ r += v.r;
+ g += v.g;
+ b += v.b;
+ a += v.a;
+ }
+
+ template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k)
+ {
+ r += v.r * k;
+ g += v.g * k;
+ b += v.b * k;
+ a += v.a * k;
+ }
+
+ template<class ArgT> AGG_INLINE void sub(const ArgT& v)
+ {
+ r -= v.r;
+ g -= v.g;
+ b -= v.b;
+ a -= v.a;
+ }
+
+ template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div)
+ {
+ typedef typename ArgT::value_type value_type;
+ v.r = value_type(r / div);
+ v.g = value_type(g / div);
+ v.b = value_type(b / div);
+ v.a = value_type(a / div);
+ }
+
+ template<class ArgT>
+ AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr)
+ {
+ typedef typename ArgT::value_type value_type;
+ v.r = value_type((r * mul) >> shr);
+ v.g = value_type((g * mul) >> shr);
+ v.b = value_type((b * mul) >> shr);
+ v.a = value_type((a * mul) >> shr);
+ }
+ };
+
+
+ //=====================================================stack_blur_calc_rgb
+ template<class T=unsigned> struct stack_blur_calc_rgb
+ {
+ typedef T value_type;
+ value_type r,g,b;
+
+ AGG_INLINE void clear()
+ {
+ r = g = b = 0;
+ }
+
+ template<class ArgT> AGG_INLINE void add(const ArgT& v)
+ {
+ r += v.r;
+ g += v.g;
+ b += v.b;
+ }
+
+ template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k)
+ {
+ r += v.r * k;
+ g += v.g * k;
+ b += v.b * k;
+ }
+
+ template<class ArgT> AGG_INLINE void sub(const ArgT& v)
+ {
+ r -= v.r;
+ g -= v.g;
+ b -= v.b;
+ }
+
+ template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div)
+ {
+ typedef typename ArgT::value_type value_type;
+ v.r = value_type(r / div);
+ v.g = value_type(g / div);
+ v.b = value_type(b / div);
+ }
+
+ template<class ArgT>
+ AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr)
+ {
+ typedef typename ArgT::value_type value_type;
+ v.r = value_type((r * mul) >> shr);
+ v.g = value_type((g * mul) >> shr);
+ v.b = value_type((b * mul) >> shr);
+ }
+ };
+
+
+ //====================================================stack_blur_calc_gray
+ template<class T=unsigned> struct stack_blur_calc_gray
+ {
+ typedef T value_type;
+ value_type v;
+
+ AGG_INLINE void clear()
+ {
+ v = 0;
+ }
+
+ template<class ArgT> AGG_INLINE void add(const ArgT& a)
+ {
+ v += a.v;
+ }
+
+ template<class ArgT> AGG_INLINE void add(const ArgT& a, unsigned k)
+ {
+ v += a.v * k;
+ }
+
+ template<class ArgT> AGG_INLINE void sub(const ArgT& a)
+ {
+ v -= a.v;
+ }
+
+ template<class ArgT> AGG_INLINE void calc_pix(ArgT& a, unsigned div)
+ {
+ typedef typename ArgT::value_type value_type;
+ a.v = value_type(v / div);
+ }
+
+ template<class ArgT>
+ AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr)
+ {
+ typedef typename ArgT::value_type value_type;
+ a.v = value_type((v * mul) >> shr);
+ }
+ };
+
+
+
+ //========================================================stack_blur_gray8
+ template<class Img>
+ void stack_blur_gray8(Img& img, unsigned rx, unsigned ry)
+ {
+ unsigned x, y, xp, yp, i;
+ unsigned stack_ptr;
+ unsigned stack_start;
+
+ const int8u* src_pix_ptr;
+ int8u* dst_pix_ptr;
+ unsigned pix;
+ unsigned stack_pix;
+ unsigned sum;
+ unsigned sum_in;
+ unsigned sum_out;
+
+ unsigned w = img.width();
+ unsigned h = img.height();
+ unsigned wm = w - 1;
+ unsigned hm = h - 1;
+
+ unsigned div;
+ unsigned mul_sum;
+ unsigned shr_sum;
+
+ pod_vector<int8u> stack;
+
+ if(rx > 0)
+ {
+ if(rx > 254) rx = 254;
+ div = rx * 2 + 1;
+ mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
+ shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
+ stack.allocate(div);
+
+ for(y = 0; y < h; y++)
+ {
+ sum = sum_in = sum_out = 0;
+
+ src_pix_ptr = img.pix_ptr(0, y);
+ pix = *src_pix_ptr;
+ for(i = 0; i <= rx; i++)
+ {
+ stack[i] = pix;
+ sum += pix * (i + 1);
+ sum_out += pix;
+ }
+ for(i = 1; i <= rx; i++)
+ {
+ if(i <= wm) src_pix_ptr += Img::pix_step;
+ pix = *src_pix_ptr;
+ stack[i + rx] = pix;
+ sum += pix * (rx + 1 - i);
+ sum_in += pix;
+ }
+
+ stack_ptr = rx;
+ xp = rx;
+ if(xp > wm) xp = wm;
+ src_pix_ptr = img.pix_ptr(xp, y);
+ dst_pix_ptr = img.pix_ptr(0, y);
+ for(x = 0; x < w; x++)
+ {
+ *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
+ dst_pix_ptr += Img::pix_step;
+
+ sum -= sum_out;
+
+ stack_start = stack_ptr + div - rx;
+ if(stack_start >= div) stack_start -= div;
+ sum_out -= stack[stack_start];
+
+ if(xp < wm)
+ {
+ src_pix_ptr += Img::pix_step;
+ pix = *src_pix_ptr;
+ ++xp;
+ }
+
+ stack[stack_start] = pix;
+
+ sum_in += pix;
+ sum += sum_in;
+
+ ++stack_ptr;
+ if(stack_ptr >= div) stack_ptr = 0;
+ stack_pix = stack[stack_ptr];
+
+ sum_out += stack_pix;
+ sum_in -= stack_pix;
+ }
+ }
+ }
+
+ if(ry > 0)
+ {
+ if(ry > 254) ry = 254;
+ div = ry * 2 + 1;
+ mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
+ shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
+ stack.allocate(div);
+
+ int stride = img.stride();
+ for(x = 0; x < w; x++)
+ {
+ sum = sum_in = sum_out = 0;
+
+ src_pix_ptr = img.pix_ptr(x, 0);
+ pix = *src_pix_ptr;
+ for(i = 0; i <= ry; i++)
+ {
+ stack[i] = pix;
+ sum += pix * (i + 1);
+ sum_out += pix;
+ }
+ for(i = 1; i <= ry; i++)
+ {
+ if(i <= hm) src_pix_ptr += stride;
+ pix = *src_pix_ptr;
+ stack[i + ry] = pix;
+ sum += pix * (ry + 1 - i);
+ sum_in += pix;
+ }
+
+ stack_ptr = ry;
+ yp = ry;
+ if(yp > hm) yp = hm;
+ src_pix_ptr = img.pix_ptr(x, yp);
+ dst_pix_ptr = img.pix_ptr(x, 0);
+ for(y = 0; y < h; y++)
+ {
+ *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
+ dst_pix_ptr += stride;
+
+ sum -= sum_out;
+
+ stack_start = stack_ptr + div - ry;
+ if(stack_start >= div) stack_start -= div;
+ sum_out -= stack[stack_start];
+
+ if(yp < hm)
+ {
+ src_pix_ptr += stride;
+ pix = *src_pix_ptr;
+ ++yp;
+ }
+
+ stack[stack_start] = pix;
+
+ sum_in += pix;
+ sum += sum_in;
+
+ ++stack_ptr;
+ if(stack_ptr >= div) stack_ptr = 0;
+ stack_pix = stack[stack_ptr];
+
+ sum_out += stack_pix;
+ sum_in -= stack_pix;
+ }
+ }
+ }
+ }
+
+
+
+ //========================================================stack_blur_rgb24
+ template<class Img>
+ void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry)
+ {
+ typedef typename Img::color_type color_type;
+ typedef typename Img::order_type order_type;
+ enum order_e
+ {
+ R = order_type::R,
+ G = order_type::G,
+ B = order_type::B
+ };
+
+ unsigned x, y, xp, yp, i;
+ unsigned stack_ptr;
+ unsigned stack_start;
+
+ const int8u* src_pix_ptr;
+ int8u* dst_pix_ptr;
+ color_type* stack_pix_ptr;
+
+ unsigned sum_r;
+ unsigned sum_g;
+ unsigned sum_b;
+ unsigned sum_in_r;
+ unsigned sum_in_g;
+ unsigned sum_in_b;
+ unsigned sum_out_r;
+ unsigned sum_out_g;
+ unsigned sum_out_b;
+
+ unsigned w = img.width();
+ unsigned h = img.height();
+ unsigned wm = w - 1;
+ unsigned hm = h - 1;
+
+ unsigned div;
+ unsigned mul_sum;
+ unsigned shr_sum;
+
+ pod_vector<color_type> stack;
+
+ if(rx > 0)
+ {
+ if(rx > 254) rx = 254;
+ div = rx * 2 + 1;
+ mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
+ shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
+ stack.allocate(div);
+
+ for(y = 0; y < h; y++)
+ {
+ sum_r =
+ sum_g =
+ sum_b =
+ sum_in_r =
+ sum_in_g =
+ sum_in_b =
+ sum_out_r =
+ sum_out_g =
+ sum_out_b = 0;
+
+ src_pix_ptr = img.pix_ptr(0, y);
+ for(i = 0; i <= rx; i++)
+ {
+ stack_pix_ptr = &stack[i];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ sum_r += src_pix_ptr[R] * (i + 1);
+ sum_g += src_pix_ptr[G] * (i + 1);
+ sum_b += src_pix_ptr[B] * (i + 1);
+ sum_out_r += src_pix_ptr[R];
+ sum_out_g += src_pix_ptr[G];
+ sum_out_b += src_pix_ptr[B];
+ }
+ for(i = 1; i <= rx; i++)
+ {
+ if(i <= wm) src_pix_ptr += Img::pix_width;
+ stack_pix_ptr = &stack[i + rx];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ sum_r += src_pix_ptr[R] * (rx + 1 - i);
+ sum_g += src_pix_ptr[G] * (rx + 1 - i);
+ sum_b += src_pix_ptr[B] * (rx + 1 - i);
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ }
+
+ stack_ptr = rx;
+ xp = rx;
+ if(xp > wm) xp = wm;
+ src_pix_ptr = img.pix_ptr(xp, y);
+ dst_pix_ptr = img.pix_ptr(0, y);
+ for(x = 0; x < w; x++)
+ {
+ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
+ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
+ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
+ dst_pix_ptr += Img::pix_width;
+
+ sum_r -= sum_out_r;
+ sum_g -= sum_out_g;
+ sum_b -= sum_out_b;
+
+ stack_start = stack_ptr + div - rx;
+ if(stack_start >= div) stack_start -= div;
+ stack_pix_ptr = &stack[stack_start];
+
+ sum_out_r -= stack_pix_ptr->r;
+ sum_out_g -= stack_pix_ptr->g;
+ sum_out_b -= stack_pix_ptr->b;
+
+ if(xp < wm)
+ {
+ src_pix_ptr += Img::pix_width;
+ ++xp;
+ }
+
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ sum_r += sum_in_r;
+ sum_g += sum_in_g;
+ sum_b += sum_in_b;
+
+ ++stack_ptr;
+ if(stack_ptr >= div) stack_ptr = 0;
+ stack_pix_ptr = &stack[stack_ptr];
+
+ sum_out_r += stack_pix_ptr->r;
+ sum_out_g += stack_pix_ptr->g;
+ sum_out_b += stack_pix_ptr->b;
+ sum_in_r -= stack_pix_ptr->r;
+ sum_in_g -= stack_pix_ptr->g;
+ sum_in_b -= stack_pix_ptr->b;
+ }
+ }
+ }
+
+ if(ry > 0)
+ {
+ if(ry > 254) ry = 254;
+ div = ry * 2 + 1;
+ mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
+ shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
+ stack.allocate(div);
+
+ int stride = img.stride();
+ for(x = 0; x < w; x++)
+ {
+ sum_r =
+ sum_g =
+ sum_b =
+ sum_in_r =
+ sum_in_g =
+ sum_in_b =
+ sum_out_r =
+ sum_out_g =
+ sum_out_b = 0;
+
+ src_pix_ptr = img.pix_ptr(x, 0);
+ for(i = 0; i <= ry; i++)
+ {
+ stack_pix_ptr = &stack[i];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ sum_r += src_pix_ptr[R] * (i + 1);
+ sum_g += src_pix_ptr[G] * (i + 1);
+ sum_b += src_pix_ptr[B] * (i + 1);
+ sum_out_r += src_pix_ptr[R];
+ sum_out_g += src_pix_ptr[G];
+ sum_out_b += src_pix_ptr[B];
+ }
+ for(i = 1; i <= ry; i++)
+ {
+ if(i <= hm) src_pix_ptr += stride;
+ stack_pix_ptr = &stack[i + ry];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ sum_r += src_pix_ptr[R] * (ry + 1 - i);
+ sum_g += src_pix_ptr[G] * (ry + 1 - i);
+ sum_b += src_pix_ptr[B] * (ry + 1 - i);
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ }
+
+ stack_ptr = ry;
+ yp = ry;
+ if(yp > hm) yp = hm;
+ src_pix_ptr = img.pix_ptr(x, yp);
+ dst_pix_ptr = img.pix_ptr(x, 0);
+ for(y = 0; y < h; y++)
+ {
+ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
+ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
+ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
+ dst_pix_ptr += stride;
+
+ sum_r -= sum_out_r;
+ sum_g -= sum_out_g;
+ sum_b -= sum_out_b;
+
+ stack_start = stack_ptr + div - ry;
+ if(stack_start >= div) stack_start -= div;
+
+ stack_pix_ptr = &stack[stack_start];
+ sum_out_r -= stack_pix_ptr->r;
+ sum_out_g -= stack_pix_ptr->g;
+ sum_out_b -= stack_pix_ptr->b;
+
+ if(yp < hm)
+ {
+ src_pix_ptr += stride;
+ ++yp;
+ }
+
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ sum_r += sum_in_r;
+ sum_g += sum_in_g;
+ sum_b += sum_in_b;
+
+ ++stack_ptr;
+ if(stack_ptr >= div) stack_ptr = 0;
+ stack_pix_ptr = &stack[stack_ptr];
+
+ sum_out_r += stack_pix_ptr->r;
+ sum_out_g += stack_pix_ptr->g;
+ sum_out_b += stack_pix_ptr->b;
+ sum_in_r -= stack_pix_ptr->r;
+ sum_in_g -= stack_pix_ptr->g;
+ sum_in_b -= stack_pix_ptr->b;
+ }
+ }
+ }
+ }
+
+
+
+ //=======================================================stack_blur_rgba32
+ template<class Img>
+ void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry)
+ {
+ typedef typename Img::color_type color_type;
+ typedef typename Img::order_type order_type;
+ enum order_e
+ {
+ R = order_type::R,
+ G = order_type::G,
+ B = order_type::B,
+ A = order_type::A
+ };
+
+ unsigned x, y, xp, yp, i;
+ unsigned stack_ptr;
+ unsigned stack_start;
+
+ const int8u* src_pix_ptr;
+ int8u* dst_pix_ptr;
+ color_type* stack_pix_ptr;
+
+ unsigned sum_r;
+ unsigned sum_g;
+ unsigned sum_b;
+ unsigned sum_a;
+ unsigned sum_in_r;
+ unsigned sum_in_g;
+ unsigned sum_in_b;
+ unsigned sum_in_a;
+ unsigned sum_out_r;
+ unsigned sum_out_g;
+ unsigned sum_out_b;
+ unsigned sum_out_a;
+
+ unsigned w = img.width();
+ unsigned h = img.height();
+ unsigned wm = w - 1;
+ unsigned hm = h - 1;
+
+ unsigned div;
+ unsigned mul_sum;
+ unsigned shr_sum;
+
+ pod_vector<color_type> stack;
+
+ if(rx > 0)
+ {
+ if(rx > 254) rx = 254;
+ div = rx * 2 + 1;
+ mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
+ shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
+ stack.allocate(div);
+
+ for(y = 0; y < h; y++)
+ {
+ sum_r =
+ sum_g =
+ sum_b =
+ sum_a =
+ sum_in_r =
+ sum_in_g =
+ sum_in_b =
+ sum_in_a =
+ sum_out_r =
+ sum_out_g =
+ sum_out_b =
+ sum_out_a = 0;
+
+ src_pix_ptr = img.pix_ptr(0, y);
+ for(i = 0; i <= rx; i++)
+ {
+ stack_pix_ptr = &stack[i];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ stack_pix_ptr->a = src_pix_ptr[A];
+ sum_r += src_pix_ptr[R] * (i + 1);
+ sum_g += src_pix_ptr[G] * (i + 1);
+ sum_b += src_pix_ptr[B] * (i + 1);
+ sum_a += src_pix_ptr[A] * (i + 1);
+ sum_out_r += src_pix_ptr[R];
+ sum_out_g += src_pix_ptr[G];
+ sum_out_b += src_pix_ptr[B];
+ sum_out_a += src_pix_ptr[A];
+ }
+ for(i = 1; i <= rx; i++)
+ {
+ if(i <= wm) src_pix_ptr += Img::pix_width;
+ stack_pix_ptr = &stack[i + rx];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ stack_pix_ptr->a = src_pix_ptr[A];
+ sum_r += src_pix_ptr[R] * (rx + 1 - i);
+ sum_g += src_pix_ptr[G] * (rx + 1 - i);
+ sum_b += src_pix_ptr[B] * (rx + 1 - i);
+ sum_a += src_pix_ptr[A] * (rx + 1 - i);
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ sum_in_a += src_pix_ptr[A];
+ }
+
+ stack_ptr = rx;
+ xp = rx;
+ if(xp > wm) xp = wm;
+ src_pix_ptr = img.pix_ptr(xp, y);
+ dst_pix_ptr = img.pix_ptr(0, y);
+ for(x = 0; x < w; x++)
+ {
+ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
+ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
+ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
+ dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
+ dst_pix_ptr += Img::pix_width;
+
+ sum_r -= sum_out_r;
+ sum_g -= sum_out_g;
+ sum_b -= sum_out_b;
+ sum_a -= sum_out_a;
+
+ stack_start = stack_ptr + div - rx;
+ if(stack_start >= div) stack_start -= div;
+ stack_pix_ptr = &stack[stack_start];
+
+ sum_out_r -= stack_pix_ptr->r;
+ sum_out_g -= stack_pix_ptr->g;
+ sum_out_b -= stack_pix_ptr->b;
+ sum_out_a -= stack_pix_ptr->a;
+
+ if(xp < wm)
+ {
+ src_pix_ptr += Img::pix_width;
+ ++xp;
+ }
+
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ stack_pix_ptr->a = src_pix_ptr[A];
+
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ sum_in_a += src_pix_ptr[A];
+ sum_r += sum_in_r;
+ sum_g += sum_in_g;
+ sum_b += sum_in_b;
+ sum_a += sum_in_a;
+
+ ++stack_ptr;
+ if(stack_ptr >= div) stack_ptr = 0;
+ stack_pix_ptr = &stack[stack_ptr];
+
+ sum_out_r += stack_pix_ptr->r;
+ sum_out_g += stack_pix_ptr->g;
+ sum_out_b += stack_pix_ptr->b;
+ sum_out_a += stack_pix_ptr->a;
+ sum_in_r -= stack_pix_ptr->r;
+ sum_in_g -= stack_pix_ptr->g;
+ sum_in_b -= stack_pix_ptr->b;
+ sum_in_a -= stack_pix_ptr->a;
+ }
+ }
+ }
+
+ if(ry > 0)
+ {
+ if(ry > 254) ry = 254;
+ div = ry * 2 + 1;
+ mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
+ shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
+ stack.allocate(div);
+
+ int stride = img.stride();
+ for(x = 0; x < w; x++)
+ {
+ sum_r =
+ sum_g =
+ sum_b =
+ sum_a =
+ sum_in_r =
+ sum_in_g =
+ sum_in_b =
+ sum_in_a =
+ sum_out_r =
+ sum_out_g =
+ sum_out_b =
+ sum_out_a = 0;
+
+ src_pix_ptr = img.pix_ptr(x, 0);
+ for(i = 0; i <= ry; i++)
+ {
+ stack_pix_ptr = &stack[i];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ stack_pix_ptr->a = src_pix_ptr[A];
+ sum_r += src_pix_ptr[R] * (i + 1);
+ sum_g += src_pix_ptr[G] * (i + 1);
+ sum_b += src_pix_ptr[B] * (i + 1);
+ sum_a += src_pix_ptr[A] * (i + 1);
+ sum_out_r += src_pix_ptr[R];
+ sum_out_g += src_pix_ptr[G];
+ sum_out_b += src_pix_ptr[B];
+ sum_out_a += src_pix_ptr[A];
+ }
+ for(i = 1; i <= ry; i++)
+ {
+ if(i <= hm) src_pix_ptr += stride;
+ stack_pix_ptr = &stack[i + ry];
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ stack_pix_ptr->a = src_pix_ptr[A];
+ sum_r += src_pix_ptr[R] * (ry + 1 - i);
+ sum_g += src_pix_ptr[G] * (ry + 1 - i);
+ sum_b += src_pix_ptr[B] * (ry + 1 - i);
+ sum_a += src_pix_ptr[A] * (ry + 1 - i);
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ sum_in_a += src_pix_ptr[A];
+ }
+
+ stack_ptr = ry;
+ yp = ry;
+ if(yp > hm) yp = hm;
+ src_pix_ptr = img.pix_ptr(x, yp);
+ dst_pix_ptr = img.pix_ptr(x, 0);
+ for(y = 0; y < h; y++)
+ {
+ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
+ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
+ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
+ dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
+ dst_pix_ptr += stride;
+
+ sum_r -= sum_out_r;
+ sum_g -= sum_out_g;
+ sum_b -= sum_out_b;
+ sum_a -= sum_out_a;
+
+ stack_start = stack_ptr + div - ry;
+ if(stack_start >= div) stack_start -= div;
+
+ stack_pix_ptr = &stack[stack_start];
+ sum_out_r -= stack_pix_ptr->r;
+ sum_out_g -= stack_pix_ptr->g;
+ sum_out_b -= stack_pix_ptr->b;
+ sum_out_a -= stack_pix_ptr->a;
+
+ if(yp < hm)
+ {
+ src_pix_ptr += stride;
+ ++yp;
+ }
+
+ stack_pix_ptr->r = src_pix_ptr[R];
+ stack_pix_ptr->g = src_pix_ptr[G];
+ stack_pix_ptr->b = src_pix_ptr[B];
+ stack_pix_ptr->a = src_pix_ptr[A];
+
+ sum_in_r += src_pix_ptr[R];
+ sum_in_g += src_pix_ptr[G];
+ sum_in_b += src_pix_ptr[B];
+ sum_in_a += src_pix_ptr[A];
+ sum_r += sum_in_r;
+ sum_g += sum_in_g;
+ sum_b += sum_in_b;
+ sum_a += sum_in_a;
+
+ ++stack_ptr;
+ if(stack_ptr >= div) stack_ptr = 0;
+ stack_pix_ptr = &stack[stack_ptr];
+
+ sum_out_r += stack_pix_ptr->r;
+ sum_out_g += stack_pix_ptr->g;
+ sum_out_b += stack_pix_ptr->b;
+ sum_out_a += stack_pix_ptr->a;
+ sum_in_r -= stack_pix_ptr->r;
+ sum_in_g -= stack_pix_ptr->g;
+ sum_in_b -= stack_pix_ptr->b;
+ sum_in_a -= stack_pix_ptr->a;
+ }
+ }
+ }
+ }
+
+
+
+ //===========================================================recursive_blur
+ template<class ColorT, class CalculatorT> class recursive_blur
+ {
+ public:
+ typedef ColorT color_type;
+ typedef CalculatorT calculator_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename calculator_type::value_type calc_type;
+
+ //--------------------------------------------------------------------
+ template<class Img> void blur_x(Img& img, double radius)
+ {
+ if(radius < 0.62) return;
+ if(img.width() < 3) return;
+
+ calc_type s = calc_type(radius * 0.5);
+ calc_type q = calc_type((s < 2.5) ?
+ 3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) :
+ 0.98711 * s - 0.96330);
+
+ calc_type q2 = calc_type(q * q);
+ calc_type q3 = calc_type(q2 * q);
+
+ calc_type b0 = calc_type(1.0 / (1.578250 +
+ 2.444130 * q +
+ 1.428100 * q2 +
+ 0.422205 * q3));
+
+ calc_type b1 = calc_type( 2.44413 * q +
+ 2.85619 * q2 +
+ 1.26661 * q3);
+
+ calc_type b2 = calc_type(-1.42810 * q2 +
+ -1.26661 * q3);
+
+ calc_type b3 = calc_type(0.422205 * q3);
+
+ calc_type b = calc_type(1 - (b1 + b2 + b3) * b0);
+
+ b1 *= b0;
+ b2 *= b0;
+ b3 *= b0;
+
+ int w = img.width();
+ int h = img.height();
+ int wm = w-1;
+ int x, y;
+
+ m_sum1.allocate(w);
+ m_sum2.allocate(w);
+ m_buf.allocate(w);
+
+ for(y = 0; y < h; y++)
+ {
+ calculator_type c;
+ c.from_pix(img.pixel(0, y));
+ m_sum1[0].calc(b, b1, b2, b3, c, c, c, c);
+ c.from_pix(img.pixel(1, y));
+ m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]);
+ c.from_pix(img.pixel(2, y));
+ m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]);
+
+ for(x = 3; x < w; ++x)
+ {
+ c.from_pix(img.pixel(x, y));
+ m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]);
+ }
+
+ m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]);
+ m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]);
+ m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]);
+ m_sum2[wm ].to_pix(m_buf[wm ]);
+ m_sum2[wm-1].to_pix(m_buf[wm-1]);
+ m_sum2[wm-2].to_pix(m_buf[wm-2]);
+
+ for(x = wm-3; x >= 0; --x)
+ {
+ m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]);
+ m_sum2[x].to_pix(m_buf[x]);
+ }
+ img.copy_color_hspan(0, y, w, &m_buf[0]);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class Img> void blur_y(Img& img, double radius)
+ {
+ pixfmt_transposer<Img> img2(img);
+ blur_x(img2, radius);
+ }
+
+ //--------------------------------------------------------------------
+ template<class Img> void blur(Img& img, double radius)
+ {
+ blur_x(img, radius);
+ pixfmt_transposer<Img> img2(img);
+ blur_x(img2, radius);
+ }
+
+ private:
+ agg::pod_vector<calculator_type> m_sum1;
+ agg::pod_vector<calculator_type> m_sum2;
+ agg::pod_vector<color_type> m_buf;
+ };
+
+
+ //=================================================recursive_blur_calc_rgba
+ template<class T=double> struct recursive_blur_calc_rgba
+ {
+ typedef T value_type;
+ typedef recursive_blur_calc_rgba<T> self_type;
+
+ value_type r,g,b,a;
+
+ template<class ColorT>
+ AGG_INLINE void from_pix(const ColorT& c)
+ {
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ a = c.a;
+ }
+
+ AGG_INLINE void calc(value_type b1,
+ value_type b2,
+ value_type b3,
+ value_type b4,
+ const self_type& c1,
+ const self_type& c2,
+ const self_type& c3,
+ const self_type& c4)
+ {
+ r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
+ g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
+ b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
+ a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a;
+ }
+
+ template<class ColorT>
+ AGG_INLINE void to_pix(ColorT& c) const
+ {
+ typedef typename ColorT::value_type cv_type;
+ c.r = (cv_type)uround(r);
+ c.g = (cv_type)uround(g);
+ c.b = (cv_type)uround(b);
+ c.a = (cv_type)uround(a);
+ }
+ };
+
+
+ //=================================================recursive_blur_calc_rgb
+ template<class T=double> struct recursive_blur_calc_rgb
+ {
+ typedef T value_type;
+ typedef recursive_blur_calc_rgb<T> self_type;
+
+ value_type r,g,b;
+
+ template<class ColorT>
+ AGG_INLINE void from_pix(const ColorT& c)
+ {
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ }
+
+ AGG_INLINE void calc(value_type b1,
+ value_type b2,
+ value_type b3,
+ value_type b4,
+ const self_type& c1,
+ const self_type& c2,
+ const self_type& c3,
+ const self_type& c4)
+ {
+ r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
+ g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
+ b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
+ }
+
+ template<class ColorT>
+ AGG_INLINE void to_pix(ColorT& c) const
+ {
+ typedef typename ColorT::value_type cv_type;
+ c.r = (cv_type)uround(r);
+ c.g = (cv_type)uround(g);
+ c.b = (cv_type)uround(b);
+ }
+ };
+
+
+ //================================================recursive_blur_calc_gray
+ template<class T=double> struct recursive_blur_calc_gray
+ {
+ typedef T value_type;
+ typedef recursive_blur_calc_gray<T> self_type;
+
+ value_type v;
+
+ template<class ColorT>
+ AGG_INLINE void from_pix(const ColorT& c)
+ {
+ v = c.v;
+ }
+
+ AGG_INLINE void calc(value_type b1,
+ value_type b2,
+ value_type b3,
+ value_type b4,
+ const self_type& c1,
+ const self_type& c2,
+ const self_type& c3,
+ const self_type& c4)
+ {
+ v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v;
+ }
+
+ template<class ColorT>
+ AGG_INLINE void to_pix(ColorT& c) const
+ {
+ typedef typename ColorT::value_type cv_type;
+ c.v = (cv_type)uround(v);
+ }
+ };
+
+}
+
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_bounding_rect.h b/plugins/Clist_ng/AGG/include/agg_bounding_rect.h new file mode 100644 index 0000000000..eb869eb6da --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_bounding_rect.h @@ -0,0 +1,122 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_BOUNDING_RECT_INCLUDED
+#define AGG_BOUNDING_RECT_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------------------bounding_rect
+ template<class VertexSource, class GetId, class CoordT>
+ bool bounding_rect(VertexSource& vs, GetId& gi,
+ unsigned start, unsigned num,
+ CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
+ {
+ unsigned i;
+ double x;
+ double y;
+ bool first = true;
+
+ *x1 = CoordT(1);
+ *y1 = CoordT(1);
+ *x2 = CoordT(0);
+ *y2 = CoordT(0);
+
+ for(i = 0; i < num; i++)
+ {
+ vs.rewind(gi[start + i]);
+ unsigned cmd;
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ if(is_vertex(cmd))
+ {
+ if(first)
+ {
+ *x1 = CoordT(x);
+ *y1 = CoordT(y);
+ *x2 = CoordT(x);
+ *y2 = CoordT(y);
+ first = false;
+ }
+ else
+ {
+ if(CoordT(x) < *x1) *x1 = CoordT(x);
+ if(CoordT(y) < *y1) *y1 = CoordT(y);
+ if(CoordT(x) > *x2) *x2 = CoordT(x);
+ if(CoordT(y) > *y2) *y2 = CoordT(y);
+ }
+ }
+ }
+ }
+ return *x1 <= *x2 && *y1 <= *y2;
+ }
+
+
+ //-----------------------------------------------------bounding_rect_single
+ template<class VertexSource, class CoordT>
+ bool bounding_rect_single(VertexSource& vs, unsigned path_id,
+ CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
+ {
+ double x;
+ double y;
+ bool first = true;
+
+ *x1 = CoordT(1);
+ *y1 = CoordT(1);
+ *x2 = CoordT(0);
+ *y2 = CoordT(0);
+
+ vs.rewind(path_id);
+ unsigned cmd;
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ if(is_vertex(cmd))
+ {
+ if(first)
+ {
+ *x1 = CoordT(x);
+ *y1 = CoordT(y);
+ *x2 = CoordT(x);
+ *y2 = CoordT(y);
+ first = false;
+ }
+ else
+ {
+ if(CoordT(x) < *x1) *x1 = CoordT(x);
+ if(CoordT(y) < *y1) *y1 = CoordT(y);
+ if(CoordT(x) > *x2) *x2 = CoordT(x);
+ if(CoordT(y) > *y2) *y2 = CoordT(y);
+ }
+ }
+ }
+ return *x1 <= *x2 && *y1 <= *y2;
+ }
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_bspline.h b/plugins/Clist_ng/AGG/include/agg_bspline.h new file mode 100644 index 0000000000..ff8eda4fcc --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_bspline.h @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_BSPLINE_INCLUDED
+#define AGG_BSPLINE_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+ //----------------------------------------------------------------bspline
+ // A very simple class of Bi-cubic Spline interpolation.
+ // First call init(num, x[], y[]) where num - number of source points,
+ // x, y - arrays of X and Y values respectively. Here Y must be a function
+ // of X. It means that all the X-coordinates must be arranged in the ascending
+ // order.
+ // Then call get(x) that calculates a value Y for the respective X.
+ // The class supports extrapolation, i.e. you can call get(x) where x is
+ // outside the given with init() X-range. Extrapolation is a simple linear
+ // function.
+ //
+ // See Implementation agg_bspline.cpp
+ //------------------------------------------------------------------------
+ class bspline
+ {
+ public:
+ bspline();
+ bspline(int num);
+ bspline(int num, const double* x, const double* y);
+
+ void init(int num);
+ void add_point(double x, double y);
+ void prepare();
+
+ void init(int num, const double* x, const double* y);
+
+ double get(double x) const;
+ double get_stateful(double x) const;
+
+ private:
+ bspline(const bspline&);
+ const bspline& operator = (const bspline&);
+
+ static void bsearch(int n, const double *x, double x0, int *i);
+ double extrapolation_left(double x) const;
+ double extrapolation_right(double x) const;
+ double interpolation(double x, int i) const;
+
+ int m_max;
+ int m_num;
+ double* m_x;
+ double* m_y;
+ pod_array<double> m_am;
+ mutable int m_last_idx;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_clip_liang_barsky.h b/plugins/Clist_ng/AGG/include/agg_clip_liang_barsky.h new file mode 100644 index 0000000000..a612ddf1f6 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_clip_liang_barsky.h @@ -0,0 +1,339 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
+#define AGG_CLIP_LIANG_BARSKY_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ enum clipping_flags_e
+ {
+ clipping_flags_x1_clipped = 4,
+ clipping_flags_x2_clipped = 1,
+ clipping_flags_y1_clipped = 8,
+ clipping_flags_y2_clipped = 2,
+ clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
+ clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
+ };
+
+ //----------------------------------------------------------clipping_flags
+ // Determine the clipping code of the vertex according to the
+ // Cyrus-Beck line clipping algorithm
+ //
+ // | |
+ // 0110 | 0010 | 0011
+ // | |
+ // -------+--------+-------- clip_box.y2
+ // | |
+ // 0100 | 0000 | 0001
+ // | |
+ // -------+--------+-------- clip_box.y1
+ // | |
+ // 1100 | 1000 | 1001
+ // | |
+ // clip_box.x1 clip_box.x2
+ //
+ //
+ template<class T>
+ inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
+ {
+ return (x > clip_box.x2) |
+ ((y > clip_box.y2) << 1) |
+ ((x < clip_box.x1) << 2) |
+ ((y < clip_box.y1) << 3);
+ }
+
+ //--------------------------------------------------------clipping_flags_x
+ template<class T>
+ inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
+ {
+ return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
+ }
+
+
+ //--------------------------------------------------------clipping_flags_y
+ template<class T>
+ inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
+ {
+ return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
+ }
+
+
+ //-------------------------------------------------------clip_liang_barsky
+ template<class T>
+ inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
+ const rect_base<T>& clip_box,
+ T* x, T* y)
+ {
+ const double nearzero = 1e-30;
+
+ double deltax = x2 - x1;
+ double deltay = y2 - y1;
+ double xin;
+ double xout;
+ double yin;
+ double yout;
+ double tinx;
+ double tiny;
+ double toutx;
+ double touty;
+ double tin1;
+ double tin2;
+ double tout1;
+ unsigned np = 0;
+
+ if(deltax == 0.0)
+ {
+ // bump off of the vertical
+ deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
+ }
+
+ if(deltay == 0.0)
+ {
+ // bump off of the horizontal
+ deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
+ }
+
+ if(deltax > 0.0)
+ {
+ // points to right
+ xin = clip_box.x1;
+ xout = clip_box.x2;
+ }
+ else
+ {
+ xin = clip_box.x2;
+ xout = clip_box.x1;
+ }
+
+ if(deltay > 0.0)
+ {
+ // points up
+ yin = clip_box.y1;
+ yout = clip_box.y2;
+ }
+ else
+ {
+ yin = clip_box.y2;
+ yout = clip_box.y1;
+ }
+
+ tinx = (xin - x1) / deltax;
+ tiny = (yin - y1) / deltay;
+
+ if (tinx < tiny)
+ {
+ // hits x first
+ tin1 = tinx;
+ tin2 = tiny;
+ }
+ else
+ {
+ // hits y first
+ tin1 = tiny;
+ tin2 = tinx;
+ }
+
+ if(tin1 <= 1.0)
+ {
+ if(0.0 < tin1)
+ {
+ *x++ = (T)xin;
+ *y++ = (T)yin;
+ ++np;
+ }
+
+ if(tin2 <= 1.0)
+ {
+ toutx = (xout - x1) / deltax;
+ touty = (yout - y1) / deltay;
+
+ tout1 = (toutx < touty) ? toutx : touty;
+
+ if(tin2 > 0.0 || tout1 > 0.0)
+ {
+ if(tin2 <= tout1)
+ {
+ if(tin2 > 0.0)
+ {
+ if(tinx > tiny)
+ {
+ *x++ = (T)xin;
+ *y++ = (T)(y1 + tinx * deltay);
+ }
+ else
+ {
+ *x++ = (T)(x1 + tiny * deltax);
+ *y++ = (T)yin;
+ }
+ ++np;
+ }
+
+ if(tout1 < 1.0)
+ {
+ if(toutx < touty)
+ {
+ *x++ = (T)xout;
+ *y++ = (T)(y1 + toutx * deltay);
+ }
+ else
+ {
+ *x++ = (T)(x1 + touty * deltax);
+ *y++ = (T)yout;
+ }
+ }
+ else
+ {
+ *x++ = x2;
+ *y++ = y2;
+ }
+ ++np;
+ }
+ else
+ {
+ if(tinx > tiny)
+ {
+ *x++ = (T)xin;
+ *y++ = (T)yout;
+ }
+ else
+ {
+ *x++ = (T)xout;
+ *y++ = (T)yin;
+ }
+ ++np;
+ }
+ }
+ }
+ }
+ return np;
+ }
+
+
+ //----------------------------------------------------------------------------
+ template<class T>
+ bool clip_move_point(T x1, T y1, T x2, T y2,
+ const rect_base<T>& clip_box,
+ T* x, T* y, unsigned flags)
+ {
+ T bound;
+
+ if(flags & clipping_flags_x_clipped)
+ {
+ if(x1 == x2)
+ {
+ return false;
+ }
+ bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
+ *y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
+ *x = bound;
+ }
+
+ flags = clipping_flags_y(*y, clip_box);
+ if(flags & clipping_flags_y_clipped)
+ {
+ if(y1 == y2)
+ {
+ return false;
+ }
+ bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
+ *x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
+ *y = bound;
+ }
+ return true;
+ }
+
+ //-------------------------------------------------------clip_line_segment
+ // Returns: ret >= 4 - Fully clipped
+ // (ret & 1) != 0 - First point has been moved
+ // (ret & 2) != 0 - Second point has been moved
+ //
+ template<class T>
+ unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
+ const rect_base<T>& clip_box)
+ {
+ unsigned f1 = clipping_flags(*x1, *y1, clip_box);
+ unsigned f2 = clipping_flags(*x2, *y2, clip_box);
+ unsigned ret = 0;
+
+ if((f2 | f1) == 0)
+ {
+ // Fully visible
+ return 0;
+ }
+
+ if((f1 & clipping_flags_x_clipped) != 0 &&
+ (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
+ {
+ // Fully clipped
+ return 4;
+ }
+
+ if((f1 & clipping_flags_y_clipped) != 0 &&
+ (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
+ {
+ // Fully clipped
+ return 4;
+ }
+
+ T tx1 = *x1;
+ T ty1 = *y1;
+ T tx2 = *x2;
+ T ty2 = *y2;
+ if(f1)
+ {
+ if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
+ {
+ return 4;
+ }
+ if(*x1 == *x2 && *y1 == *y2)
+ {
+ return 4;
+ }
+ ret |= 1;
+ }
+ if(f2)
+ {
+ if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
+ {
+ return 4;
+ }
+ if(*x1 == *x2 && *y1 == *y2)
+ {
+ return 4;
+ }
+ ret |= 2;
+ }
+ return ret;
+ }
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_color_gray.h b/plugins/Clist_ng/AGG/include/agg_color_gray.h new file mode 100644 index 0000000000..74ed66e1d1 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_color_gray.h @@ -0,0 +1,423 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+//
+// color types gray8, gray16
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_COLOR_GRAY_INCLUDED
+#define AGG_COLOR_GRAY_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+
+namespace agg
+{
+
+ //===================================================================gray8
+ struct gray8
+ {
+ typedef int8u value_type;
+ typedef int32u calc_type;
+ typedef int32 long_type;
+ enum base_scale_e
+ {
+ base_shift = 8,
+ base_scale = 1 << base_shift,
+ base_mask = base_scale - 1
+ };
+ typedef gray8 self_type;
+
+ value_type v;
+ value_type a;
+
+ //--------------------------------------------------------------------
+ gray8() {}
+
+ //--------------------------------------------------------------------
+ gray8(unsigned v_, unsigned a_=base_mask) :
+ v(int8u(v_)), a(int8u(a_)) {}
+
+ //--------------------------------------------------------------------
+ gray8(const self_type& c, unsigned a_) :
+ v(c.v), a(value_type(a_)) {}
+
+ //--------------------------------------------------------------------
+ gray8(const rgba& c) :
+ v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
+ a((value_type)uround(c.a * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ gray8(const rgba& c, double a_) :
+ v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
+ a((value_type)uround(a_ * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ gray8(const rgba8& c) :
+ v((c.r*77 + c.g*150 + c.b*29) >> 8),
+ a(c.a) {}
+
+ //--------------------------------------------------------------------
+ gray8(const rgba8& c, unsigned a_) :
+ v((c.r*77 + c.g*150 + c.b*29) >> 8),
+ a(a_) {}
+
+ //--------------------------------------------------------------------
+ void clear()
+ {
+ v = a = 0;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& transparent()
+ {
+ a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ void opacity(double a_)
+ {
+ if(a_ < 0.0) a_ = 0.0;
+ if(a_ > 1.0) a_ = 1.0;
+ a = (value_type)uround(a_ * double(base_mask));
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return double(a) / double(base_mask);
+ }
+
+
+ //--------------------------------------------------------------------
+ const self_type& premultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ v = 0;
+ return *this;
+ }
+ v = value_type((calc_type(v) * a) >> base_shift);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& premultiply(unsigned a_)
+ {
+ if(a == base_mask && a_ >= base_mask) return *this;
+ if(a == 0 || a_ == 0)
+ {
+ v = a = 0;
+ return *this;
+ }
+ calc_type v_ = (calc_type(v) * a_) / a;
+ v = value_type((v_ > a_) ? a_ : v_);
+ a = value_type(a_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& demultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ v = 0;
+ return *this;
+ }
+ calc_type v_ = (calc_type(v) * base_mask) / a;
+ v = value_type((v_ > base_mask) ? (value_type)base_mask : v_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type gradient(self_type c, double k) const
+ {
+ self_type ret;
+ calc_type ik = uround(k * base_scale);
+ ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
+ ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ return ret;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void add(const self_type& c, unsigned cover)
+ {
+ calc_type cv, ca;
+ if(cover == cover_mask)
+ {
+ if(c.a == base_mask)
+ {
+ *this = c;
+ }
+ else
+ {
+ cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
+ ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+ else
+ {
+ cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
+ ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
+ v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
+ a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ static self_type no_color() { return self_type(0,0); }
+ };
+
+
+ //-------------------------------------------------------------gray8_pre
+ inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask)
+ {
+ return gray8(v,a).premultiply();
+ }
+ inline gray8 gray8_pre(const gray8& c, unsigned a)
+ {
+ return gray8(c,a).premultiply();
+ }
+ inline gray8 gray8_pre(const rgba& c)
+ {
+ return gray8(c).premultiply();
+ }
+ inline gray8 gray8_pre(const rgba& c, double a)
+ {
+ return gray8(c,a).premultiply();
+ }
+ inline gray8 gray8_pre(const rgba8& c)
+ {
+ return gray8(c).premultiply();
+ }
+ inline gray8 gray8_pre(const rgba8& c, unsigned a)
+ {
+ return gray8(c,a).premultiply();
+ }
+
+
+
+
+ //==================================================================gray16
+ struct gray16
+ {
+ typedef int16u value_type;
+ typedef int32u calc_type;
+ typedef int64 long_type;
+ enum base_scale_e
+ {
+ base_shift = 16,
+ base_scale = 1 << base_shift,
+ base_mask = base_scale - 1
+ };
+ typedef gray16 self_type;
+
+ value_type v;
+ value_type a;
+
+ //--------------------------------------------------------------------
+ gray16() {}
+
+ //--------------------------------------------------------------------
+ gray16(unsigned v_, unsigned a_=base_mask) :
+ v(int16u(v_)), a(int16u(a_)) {}
+
+ //--------------------------------------------------------------------
+ gray16(const self_type& c, unsigned a_) :
+ v(c.v), a(value_type(a_)) {}
+
+ //--------------------------------------------------------------------
+ gray16(const rgba& c) :
+ v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
+ a((value_type)uround(c.a * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ gray16(const rgba& c, double a_) :
+ v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
+ a((value_type)uround(a_ * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ gray16(const rgba8& c) :
+ v(c.r*77 + c.g*150 + c.b*29),
+ a((value_type(c.a) << 8) | c.a) {}
+
+ //--------------------------------------------------------------------
+ gray16(const rgba8& c, unsigned a_) :
+ v(c.r*77 + c.g*150 + c.b*29),
+ a((value_type(a_) << 8) | c.a) {}
+
+ //--------------------------------------------------------------------
+ void clear()
+ {
+ v = a = 0;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& transparent()
+ {
+ a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ void opacity(double a_)
+ {
+ if(a_ < 0.0) a_ = 0.0;
+ if(a_ > 1.0) a_ = 1.0;
+ a = (value_type)uround(a_ * double(base_mask));
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return double(a) / double(base_mask);
+ }
+
+
+ //--------------------------------------------------------------------
+ const self_type& premultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ v = 0;
+ return *this;
+ }
+ v = value_type((calc_type(v) * a) >> base_shift);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& premultiply(unsigned a_)
+ {
+ if(a == base_mask && a_ >= base_mask) return *this;
+ if(a == 0 || a_ == 0)
+ {
+ v = a = 0;
+ return *this;
+ }
+ calc_type v_ = (calc_type(v) * a_) / a;
+ v = value_type((v_ > a_) ? a_ : v_);
+ a = value_type(a_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& demultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ v = 0;
+ return *this;
+ }
+ calc_type v_ = (calc_type(v) * base_mask) / a;
+ v = value_type((v_ > base_mask) ? base_mask : v_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type gradient(self_type c, double k) const
+ {
+ self_type ret;
+ calc_type ik = uround(k * base_scale);
+ ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
+ ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ return ret;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void add(const self_type& c, unsigned cover)
+ {
+ calc_type cv, ca;
+ if(cover == cover_mask)
+ {
+ if(c.a == base_mask)
+ {
+ *this = c;
+ }
+ else
+ {
+ cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
+ ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+ else
+ {
+ cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
+ ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
+ v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
+ a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ static self_type no_color() { return self_type(0,0); }
+ };
+
+
+ //------------------------------------------------------------gray16_pre
+ inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask)
+ {
+ return gray16(v,a).premultiply();
+ }
+ inline gray16 gray16_pre(const gray16& c, unsigned a)
+ {
+ return gray16(c,a).premultiply();
+ }
+ inline gray16 gray16_pre(const rgba& c)
+ {
+ return gray16(c).premultiply();
+ }
+ inline gray16 gray16_pre(const rgba& c, double a)
+ {
+ return gray16(c,a).premultiply();
+ }
+ inline gray16 gray16_pre(const rgba8& c)
+ {
+ return gray16(c).premultiply();
+ }
+ inline gray16 gray16_pre(const rgba8& c, unsigned a)
+ {
+ return gray16(c,a).premultiply();
+ }
+
+
+}
+
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_color_rgba.h b/plugins/Clist_ng/AGG/include/agg_color_rgba.h new file mode 100644 index 0000000000..7cc25b5f0f --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_color_rgba.h @@ -0,0 +1,756 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+
+#ifndef AGG_COLOR_RGBA_INCLUDED
+#define AGG_COLOR_RGBA_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+ // Supported byte orders for RGB and RGBA pixel formats
+ //=======================================================================
+ struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb
+ struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr
+ struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba
+ struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb
+ struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr
+ struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra
+
+ //====================================================================rgba
+ struct rgba
+ {
+ typedef double value_type;
+
+ double r;
+ double g;
+ double b;
+ double a;
+
+ //--------------------------------------------------------------------
+ rgba() {}
+
+ //--------------------------------------------------------------------
+ rgba(double r_, double g_, double b_, double a_=1.0) :
+ r(r_), g(g_), b(b_), a(a_) {}
+
+ //--------------------------------------------------------------------
+ rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
+
+ //--------------------------------------------------------------------
+ void clear()
+ {
+ r = g = b = a = 0;
+ }
+
+ //--------------------------------------------------------------------
+ const rgba& transparent()
+ {
+ a = 0.0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const rgba& opacity(double a_)
+ {
+ if(a_ < 0.0) a_ = 0.0;
+ if(a_ > 1.0) a_ = 1.0;
+ a = a_;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return a;
+ }
+
+ //--------------------------------------------------------------------
+ const rgba& premultiply()
+ {
+ r *= a;
+ g *= a;
+ b *= a;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const rgba& premultiply(double a_)
+ {
+ if(a <= 0.0 || a_ <= 0.0)
+ {
+ r = g = b = a = 0.0;
+ return *this;
+ }
+ a_ /= a;
+ r *= a_;
+ g *= a_;
+ b *= a_;
+ a = a_;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const rgba& demultiply()
+ {
+ if(a == 0)
+ {
+ r = g = b = 0;
+ return *this;
+ }
+ double a_ = 1.0 / a;
+ r *= a_;
+ g *= a_;
+ b *= a_;
+ return *this;
+ }
+
+
+ //--------------------------------------------------------------------
+ rgba gradient(rgba c, double k) const
+ {
+ rgba ret;
+ ret.r = r + (c.r - r) * k;
+ ret.g = g + (c.g - g) * k;
+ ret.b = b + (c.b - b) * k;
+ ret.a = a + (c.a - a) * k;
+ return ret;
+ }
+
+ //--------------------------------------------------------------------
+ static rgba no_color() { return rgba(0,0,0,0); }
+
+ //--------------------------------------------------------------------
+ static rgba from_wavelength(double wl, double gamma = 1.0);
+
+ //--------------------------------------------------------------------
+ explicit rgba(double wavelen, double gamma=1.0)
+ {
+ *this = from_wavelength(wavelen, gamma);
+ }
+
+ };
+
+ //----------------------------------------------------------------rgba_pre
+ inline rgba rgba_pre(double r, double g, double b, double a=1.0)
+ {
+ return rgba(r, g, b, a).premultiply();
+ }
+ inline rgba rgba_pre(const rgba& c)
+ {
+ return rgba(c).premultiply();
+ }
+ inline rgba rgba_pre(const rgba& c, double a)
+ {
+ return rgba(c, a).premultiply();
+ }
+
+ //------------------------------------------------------------------------
+ inline rgba rgba::from_wavelength(double wl, double gamma)
+ {
+ rgba t(0.0, 0.0, 0.0);
+
+ if(wl >= 380.0 && wl <= 440.0)
+ {
+ t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
+ t.b = 1.0;
+ }
+ else
+ if(wl >= 440.0 && wl <= 490.0)
+ {
+ t.g = (wl - 440.0) / (490.0 - 440.0);
+ t.b = 1.0;
+ }
+ else
+ if(wl >= 490.0 && wl <= 510.0)
+ {
+ t.g = 1.0;
+ t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
+ }
+ else
+ if(wl >= 510.0 && wl <= 580.0)
+ {
+ t.r = (wl - 510.0) / (580.0 - 510.0);
+ t.g = 1.0;
+ }
+ else
+ if(wl >= 580.0 && wl <= 645.0)
+ {
+ t.r = 1.0;
+ t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
+ }
+ else
+ if(wl >= 645.0 && wl <= 780.0)
+ {
+ t.r = 1.0;
+ }
+
+ double s = 1.0;
+ if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
+ else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
+
+ t.r = pow(t.r * s, gamma);
+ t.g = pow(t.g * s, gamma);
+ t.b = pow(t.b * s, gamma);
+ return t;
+ }
+
+
+
+
+ //===================================================================rgba8
+ struct rgba8
+ {
+ typedef int8u value_type;
+ typedef int32u calc_type;
+ typedef int32 long_type;
+ enum base_scale_e
+ {
+ base_shift = 8,
+ base_scale = 1 << base_shift,
+ base_mask = base_scale - 1
+ };
+ typedef rgba8 self_type;
+
+
+ value_type r;
+ value_type g;
+ value_type b;
+ value_type a;
+
+ //--------------------------------------------------------------------
+ rgba8() {}
+
+ //--------------------------------------------------------------------
+ rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
+ r(value_type(r_)),
+ g(value_type(g_)),
+ b(value_type(b_)),
+ a(value_type(a_)) {}
+
+ //--------------------------------------------------------------------
+ rgba8(const rgba& c, double a_) :
+ r((value_type)uround(c.r * double(base_mask))),
+ g((value_type)uround(c.g * double(base_mask))),
+ b((value_type)uround(c.b * double(base_mask))),
+ a((value_type)uround(a_ * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ rgba8(const self_type& c, unsigned a_) :
+ r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
+
+ //--------------------------------------------------------------------
+ rgba8(const rgba& c) :
+ r((value_type)uround(c.r * double(base_mask))),
+ g((value_type)uround(c.g * double(base_mask))),
+ b((value_type)uround(c.b * double(base_mask))),
+ a((value_type)uround(c.a * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ void clear()
+ {
+ r = g = b = a = 0;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& transparent()
+ {
+ a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& opacity(double a_)
+ {
+ if(a_ < 0.0) a_ = 0.0;
+ if(a_ > 1.0) a_ = 1.0;
+ a = (value_type)uround(a_ * double(base_mask));
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return double(a) / double(base_mask);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE const self_type& premultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ r = g = b = 0;
+ return *this;
+ }
+ r = value_type((calc_type(r) * a) >> base_shift);
+ g = value_type((calc_type(g) * a) >> base_shift);
+ b = value_type((calc_type(b) * a) >> base_shift);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE const self_type& premultiply(unsigned a_)
+ {
+ if(a == base_mask && a_ >= base_mask) return *this;
+ if(a == 0 || a_ == 0)
+ {
+ r = g = b = a = 0;
+ return *this;
+ }
+ calc_type r_ = (calc_type(r) * a_) / a;
+ calc_type g_ = (calc_type(g) * a_) / a;
+ calc_type b_ = (calc_type(b) * a_) / a;
+ r = value_type((r_ > a_) ? a_ : r_);
+ g = value_type((g_ > a_) ? a_ : g_);
+ b = value_type((b_ > a_) ? a_ : b_);
+ a = value_type(a_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE const self_type& demultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ r = g = b = 0;
+ return *this;
+ }
+ calc_type r_ = (calc_type(r) * base_mask) / a;
+ calc_type g_ = (calc_type(g) * base_mask) / a;
+ calc_type b_ = (calc_type(b) * base_mask) / a;
+ r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
+ g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
+ b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE self_type gradient(const self_type& c, double k) const
+ {
+ self_type ret;
+ calc_type ik = uround(k * base_scale);
+ ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
+ ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
+ ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
+ ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ return ret;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void add(const self_type& c, unsigned cover)
+ {
+ calc_type cr, cg, cb, ca;
+ if(cover == cover_mask)
+ {
+ if(c.a == base_mask)
+ {
+ *this = c;
+ }
+ else
+ {
+ cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
+ cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
+ cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
+ ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+ else
+ {
+ cr = r + ((c.r * cover + cover_mask/2) >> cover_shift);
+ cg = g + ((c.g * cover + cover_mask/2) >> cover_shift);
+ cb = b + ((c.b * cover + cover_mask/2) >> cover_shift);
+ ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
+ r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
+ g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
+ b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
+ a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLUT>
+ AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
+ {
+ r = gamma.dir(r);
+ g = gamma.dir(g);
+ b = gamma.dir(b);
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLUT>
+ AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
+ {
+ r = gamma.inv(r);
+ g = gamma.inv(g);
+ b = gamma.inv(b);
+ }
+
+ //--------------------------------------------------------------------
+ static self_type no_color() { return self_type(0,0,0,0); }
+
+ //--------------------------------------------------------------------
+ static self_type from_wavelength(double wl, double gamma = 1.0)
+ {
+ return self_type(rgba::from_wavelength(wl, gamma));
+ }
+ };
+
+
+ //-------------------------------------------------------------rgba8_pre
+ inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
+ unsigned a = rgba8::base_mask)
+ {
+ return rgba8(r,g,b,a).premultiply();
+ }
+ inline rgba8 rgba8_pre(const rgba8& c)
+ {
+ return rgba8(c).premultiply();
+ }
+ inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
+ {
+ return rgba8(c,a).premultiply();
+ }
+ inline rgba8 rgba8_pre(const rgba& c)
+ {
+ return rgba8(c).premultiply();
+ }
+ inline rgba8 rgba8_pre(const rgba& c, double a)
+ {
+ return rgba8(c,a).premultiply();
+ }
+
+
+ //-------------------------------------------------------------rgb8_packed
+ inline rgba8 rgb8_packed(unsigned v)
+ {
+ return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
+ }
+
+ //-------------------------------------------------------------bgr8_packed
+ inline rgba8 bgr8_packed(unsigned v)
+ {
+ return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
+ }
+
+ //------------------------------------------------------------argb8_packed
+ inline rgba8 argb8_packed(unsigned v)
+ {
+ return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
+ }
+
+ //---------------------------------------------------------rgba8_gamma_dir
+ template<class GammaLUT>
+ rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma)
+ {
+ return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
+ }
+
+ //---------------------------------------------------------rgba8_gamma_inv
+ template<class GammaLUT>
+ rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma)
+ {
+ return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
+ }
+
+
+
+
+
+ //==================================================================rgba16
+ struct rgba16
+ {
+ typedef int16u value_type;
+ typedef int32u calc_type;
+ typedef int64 long_type;
+ enum base_scale_e
+ {
+ base_shift = 16,
+ base_scale = 1 << base_shift,
+ base_mask = base_scale - 1
+ };
+ typedef rgba16 self_type;
+
+ value_type r;
+ value_type g;
+ value_type b;
+ value_type a;
+
+ //--------------------------------------------------------------------
+ rgba16() {}
+
+ //--------------------------------------------------------------------
+ rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
+ r(value_type(r_)),
+ g(value_type(g_)),
+ b(value_type(b_)),
+ a(value_type(a_)) {}
+
+ //--------------------------------------------------------------------
+ rgba16(const self_type& c, unsigned a_) :
+ r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
+
+ //--------------------------------------------------------------------
+ rgba16(const rgba& c) :
+ r((value_type)uround(c.r * double(base_mask))),
+ g((value_type)uround(c.g * double(base_mask))),
+ b((value_type)uround(c.b * double(base_mask))),
+ a((value_type)uround(c.a * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ rgba16(const rgba& c, double a_) :
+ r((value_type)uround(c.r * double(base_mask))),
+ g((value_type)uround(c.g * double(base_mask))),
+ b((value_type)uround(c.b * double(base_mask))),
+ a((value_type)uround(a_ * double(base_mask))) {}
+
+ //--------------------------------------------------------------------
+ rgba16(const rgba8& c) :
+ r(value_type((value_type(c.r) << 8) | c.r)),
+ g(value_type((value_type(c.g) << 8) | c.g)),
+ b(value_type((value_type(c.b) << 8) | c.b)),
+ a(value_type((value_type(c.a) << 8) | c.a)) {}
+
+ //--------------------------------------------------------------------
+ rgba16(const rgba8& c, unsigned a_) :
+ r(value_type((value_type(c.r) << 8) | c.r)),
+ g(value_type((value_type(c.g) << 8) | c.g)),
+ b(value_type((value_type(c.b) << 8) | c.b)),
+ a(value_type(( a_ << 8) | c.a)) {}
+
+ //--------------------------------------------------------------------
+ void clear()
+ {
+ r = g = b = a = 0;
+ }
+
+ //--------------------------------------------------------------------
+ const self_type& transparent()
+ {
+ a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE const self_type& opacity(double a_)
+ {
+ if(a_ < 0.0) a_ = 0.0;
+ if(a_ > 1.0) a_ = 1.0;
+ a = (value_type)uround(a_ * double(base_mask));
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return double(a) / double(base_mask);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE const self_type& premultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ r = g = b = 0;
+ return *this;
+ }
+ r = value_type((calc_type(r) * a) >> base_shift);
+ g = value_type((calc_type(g) * a) >> base_shift);
+ b = value_type((calc_type(b) * a) >> base_shift);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE const self_type& premultiply(unsigned a_)
+ {
+ if(a == base_mask && a_ >= base_mask) return *this;
+ if(a == 0 || a_ == 0)
+ {
+ r = g = b = a = 0;
+ return *this;
+ }
+ calc_type r_ = (calc_type(r) * a_) / a;
+ calc_type g_ = (calc_type(g) * a_) / a;
+ calc_type b_ = (calc_type(b) * a_) / a;
+ r = value_type((r_ > a_) ? a_ : r_);
+ g = value_type((g_ > a_) ? a_ : g_);
+ b = value_type((b_ > a_) ? a_ : b_);
+ a = value_type(a_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE const self_type& demultiply()
+ {
+ if(a == base_mask) return *this;
+ if(a == 0)
+ {
+ r = g = b = 0;
+ return *this;
+ }
+ calc_type r_ = (calc_type(r) * base_mask) / a;
+ calc_type g_ = (calc_type(g) * base_mask) / a;
+ calc_type b_ = (calc_type(b) * base_mask) / a;
+ r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
+ g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
+ b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE self_type gradient(const self_type& c, double k) const
+ {
+ self_type ret;
+ calc_type ik = uround(k * base_scale);
+ ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
+ ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
+ ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
+ ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ return ret;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void add(const self_type& c, unsigned cover)
+ {
+ calc_type cr, cg, cb, ca;
+ if(cover == cover_mask)
+ {
+ if(c.a == base_mask)
+ {
+ *this = c;
+ }
+ else
+ {
+ cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
+ cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
+ cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
+ ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+ else
+ {
+ cr = r + ((c.r * cover + cover_mask) >> cover_shift);
+ cg = g + ((c.g * cover + cover_mask) >> cover_shift);
+ cb = b + ((c.b * cover + cover_mask) >> cover_shift);
+ ca = a + ((c.a * cover + cover_mask) >> cover_shift);
+ r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
+ g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
+ b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
+ a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLUT>
+ AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
+ {
+ r = gamma.dir(r);
+ g = gamma.dir(g);
+ b = gamma.dir(b);
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLUT>
+ AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
+ {
+ r = gamma.inv(r);
+ g = gamma.inv(g);
+ b = gamma.inv(b);
+ }
+
+ //--------------------------------------------------------------------
+ static self_type no_color() { return self_type(0,0,0,0); }
+
+ //--------------------------------------------------------------------
+ static self_type from_wavelength(double wl, double gamma = 1.0)
+ {
+ return self_type(rgba::from_wavelength(wl, gamma));
+ }
+ };
+
+
+
+ //--------------------------------------------------------------rgba16_pre
+ inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b,
+ unsigned a = rgba16::base_mask)
+ {
+ return rgba16(r,g,b,a).premultiply();
+ }
+ inline rgba16 rgba16_pre(const rgba16& c, unsigned a)
+ {
+ return rgba16(c,a).premultiply();
+ }
+ inline rgba16 rgba16_pre(const rgba& c)
+ {
+ return rgba16(c).premultiply();
+ }
+ inline rgba16 rgba16_pre(const rgba& c, double a)
+ {
+ return rgba16(c,a).premultiply();
+ }
+ inline rgba16 rgba16_pre(const rgba8& c)
+ {
+ return rgba16(c).premultiply();
+ }
+ inline rgba16 rgba16_pre(const rgba8& c, unsigned a)
+ {
+ return rgba16(c,a).premultiply();
+ }
+
+
+ //------------------------------------------------------rgba16_gamma_dir
+ template<class GammaLUT>
+ rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
+ {
+ return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
+ }
+
+ //------------------------------------------------------rgba16_gamma_inv
+ template<class GammaLUT>
+ rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma)
+ {
+ return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
+ }
+
+
+}
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_config.h b/plugins/Clist_ng/AGG/include/agg_config.h new file mode 100644 index 0000000000..372b77bfc7 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_config.h @@ -0,0 +1,44 @@ +#ifndef AGG_CONFIG_INCLUDED
+#define AGG_CONFIG_INCLUDED
+
+// This file can be used to redefine certain data types.
+
+//---------------------------------------
+// 1. Default basic types such as:
+//
+// AGG_INT8
+// AGG_INT8U
+// AGG_INT16
+// AGG_INT16U
+// AGG_INT32
+// AGG_INT32U
+// AGG_INT64
+// AGG_INT64U
+//
+// Just replace this file with new defines if necessary.
+// For example, if your compiler doesn't have a 64 bit integer type
+// you can still use AGG if you define the follows:
+//
+// #define AGG_INT64 int
+// #define AGG_INT64U unsigned
+//
+// It will result in overflow in 16 bit-per-component image/pattern resampling
+// but it won't result any crash and the rest of the library will remain
+// fully functional.
+
+
+//---------------------------------------
+// 2. Default rendering_buffer type. Can be:
+//
+// Provides faster access for massive pixel operations,
+// such as blur, image filtering:
+// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
+//
+// Provides cheaper creation and destruction (no mem allocs):
+// #define AGG_RENDERING_BUFFER row_accessor<int8u>
+//
+// You can still use both of them simultaneouslyin your applications
+// This #define is used only for default rendering_buffer type,
+// in short hand typedefs like pixfmt_rgba32.
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_adaptor_vcgen.h b/plugins/Clist_ng/AGG/include/agg_conv_adaptor_vcgen.h new file mode 100644 index 0000000000..9719c715ea --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_adaptor_vcgen.h @@ -0,0 +1,166 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
+#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //------------------------------------------------------------null_markers
+ struct null_markers
+ {
+ void remove_all() {}
+ void add_vertex(double, double, unsigned) {}
+ void prepare_src() {}
+
+ void rewind(unsigned) {}
+ unsigned vertex(double*, double*) { return path_cmd_stop; }
+ };
+
+
+ //------------------------------------------------------conv_adaptor_vcgen
+ template<class VertexSource,
+ class Generator,
+ class Markers=null_markers> class conv_adaptor_vcgen
+ {
+ enum status
+ {
+ initial,
+ accumulate,
+ generate
+ };
+
+ public:
+ explicit conv_adaptor_vcgen(VertexSource& source) :
+ m_source(&source),
+ m_status(initial)
+ {}
+ void attach(VertexSource& source) { m_source = &source; }
+
+ Generator& generator() { return m_generator; }
+ const Generator& generator() const { return m_generator; }
+
+ Markers& markers() { return m_markers; }
+ const Markers& markers() const { return m_markers; }
+
+ void rewind(unsigned path_id)
+ {
+ m_source->rewind(path_id);
+ m_status = initial;
+ }
+
+ unsigned vertex(double* x, double* y);
+
+ private:
+ // Prohibit copying
+ conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
+ const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
+ operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
+
+ VertexSource* m_source;
+ Generator m_generator;
+ Markers m_markers;
+ status m_status;
+ unsigned m_last_cmd;
+ double m_start_x;
+ double m_start_y;
+ };
+
+
+
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource, class Generator, class Markers>
+ unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_stop;
+ bool done = false;
+ while(!done)
+ {
+ switch(m_status)
+ {
+ case initial:
+ m_markers.remove_all();
+ m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
+ m_status = accumulate;
+
+ case accumulate:
+ if(is_stop(m_last_cmd)) return path_cmd_stop;
+
+ m_generator.remove_all();
+ m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
+ m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
+
+ for(;;)
+ {
+ cmd = m_source->vertex(x, y);
+ if(is_vertex(cmd))
+ {
+ m_last_cmd = cmd;
+ if(is_move_to(cmd))
+ {
+ m_start_x = *x;
+ m_start_y = *y;
+ break;
+ }
+ m_generator.add_vertex(*x, *y, cmd);
+ m_markers.add_vertex(*x, *y, path_cmd_line_to);
+ }
+ else
+ {
+ if(is_stop(cmd))
+ {
+ m_last_cmd = path_cmd_stop;
+ break;
+ }
+ if(is_end_poly(cmd))
+ {
+ m_generator.add_vertex(*x, *y, cmd);
+ break;
+ }
+ }
+ }
+ m_generator.rewind(0);
+ m_status = generate;
+
+ case generate:
+ cmd = m_generator.vertex(x, y);
+ if(is_stop(cmd))
+ {
+ m_status = accumulate;
+ break;
+ }
+ done = true;
+ break;
+ }
+ }
+ return cmd;
+ }
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_adaptor_vpgen.h b/plugins/Clist_ng/AGG/include/agg_conv_adaptor_vpgen.h new file mode 100644 index 0000000000..2243e1e873 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_adaptor_vpgen.h @@ -0,0 +1,168 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
+#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //======================================================conv_adaptor_vpgen
+ template<class VertexSource, class VPGen> class conv_adaptor_vpgen
+ {
+ public:
+ explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
+ void attach(VertexSource& source) { m_source = &source; }
+
+ VPGen& vpgen() { return m_vpgen; }
+ const VPGen& vpgen() const { return m_vpgen; }
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
+ const conv_adaptor_vpgen<VertexSource, VPGen>&
+ operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
+
+ VertexSource* m_source;
+ VPGen m_vpgen;
+ double m_start_x;
+ double m_start_y;
+ unsigned m_poly_flags;
+ int m_vertices;
+ };
+
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource, class VPGen>
+ void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
+ {
+ m_source->rewind(path_id);
+ m_vpgen.reset();
+ m_start_x = 0;
+ m_start_y = 0;
+ m_poly_flags = 0;
+ m_vertices = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource, class VPGen>
+ unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_stop;
+ for(;;)
+ {
+ cmd = m_vpgen.vertex(x, y);
+ if(!is_stop(cmd)) break;
+
+ if(m_poly_flags && !m_vpgen.auto_unclose())
+ {
+ *x = 0.0;
+ *y = 0.0;
+ cmd = m_poly_flags;
+ m_poly_flags = 0;
+ break;
+ }
+
+ if(m_vertices < 0)
+ {
+ if(m_vertices < -1)
+ {
+ m_vertices = 0;
+ return path_cmd_stop;
+ }
+ m_vpgen.move_to(m_start_x, m_start_y);
+ m_vertices = 1;
+ continue;
+ }
+
+ double tx, ty;
+ cmd = m_source->vertex(&tx, &ty);
+ if(is_vertex(cmd))
+ {
+ if(is_move_to(cmd))
+ {
+ if(m_vpgen.auto_close() && m_vertices > 2)
+ {
+ m_vpgen.line_to(m_start_x, m_start_y);
+ m_poly_flags = path_cmd_end_poly | path_flags_close;
+ m_start_x = tx;
+ m_start_y = ty;
+ m_vertices = -1;
+ continue;
+ }
+ m_vpgen.move_to(tx, ty);
+ m_start_x = tx;
+ m_start_y = ty;
+ m_vertices = 1;
+ }
+ else
+ {
+ m_vpgen.line_to(tx, ty);
+ ++m_vertices;
+ }
+ }
+ else
+ {
+ if(is_end_poly(cmd))
+ {
+ m_poly_flags = cmd;
+ if(is_closed(cmd) || m_vpgen.auto_close())
+ {
+ if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
+ if(m_vertices > 2)
+ {
+ m_vpgen.line_to(m_start_x, m_start_y);
+ }
+ m_vertices = 0;
+ }
+ }
+ else
+ {
+ // path_cmd_stop
+ if(m_vpgen.auto_close() && m_vertices > 2)
+ {
+ m_vpgen.line_to(m_start_x, m_start_y);
+ m_poly_flags = path_cmd_end_poly | path_flags_close;
+ m_vertices = -2;
+ continue;
+ }
+ break;
+ }
+ }
+ }
+ return cmd;
+ }
+
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_bspline.h b/plugins/Clist_ng/AGG/include/agg_conv_bspline.h new file mode 100644 index 0000000000..ff5fb751f3 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_bspline.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_BSPLINE_INCLUDED
+#define AGG_CONV_BSPLINE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vcgen_bspline.h"
+#include "agg_conv_adaptor_vcgen.h"
+
+
+namespace agg
+{
+
+ //---------------------------------------------------------conv_bspline
+ template<class VertexSource>
+ struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
+ {
+ typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
+
+ conv_bspline(VertexSource& vs) :
+ conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
+
+ void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
+ double interpolation_step() const { return base_type::generator().interpolation_step(); }
+
+ private:
+ conv_bspline(const conv_bspline<VertexSource>&);
+ const conv_bspline<VertexSource>&
+ operator = (const conv_bspline<VertexSource>&);
+ };
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_clip_polygon.h b/plugins/Clist_ng/AGG/include/agg_conv_clip_polygon.h new file mode 100644 index 0000000000..e1e9d45a3c --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_clip_polygon.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Polygon clipping converter
+// There an optimized Liang-Basky algorithm is used.
+// The algorithm doesn't optimize the degenerate edges, i.e. it will never
+// break a closed polygon into two or more ones, instead, there will be
+// degenerate edges coinciding with the respective clipping boundaries.
+// This is a sub-optimal solution, because that optimization would require
+// extra, rather expensive math while the rasterizer tolerates it quite well,
+// without any considerable overhead.
+//
+//----------------------------------------------------------------------------
+#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
+#define AGG_CONV_CLIP_POLYGON_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_conv_adaptor_vpgen.h"
+#include "agg_vpgen_clip_polygon.h"
+
+namespace agg
+{
+
+ //=======================================================conv_clip_polygon
+ template<class VertexSource>
+ struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
+ {
+ typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
+
+ conv_clip_polygon(VertexSource& vs) :
+ conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
+
+ void clip_box(double x1, double y1, double x2, double y2)
+ {
+ base_type::vpgen().clip_box(x1, y1, x2, y2);
+ }
+
+ double x1() const { return base_type::vpgen().x1(); }
+ double y1() const { return base_type::vpgen().y1(); }
+ double x2() const { return base_type::vpgen().x2(); }
+ double y2() const { return base_type::vpgen().y2(); }
+
+ private:
+ conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
+ const conv_clip_polygon<VertexSource>&
+ operator = (const conv_clip_polygon<VertexSource>&);
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_clip_polyline.h b/plugins/Clist_ng/AGG/include/agg_conv_clip_polyline.h new file mode 100644 index 0000000000..7614f7eb3d --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_clip_polyline.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// polyline clipping converter
+// There an optimized Liang-Basky algorithm is used.
+// The algorithm doesn't optimize the degenerate edges, i.e. it will never
+// break a closed polyline into two or more ones, instead, there will be
+// degenerate edges coinciding with the respective clipping boundaries.
+// This is a sub-optimal solution, because that optimization would require
+// extra, rather expensive math while the rasterizer tolerates it quite well,
+// without any considerable overhead.
+//
+//----------------------------------------------------------------------------
+#ifndef AGG_CONV_CLIP_polyline_INCLUDED
+#define AGG_CONV_CLIP_polyline_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_conv_adaptor_vpgen.h"
+#include "agg_vpgen_clip_polyline.h"
+
+namespace agg
+{
+
+ //=======================================================conv_clip_polyline
+ template<class VertexSource>
+ struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
+ {
+ typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
+
+ conv_clip_polyline(VertexSource& vs) :
+ conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
+
+ void clip_box(double x1, double y1, double x2, double y2)
+ {
+ base_type::vpgen().clip_box(x1, y1, x2, y2);
+ }
+
+ double x1() const { return base_type::vpgen().x1(); }
+ double y1() const { return base_type::vpgen().y1(); }
+ double x2() const { return base_type::vpgen().x2(); }
+ double y2() const { return base_type::vpgen().y2(); }
+
+ private:
+ conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
+ const conv_clip_polyline<VertexSource>&
+ operator = (const conv_clip_polyline<VertexSource>&);
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_close_polygon.h b/plugins/Clist_ng/AGG/include/agg_conv_close_polygon.h new file mode 100644 index 0000000000..e50deed62e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_close_polygon.h @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
+#define AGG_CONV_CLOSE_POLYGON_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //======================================================conv_close_polygon
+ template<class VertexSource> class conv_close_polygon
+ {
+ public:
+ explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
+ void attach(VertexSource& source) { m_source = &source; }
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ conv_close_polygon(const conv_close_polygon<VertexSource>&);
+ const conv_close_polygon<VertexSource>&
+ operator = (const conv_close_polygon<VertexSource>&);
+
+ VertexSource* m_source;
+ unsigned m_cmd[2];
+ double m_x[2];
+ double m_y[2];
+ unsigned m_vertex;
+ bool m_line_to;
+ };
+
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource>
+ void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
+ {
+ m_source->rewind(path_id);
+ m_vertex = 2;
+ m_line_to = false;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource>
+ unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_stop;
+ for(;;)
+ {
+ if(m_vertex < 2)
+ {
+ *x = m_x[m_vertex];
+ *y = m_y[m_vertex];
+ cmd = m_cmd[m_vertex];
+ ++m_vertex;
+ break;
+ }
+
+ cmd = m_source->vertex(x, y);
+
+ if(is_end_poly(cmd))
+ {
+ cmd |= path_flags_close;
+ break;
+ }
+
+ if(is_stop(cmd))
+ {
+ if(m_line_to)
+ {
+ m_cmd[0] = path_cmd_end_poly | path_flags_close;
+ m_cmd[1] = path_cmd_stop;
+ m_vertex = 0;
+ m_line_to = false;
+ continue;
+ }
+ break;
+ }
+
+ if(is_move_to(cmd))
+ {
+ if(m_line_to)
+ {
+ m_x[0] = 0.0;
+ m_y[0] = 0.0;
+ m_cmd[0] = path_cmd_end_poly | path_flags_close;
+ m_x[1] = *x;
+ m_y[1] = *y;
+ m_cmd[1] = cmd;
+ m_vertex = 0;
+ m_line_to = false;
+ continue;
+ }
+ break;
+ }
+
+ if(is_vertex(cmd))
+ {
+ m_line_to = true;
+ break;
+ }
+ }
+ return cmd;
+ }
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_concat.h b/plugins/Clist_ng/AGG/include/agg_conv_concat.h new file mode 100644 index 0000000000..72ff0fc685 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_concat.h @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_CONCAT_INCLUDED
+#define AGG_CONV_CONCAT_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //=============================================================conv_concat
+ // Concatenation of two paths. Usually used to combine lines or curves
+ // with markers such as arrowheads
+ template<class VS1, class VS2> class conv_concat
+ {
+ public:
+ conv_concat(VS1& source1, VS2& source2) :
+ m_source1(&source1), m_source2(&source2), m_status(2) {}
+ void attach1(VS1& source) { m_source1 = &source; }
+ void attach2(VS2& source) { m_source2 = &source; }
+
+
+ void rewind(unsigned path_id)
+ {
+ m_source1->rewind(path_id);
+ m_source2->rewind(0);
+ m_status = 0;
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ unsigned cmd;
+ if(m_status == 0)
+ {
+ cmd = m_source1->vertex(x, y);
+ if(!is_stop(cmd)) return cmd;
+ m_status = 1;
+ }
+ if(m_status == 1)
+ {
+ cmd = m_source2->vertex(x, y);
+ if(!is_stop(cmd)) return cmd;
+ m_status = 2;
+ }
+ return path_cmd_stop;
+ }
+
+ private:
+ conv_concat(const conv_concat<VS1, VS2>&);
+ const conv_concat<VS1, VS2>&
+ operator = (const conv_concat<VS1, VS2>&);
+
+ VS1* m_source1;
+ VS2* m_source2;
+ int m_status;
+
+ };
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_contour.h b/plugins/Clist_ng/AGG/include/agg_conv_contour.h new file mode 100644 index 0000000000..ae05b02a11 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_contour.h @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_CONTOUR_INCLUDED
+#define AGG_CONV_CONTOUR_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vcgen_contour.h"
+#include "agg_conv_adaptor_vcgen.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------------------conv_contour
+ template<class VertexSource>
+ struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
+ {
+ typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
+
+ conv_contour(VertexSource& vs) :
+ conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
+ {
+ }
+
+ void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
+ void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
+ void width(double w) { base_type::generator().width(w); }
+ void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
+ void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
+ void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
+ void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
+ void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
+
+ line_join_e line_join() const { return base_type::generator().line_join(); }
+ inner_join_e inner_join() const { return base_type::generator().inner_join(); }
+ double width() const { return base_type::generator().width(); }
+ double miter_limit() const { return base_type::generator().miter_limit(); }
+ double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
+ double approximation_scale() const { return base_type::generator().approximation_scale(); }
+ bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
+
+ private:
+ conv_contour(const conv_contour<VertexSource>&);
+ const conv_contour<VertexSource>&
+ operator = (const conv_contour<VertexSource>&);
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_curve.h b/plugins/Clist_ng/AGG/include/agg_conv_curve.h new file mode 100644 index 0000000000..504bd4709b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_curve.h @@ -0,0 +1,206 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_CURVE_INCLUDED
+#define AGG_CONV_CURVE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_curves.h"
+
+namespace agg
+{
+
+
+ //---------------------------------------------------------------conv_curve
+ // Curve converter class. Any path storage can have Bezier curves defined
+ // by their control points. There're two types of curves supported: curve3
+ // and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
+ // point. Curve4 has 2 control points (4 points in total) and can be used
+ // to interpolate more complicated curves. Curve4, unlike curve3 can be used
+ // to approximate arcs, both circular and elliptical. Curves are approximated
+ // with straight lines and one of the approaches is just to store the whole
+ // sequence of vertices that approximate our curve. It takes additional
+ // memory, and at the same time the consecutive vertices can be calculated
+ // on demand.
+ //
+ // Initially, path storages are not suppose to keep all the vertices of the
+ // curves (although, nothing prevents us from doing so). Instead, path_storage
+ // keeps only vertices, needed to calculate a curve on demand. Those vertices
+ // are marked with special commands. So, if the path_storage contains curves
+ // (which are not real curves yet), and we render this storage directly,
+ // all we will see is only 2 or 3 straight line segments (for curve3 and
+ // curve4 respectively). If we need to see real curves drawn we need to
+ // include this class into the conversion pipeline.
+ //
+ // Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
+ // and converts these vertices into a move_to/line_to sequence.
+ //-----------------------------------------------------------------------
+ template<class VertexSource,
+ class Curve3=curve3,
+ class Curve4=curve4> class conv_curve
+ {
+ public:
+ typedef Curve3 curve3_type;
+ typedef Curve4 curve4_type;
+ typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
+
+ explicit conv_curve(VertexSource& source) :
+ m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
+ void attach(VertexSource& source) { m_source = &source; }
+
+ void approximation_method(curve_approximation_method_e v)
+ {
+ m_curve3.approximation_method(v);
+ m_curve4.approximation_method(v);
+ }
+
+ curve_approximation_method_e approximation_method() const
+ {
+ return m_curve4.approximation_method();
+ }
+
+ void approximation_scale(double s)
+ {
+ m_curve3.approximation_scale(s);
+ m_curve4.approximation_scale(s);
+ }
+
+ double approximation_scale() const
+ {
+ return m_curve4.approximation_scale();
+ }
+
+ void angle_tolerance(double v)
+ {
+ m_curve3.angle_tolerance(v);
+ m_curve4.angle_tolerance(v);
+ }
+
+ double angle_tolerance() const
+ {
+ return m_curve4.angle_tolerance();
+ }
+
+ void cusp_limit(double v)
+ {
+ m_curve3.cusp_limit(v);
+ m_curve4.cusp_limit(v);
+ }
+
+ double cusp_limit() const
+ {
+ return m_curve4.cusp_limit();
+ }
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ conv_curve(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ VertexSource* m_source;
+ double m_last_x;
+ double m_last_y;
+ curve3_type m_curve3;
+ curve4_type m_curve4;
+ };
+
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource, class Curve3, class Curve4>
+ void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
+ {
+ m_source->rewind(path_id);
+ m_last_x = 0.0;
+ m_last_y = 0.0;
+ m_curve3.reset();
+ m_curve4.reset();
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource, class Curve3, class Curve4>
+ unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
+ {
+ if(!is_stop(m_curve3.vertex(x, y)))
+ {
+ m_last_x = *x;
+ m_last_y = *y;
+ return path_cmd_line_to;
+ }
+
+ if(!is_stop(m_curve4.vertex(x, y)))
+ {
+ m_last_x = *x;
+ m_last_y = *y;
+ return path_cmd_line_to;
+ }
+
+ double ct2_x;
+ double ct2_y;
+ double end_x;
+ double end_y;
+
+ unsigned cmd = m_source->vertex(x, y);
+ switch(cmd)
+ {
+ case path_cmd_curve3:
+ m_source->vertex(&end_x, &end_y);
+
+ m_curve3.init(m_last_x, m_last_y,
+ *x, *y,
+ end_x, end_y);
+
+ m_curve3.vertex(x, y); // First call returns path_cmd_move_to
+ m_curve3.vertex(x, y); // This is the first vertex of the curve
+ cmd = path_cmd_line_to;
+ break;
+
+ case path_cmd_curve4:
+ m_source->vertex(&ct2_x, &ct2_y);
+ m_source->vertex(&end_x, &end_y);
+
+ m_curve4.init(m_last_x, m_last_y,
+ *x, *y,
+ ct2_x, ct2_y,
+ end_x, end_y);
+
+ m_curve4.vertex(x, y); // First call returns path_cmd_move_to
+ m_curve4.vertex(x, y); // This is the first vertex of the curve
+ cmd = path_cmd_line_to;
+ break;
+ }
+ m_last_x = *x;
+ m_last_y = *y;
+ return cmd;
+ }
+
+
+}
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_dash.h b/plugins/Clist_ng/AGG/include/agg_conv_dash.h new file mode 100644 index 0000000000..c3f1613b16 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_dash.h @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_DASH_INCLUDED
+#define AGG_CONV_DASH_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vcgen_dash.h"
+#include "agg_conv_adaptor_vcgen.h"
+
+namespace agg
+{
+
+ //---------------------------------------------------------------conv_dash
+ template<class VertexSource, class Markers=null_markers>
+ struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>
+ {
+ typedef Markers marker_type;
+ typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type;
+
+ conv_dash(VertexSource& vs) :
+ conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
+ {
+ }
+
+ void remove_all_dashes()
+ {
+ base_type::generator().remove_all_dashes();
+ }
+
+ void add_dash(double dash_len, double gap_len)
+ {
+ base_type::generator().add_dash(dash_len, gap_len);
+ }
+
+ void dash_start(double ds)
+ {
+ base_type::generator().dash_start(ds);
+ }
+
+ void shorten(double s) { base_type::generator().shorten(s); }
+ double shorten() const { return base_type::generator().shorten(); }
+
+ private:
+ conv_dash(const conv_dash<VertexSource, Markers>&);
+ const conv_dash<VertexSource, Markers>&
+ operator = (const conv_dash<VertexSource, Markers>&);
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_gpc.h b/plugins/Clist_ng/AGG/include/agg_conv_gpc.h new file mode 100644 index 0000000000..c837c08cc7 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_gpc.h @@ -0,0 +1,441 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// General Polygon Clipper based on the GPC library by Alan Murta
+// Union, Intersection, XOR, A-B, B-A
+// Contact the author if you intend to use it in commercial applications!
+// http://www.cs.man.ac.uk/aig/staff/alan/software/
+// Alan Murta (email: gpc@cs.man.ac.uk)
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_GPC_INCLUDED
+#define AGG_CONV_GPC_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+#include "agg_array.h"
+
+extern "C"
+{
+#include "gpc.h"
+}
+
+namespace agg
+{
+ enum gpc_op_e
+ {
+ gpc_or,
+ gpc_and,
+ gpc_xor,
+ gpc_a_minus_b,
+ gpc_b_minus_a
+ };
+
+
+ //================================================================conv_gpc
+ template<class VSA, class VSB> class conv_gpc
+ {
+ enum status
+ {
+ status_move_to,
+ status_line_to,
+ status_stop
+ };
+
+ struct contour_header_type
+ {
+ int num_vertices;
+ int hole_flag;
+ gpc_vertex* vertices;
+ };
+
+ typedef pod_bvector<gpc_vertex, 8> vertex_array_type;
+ typedef pod_bvector<contour_header_type, 6> contour_header_array_type;
+
+
+ public:
+ typedef VSA source_a_type;
+ typedef VSB source_b_type;
+ typedef conv_gpc<source_a_type, source_b_type> self_type;
+
+ ~conv_gpc()
+ {
+ free_gpc_data();
+ }
+
+ conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
+ m_src_a(&a),
+ m_src_b(&b),
+ m_status(status_move_to),
+ m_vertex(-1),
+ m_contour(-1),
+ m_operation(op)
+ {
+ memset(&m_poly_a, 0, sizeof(m_poly_a));
+ memset(&m_poly_b, 0, sizeof(m_poly_b));
+ memset(&m_result, 0, sizeof(m_result));
+ }
+
+ void attach1(VSA& source) { m_src_a = &source; }
+ void attach2(VSB& source) { m_src_b = &source; }
+
+ void operation(gpc_op_e v) { m_operation = v; }
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ conv_gpc(const conv_gpc<VSA, VSB>&);
+ const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
+
+ //--------------------------------------------------------------------
+ void free_polygon(gpc_polygon& p);
+ void free_result();
+ void free_gpc_data();
+ void start_contour();
+ void add_vertex(double x, double y);
+ void end_contour(unsigned orientation);
+ void make_polygon(gpc_polygon& p);
+ void start_extracting();
+ bool next_contour();
+ bool next_vertex(double* x, double* y);
+
+
+ //--------------------------------------------------------------------
+ template<class VS> void add(VS& src, gpc_polygon& p)
+ {
+ unsigned cmd;
+ double x, y;
+ double start_x = 0.0;
+ double start_y = 0.0;
+ bool line_to = false;
+ unsigned orientation = 0;
+
+ m_contour_accumulator.remove_all();
+
+ while(!is_stop(cmd = src.vertex(&x, &y)))
+ {
+ if(is_vertex(cmd))
+ {
+ if(is_move_to(cmd))
+ {
+ if(line_to)
+ {
+ end_contour(orientation);
+ orientation = 0;
+ }
+ start_contour();
+ start_x = x;
+ start_y = y;
+ }
+ add_vertex(x, y);
+ line_to = true;
+ }
+ else
+ {
+ if(is_end_poly(cmd))
+ {
+ orientation = get_orientation(cmd);
+ if(line_to && is_closed(cmd))
+ {
+ add_vertex(start_x, start_y);
+ }
+ }
+ }
+ }
+ if(line_to)
+ {
+ end_contour(orientation);
+ }
+ make_polygon(p);
+ }
+
+
+ private:
+ //--------------------------------------------------------------------
+ source_a_type* m_src_a;
+ source_b_type* m_src_b;
+ status m_status;
+ int m_vertex;
+ int m_contour;
+ gpc_op_e m_operation;
+ vertex_array_type m_vertex_accumulator;
+ contour_header_array_type m_contour_accumulator;
+ gpc_polygon m_poly_a;
+ gpc_polygon m_poly_b;
+ gpc_polygon m_result;
+ };
+
+
+
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
+ {
+ int i;
+ for(i = 0; i < p.num_contours; i++)
+ {
+ pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex,
+ p.contour[i].num_vertices);
+ }
+ pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
+ memset(&p, 0, sizeof(gpc_polygon));
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::free_result()
+ {
+ if(m_result.contour)
+ {
+ gpc_free_polygon(&m_result);
+ }
+ memset(&m_result, 0, sizeof(m_result));
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::free_gpc_data()
+ {
+ free_polygon(m_poly_a);
+ free_polygon(m_poly_b);
+ free_result();
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::start_contour()
+ {
+ contour_header_type h;
+ memset(&h, 0, sizeof(h));
+ m_contour_accumulator.add(h);
+ m_vertex_accumulator.remove_all();
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
+ {
+ gpc_vertex v;
+ v.x = x;
+ v.y = y;
+ m_vertex_accumulator.add(v);
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)
+ {
+ if(m_contour_accumulator.size())
+ {
+ if(m_vertex_accumulator.size() > 2)
+ {
+ contour_header_type& h =
+ m_contour_accumulator[m_contour_accumulator.size() - 1];
+
+ h.num_vertices = m_vertex_accumulator.size();
+ h.hole_flag = 0;
+
+ // TO DO: Clarify the "holes"
+ //if(is_cw(orientation)) h.hole_flag = 1;
+
+ h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices);
+ gpc_vertex* d = h.vertices;
+ int i;
+ for(i = 0; i < h.num_vertices; i++)
+ {
+ const gpc_vertex& s = m_vertex_accumulator[i];
+ d->x = s.x;
+ d->y = s.y;
+ ++d;
+ }
+ }
+ else
+ {
+ m_vertex_accumulator.remove_last();
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
+ {
+ free_polygon(p);
+ if(m_contour_accumulator.size())
+ {
+ p.num_contours = m_contour_accumulator.size();
+
+ p.hole = 0;
+ p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
+
+ int i;
+ gpc_vertex_list* pv = p.contour;
+ for(i = 0; i < p.num_contours; i++)
+ {
+ const contour_header_type& h = m_contour_accumulator[i];
+ pv->num_vertices = h.num_vertices;
+ pv->vertex = h.vertices;
+ ++pv;
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::start_extracting()
+ {
+ m_status = status_move_to;
+ m_contour = -1;
+ m_vertex = -1;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ bool conv_gpc<VSA, VSB>::next_contour()
+ {
+ if(++m_contour < m_result.num_contours)
+ {
+ m_vertex = -1;
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
+ {
+ const gpc_vertex_list& vlist = m_result.contour[m_contour];
+ if(++m_vertex < vlist.num_vertices)
+ {
+ const gpc_vertex& v = vlist.vertex[m_vertex];
+ *x = v.x;
+ *y = v.y;
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ void conv_gpc<VSA, VSB>::rewind(unsigned path_id)
+ {
+ free_result();
+ m_src_a->rewind(path_id);
+ m_src_b->rewind(path_id);
+ add(*m_src_a, m_poly_a);
+ add(*m_src_b, m_poly_b);
+ switch(m_operation)
+ {
+ case gpc_or:
+ gpc_polygon_clip(GPC_UNION,
+ &m_poly_a,
+ &m_poly_b,
+ &m_result);
+ break;
+
+ case gpc_and:
+ gpc_polygon_clip(GPC_INT,
+ &m_poly_a,
+ &m_poly_b,
+ &m_result);
+ break;
+
+ case gpc_xor:
+ gpc_polygon_clip(GPC_XOR,
+ &m_poly_a,
+ &m_poly_b,
+ &m_result);
+ break;
+
+ case gpc_a_minus_b:
+ gpc_polygon_clip(GPC_DIFF,
+ &m_poly_a,
+ &m_poly_b,
+ &m_result);
+ break;
+
+ case gpc_b_minus_a:
+ gpc_polygon_clip(GPC_DIFF,
+ &m_poly_b,
+ &m_poly_a,
+ &m_result);
+ break;
+ }
+ start_extracting();
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VSA, class VSB>
+ unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
+ {
+ if(m_status == status_move_to)
+ {
+ if(next_contour())
+ {
+ if(next_vertex(x, y))
+ {
+ m_status = status_line_to;
+ return path_cmd_move_to;
+ }
+ m_status = status_stop;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ }
+ else
+ {
+ if(next_vertex(x, y))
+ {
+ return path_cmd_line_to;
+ }
+ else
+ {
+ m_status = status_move_to;
+ }
+ return path_cmd_end_poly | path_flags_close;
+ }
+ return path_cmd_stop;
+ }
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_marker.h b/plugins/Clist_ng/AGG/include/agg_conv_marker.h new file mode 100644 index 0000000000..69f8f7bde1 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_marker.h @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_MARKER_INCLUDED
+#define AGG_CONV_MARKER_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_trans_affine.h"
+
+namespace agg
+{
+ //-------------------------------------------------------------conv_marker
+ template<class MarkerLocator, class MarkerShapes>
+ class conv_marker
+ {
+ public:
+ conv_marker(MarkerLocator& ml, MarkerShapes& ms);
+
+ trans_affine& transform() { return m_transform; }
+ const trans_affine& transform() const { return m_transform; }
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
+ const conv_marker<MarkerLocator, MarkerShapes>&
+ operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
+
+ enum status_e
+ {
+ initial,
+ markers,
+ polygon,
+ stop
+ };
+
+ MarkerLocator* m_marker_locator;
+ MarkerShapes* m_marker_shapes;
+ trans_affine m_transform;
+ trans_affine m_mtx;
+ status_e m_status;
+ unsigned m_marker;
+ unsigned m_num_markers;
+ };
+
+
+ //------------------------------------------------------------------------
+ template<class MarkerLocator, class MarkerShapes>
+ conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
+ m_marker_locator(&ml),
+ m_marker_shapes(&ms),
+ m_status(initial),
+ m_marker(0),
+ m_num_markers(1)
+ {
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class MarkerLocator, class MarkerShapes>
+ void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
+ {
+ m_status = initial;
+ m_marker = 0;
+ m_num_markers = 1;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class MarkerLocator, class MarkerShapes>
+ unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_move_to;
+ double x1, y1, x2, y2;
+
+ while(!is_stop(cmd))
+ {
+ switch(m_status)
+ {
+ case initial:
+ if(m_num_markers == 0)
+ {
+ cmd = path_cmd_stop;
+ break;
+ }
+ m_marker_locator->rewind(m_marker);
+ ++m_marker;
+ m_num_markers = 0;
+ m_status = markers;
+
+ case markers:
+ if(is_stop(m_marker_locator->vertex(&x1, &y1)))
+ {
+ m_status = initial;
+ break;
+ }
+ if(is_stop(m_marker_locator->vertex(&x2, &y2)))
+ {
+ m_status = initial;
+ break;
+ }
+ ++m_num_markers;
+ m_mtx = m_transform;
+ m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1));
+ m_mtx *= trans_affine_translation(x1, y1);
+ m_marker_shapes->rewind(m_marker - 1);
+ m_status = polygon;
+
+ case polygon:
+ cmd = m_marker_shapes->vertex(x, y);
+ if(is_stop(cmd))
+ {
+ cmd = path_cmd_move_to;
+ m_status = markers;
+ break;
+ }
+ m_mtx.transform(x, y);
+ return cmd;
+
+ case stop:
+ cmd = path_cmd_stop;
+ break;
+ }
+ }
+ return cmd;
+ }
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_marker_adaptor.h b/plugins/Clist_ng/AGG/include/agg_conv_marker_adaptor.h new file mode 100644 index 0000000000..cef4ae99b4 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_marker_adaptor.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED
+#define AGG_CONV_MARKER_ADAPTOR_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_conv_adaptor_vcgen.h"
+#include "agg_vcgen_vertex_sequence.h"
+
+namespace agg
+{
+
+ //=====================================================conv_marker_adaptor
+ template<class VertexSource, class Markers=null_markers>
+ struct conv_marker_adaptor :
+ public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>
+ {
+ typedef Markers marker_type;
+ typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type;
+
+ conv_marker_adaptor(VertexSource& vs) :
+ conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
+ {
+ }
+
+ void shorten(double s) { base_type::generator().shorten(s); }
+ double shorten() const { return base_type::generator().shorten(); }
+
+ private:
+ conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
+ const conv_marker_adaptor<VertexSource, Markers>&
+ operator = (const conv_marker_adaptor<VertexSource, Markers>&);
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_segmentator.h b/plugins/Clist_ng/AGG/include/agg_conv_segmentator.h new file mode 100644 index 0000000000..a81c7f1525 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_segmentator.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_SEGMENTATOR_INCLUDED
+#define AGG_CONV_SEGMENTATOR_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_conv_adaptor_vpgen.h"
+#include "agg_vpgen_segmentator.h"
+
+namespace agg
+{
+
+ //========================================================conv_segmentator
+ template<class VertexSource>
+ struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator>
+ {
+ typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
+
+ conv_segmentator(VertexSource& vs) :
+ conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {}
+
+ void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
+ double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
+
+ private:
+ conv_segmentator(const conv_segmentator<VertexSource>&);
+ const conv_segmentator<VertexSource>&
+ operator = (const conv_segmentator<VertexSource>&);
+ };
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_shorten_path.h b/plugins/Clist_ng/AGG/include/agg_conv_shorten_path.h new file mode 100644 index 0000000000..c8c7bcfa62 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_shorten_path.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_SHORTEN_PATH_INCLUDED
+#define AGG_CONV_SHORTEN_PATH_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_conv_adaptor_vcgen.h"
+#include "agg_vcgen_vertex_sequence.h"
+
+namespace agg
+{
+
+ //=======================================================conv_shorten_path
+ template<class VertexSource> class conv_shorten_path :
+ public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>
+ {
+ public:
+ typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type;
+
+ conv_shorten_path(VertexSource& vs) :
+ conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
+ {
+ }
+
+ void shorten(double s) { base_type::generator().shorten(s); }
+ double shorten() const { return base_type::generator().shorten(); }
+
+ private:
+ conv_shorten_path(const conv_shorten_path<VertexSource>&);
+ const conv_shorten_path<VertexSource>&
+ operator = (const conv_shorten_path<VertexSource>&);
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_smooth_poly1.h b/plugins/Clist_ng/AGG/include/agg_conv_smooth_poly1.h new file mode 100644 index 0000000000..73d0e1066a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_smooth_poly1.h @@ -0,0 +1,86 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED
+#define AGG_CONV_SMOOTH_POLY1_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vcgen_smooth_poly1.h"
+#include "agg_conv_adaptor_vcgen.h"
+#include "agg_conv_curve.h"
+
+
+namespace agg
+{
+
+ //-------------------------------------------------------conv_smooth_poly1
+ template<class VertexSource>
+ struct conv_smooth_poly1 :
+ public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>
+ {
+ typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type;
+
+ conv_smooth_poly1(VertexSource& vs) :
+ conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs)
+ {
+ }
+
+ void smooth_value(double v) { base_type::generator().smooth_value(v); }
+ double smooth_value() const { return base_type::generator().smooth_value(); }
+
+ private:
+ conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&);
+ const conv_smooth_poly1<VertexSource>&
+ operator = (const conv_smooth_poly1<VertexSource>&);
+ };
+
+
+
+ //-------------------------------------------------conv_smooth_poly1_curve
+ template<class VertexSource>
+ struct conv_smooth_poly1_curve :
+ public conv_curve<conv_smooth_poly1<VertexSource> >
+ {
+ conv_smooth_poly1_curve(VertexSource& vs) :
+ conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth),
+ m_smooth(vs)
+ {
+ }
+
+ void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
+ double smooth_value() const { return m_smooth.generator().smooth_value(); }
+
+ private:
+ conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&);
+ const conv_smooth_poly1_curve<VertexSource>&
+ operator = (const conv_smooth_poly1_curve<VertexSource>&);
+
+ conv_smooth_poly1<VertexSource> m_smooth;
+ };
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_stroke.h b/plugins/Clist_ng/AGG/include/agg_conv_stroke.h new file mode 100644 index 0000000000..73b7801fe8 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_stroke.h @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_STROKE_INCLUDED
+#define AGG_CONV_STROKE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vcgen_stroke.h"
+#include "agg_conv_adaptor_vcgen.h"
+
+namespace agg
+{
+
+ //-------------------------------------------------------------conv_stroke
+ template<class VertexSource, class Markers=null_markers>
+ struct conv_stroke :
+ public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>
+ {
+ typedef Markers marker_type;
+ typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type;
+
+ conv_stroke(VertexSource& vs) :
+ conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
+ {
+ }
+
+ void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); }
+ void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
+ void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
+
+ line_cap_e line_cap() const { return base_type::generator().line_cap(); }
+ line_join_e line_join() const { return base_type::generator().line_join(); }
+ inner_join_e inner_join() const { return base_type::generator().inner_join(); }
+
+ void width(double w) { base_type::generator().width(w); }
+ void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
+ void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
+ void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
+ void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
+
+ double width() const { return base_type::generator().width(); }
+ double miter_limit() const { return base_type::generator().miter_limit(); }
+ double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
+ double approximation_scale() const { return base_type::generator().approximation_scale(); }
+
+ void shorten(double s) { base_type::generator().shorten(s); }
+ double shorten() const { return base_type::generator().shorten(); }
+
+ private:
+ conv_stroke(const conv_stroke<VertexSource, Markers>&);
+ const conv_stroke<VertexSource, Markers>&
+ operator = (const conv_stroke<VertexSource, Markers>&);
+
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_transform.h b/plugins/Clist_ng/AGG/include/agg_conv_transform.h new file mode 100644 index 0000000000..3ed2a98417 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_transform.h @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_TRANSFORM_INCLUDED
+#define AGG_CONV_TRANSFORM_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_trans_affine.h"
+
+namespace agg
+{
+
+ //----------------------------------------------------------conv_transform
+ template<class VertexSource, class Transformer=trans_affine> class conv_transform
+ {
+ public:
+ conv_transform(VertexSource& source, const Transformer& tr) :
+ m_source(&source), m_trans(&tr) {}
+ void attach(VertexSource& source) { m_source = &source; }
+
+ void rewind(unsigned path_id)
+ {
+ m_source->rewind(path_id);
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ unsigned cmd = m_source->vertex(x, y);
+ if(is_vertex(cmd))
+ {
+ m_trans->transform(x, y);
+ }
+ return cmd;
+ }
+
+ void transformer(const Transformer& tr)
+ {
+ m_trans = &tr;
+ }
+
+ private:
+ conv_transform(const conv_transform<VertexSource>&);
+ const conv_transform<VertexSource>&
+ operator = (const conv_transform<VertexSource>&);
+
+ VertexSource* m_source;
+ const Transformer* m_trans;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_conv_unclose_polygon.h b/plugins/Clist_ng/AGG/include/agg_conv_unclose_polygon.h new file mode 100644 index 0000000000..76070e92cf --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_conv_unclose_polygon.h @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED
+#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //====================================================conv_unclose_polygon
+ template<class VertexSource> class conv_unclose_polygon
+ {
+ public:
+ explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
+ void attach(VertexSource& source) { m_source = &source; }
+
+ void rewind(unsigned path_id)
+ {
+ m_source->rewind(path_id);
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ unsigned cmd = m_source->vertex(x, y);
+ if(is_end_poly(cmd)) cmd &= ~path_flags_close;
+ return cmd;
+ }
+
+ private:
+ conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
+ const conv_unclose_polygon<VertexSource>&
+ operator = (const conv_unclose_polygon<VertexSource>&);
+
+ VertexSource* m_source;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_curves.h b/plugins/Clist_ng/AGG/include/agg_curves.h new file mode 100644 index 0000000000..ca2f5bc651 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_curves.h @@ -0,0 +1,701 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CURVES_INCLUDED
+#define AGG_CURVES_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+
+ // See Implementation agg_curves.cpp
+
+ //--------------------------------------------curve_approximation_method_e
+ enum curve_approximation_method_e
+ {
+ curve_inc,
+ curve_div
+ };
+
+ //--------------------------------------------------------------curve3_inc
+ class curve3_inc
+ {
+ public:
+ curve3_inc() :
+ m_num_steps(0), m_step(0), m_scale(1.0) { }
+
+ curve3_inc(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3) :
+ m_num_steps(0), m_step(0), m_scale(1.0)
+ {
+ init(x1, y1, x2, y2, x3, y3);
+ }
+
+ void reset() { m_num_steps = 0; m_step = -1; }
+ void init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3);
+
+ void approximation_method(curve_approximation_method_e) {}
+ curve_approximation_method_e approximation_method() const { return curve_inc; }
+
+ void approximation_scale(double s);
+ double approximation_scale() const;
+
+ void angle_tolerance(double) {}
+ double angle_tolerance() const { return 0.0; }
+
+ void cusp_limit(double) {}
+ double cusp_limit() const { return 0.0; }
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ int m_num_steps;
+ int m_step;
+ double m_scale;
+ double m_start_x;
+ double m_start_y;
+ double m_end_x;
+ double m_end_y;
+ double m_fx;
+ double m_fy;
+ double m_dfx;
+ double m_dfy;
+ double m_ddfx;
+ double m_ddfy;
+ double m_saved_fx;
+ double m_saved_fy;
+ double m_saved_dfx;
+ double m_saved_dfy;
+ };
+
+
+
+
+
+ //-------------------------------------------------------------curve3_div
+ class curve3_div
+ {
+ public:
+ curve3_div() :
+ m_approximation_scale(1.0),
+ m_angle_tolerance(0.0),
+ m_count(0)
+ {}
+
+ curve3_div(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3) :
+ m_approximation_scale(1.0),
+ m_angle_tolerance(0.0),
+ m_count(0)
+ {
+ init(x1, y1, x2, y2, x3, y3);
+ }
+
+ void reset() { m_points.remove_all(); m_count = 0; }
+ void init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3);
+
+ void approximation_method(curve_approximation_method_e) {}
+ curve_approximation_method_e approximation_method() const { return curve_div; }
+
+ void approximation_scale(double s) { m_approximation_scale = s; }
+ double approximation_scale() const { return m_approximation_scale; }
+
+ void angle_tolerance(double a) { m_angle_tolerance = a; }
+ double angle_tolerance() const { return m_angle_tolerance; }
+
+ void cusp_limit(double) {}
+ double cusp_limit() const { return 0.0; }
+
+ void rewind(unsigned)
+ {
+ m_count = 0;
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_count >= m_points.size()) return path_cmd_stop;
+ const point_d& p = m_points[m_count++];
+ *x = p.x;
+ *y = p.y;
+ return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
+ }
+
+ private:
+ void bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3);
+ void recursive_bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ unsigned level);
+
+ double m_approximation_scale;
+ double m_distance_tolerance_square;
+ double m_angle_tolerance;
+ unsigned m_count;
+ pod_bvector<point_d> m_points;
+ };
+
+
+
+
+
+
+
+ //-------------------------------------------------------------curve4_points
+ struct curve4_points
+ {
+ double cp[8];
+ curve4_points() {}
+ curve4_points(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
+ cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
+ }
+ void init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
+ cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
+ }
+ double operator [] (unsigned i) const { return cp[i]; }
+ double& operator [] (unsigned i) { return cp[i]; }
+ };
+
+
+
+ //-------------------------------------------------------------curve4_inc
+ class curve4_inc
+ {
+ public:
+ curve4_inc() :
+ m_num_steps(0), m_step(0), m_scale(1.0) { }
+
+ curve4_inc(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4) :
+ m_num_steps(0), m_step(0), m_scale(1.0)
+ {
+ init(x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ curve4_inc(const curve4_points& cp) :
+ m_num_steps(0), m_step(0), m_scale(1.0)
+ {
+ init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
+ }
+
+ void reset() { m_num_steps = 0; m_step = -1; }
+ void init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4);
+
+ void init(const curve4_points& cp)
+ {
+ init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
+ }
+
+ void approximation_method(curve_approximation_method_e) {}
+ curve_approximation_method_e approximation_method() const { return curve_inc; }
+
+ void approximation_scale(double s);
+ double approximation_scale() const;
+
+ void angle_tolerance(double) {}
+ double angle_tolerance() const { return 0.0; }
+
+ void cusp_limit(double) {}
+ double cusp_limit() const { return 0.0; }
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ int m_num_steps;
+ int m_step;
+ double m_scale;
+ double m_start_x;
+ double m_start_y;
+ double m_end_x;
+ double m_end_y;
+ double m_fx;
+ double m_fy;
+ double m_dfx;
+ double m_dfy;
+ double m_ddfx;
+ double m_ddfy;
+ double m_dddfx;
+ double m_dddfy;
+ double m_saved_fx;
+ double m_saved_fy;
+ double m_saved_dfx;
+ double m_saved_dfy;
+ double m_saved_ddfx;
+ double m_saved_ddfy;
+ };
+
+
+
+ //-------------------------------------------------------catrom_to_bezier
+ inline curve4_points catrom_to_bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ // Trans. matrix Catmull-Rom to Bezier
+ //
+ // 0 1 0 0
+ // -1/6 1 1/6 0
+ // 0 1/6 1 -1/6
+ // 0 0 1 0
+ //
+ return curve4_points(
+ x2,
+ y2,
+ (-x1 + 6*x2 + x3) / 6,
+ (-y1 + 6*y2 + y3) / 6,
+ ( x2 + 6*x3 - x4) / 6,
+ ( y2 + 6*y3 - y4) / 6,
+ x3,
+ y3);
+ }
+
+
+ //-----------------------------------------------------------------------
+ inline curve4_points
+ catrom_to_bezier(const curve4_points& cp)
+ {
+ return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3],
+ cp[4], cp[5], cp[6], cp[7]);
+ }
+
+
+
+ //-----------------------------------------------------ubspline_to_bezier
+ inline curve4_points ubspline_to_bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ // Trans. matrix Uniform BSpline to Bezier
+ //
+ // 1/6 4/6 1/6 0
+ // 0 4/6 2/6 0
+ // 0 2/6 4/6 0
+ // 0 1/6 4/6 1/6
+ //
+ return curve4_points(
+ (x1 + 4*x2 + x3) / 6,
+ (y1 + 4*y2 + y3) / 6,
+ (4*x2 + 2*x3) / 6,
+ (4*y2 + 2*y3) / 6,
+ (2*x2 + 4*x3) / 6,
+ (2*y2 + 4*y3) / 6,
+ (x2 + 4*x3 + x4) / 6,
+ (y2 + 4*y3 + y4) / 6);
+ }
+
+
+ //-----------------------------------------------------------------------
+ inline curve4_points
+ ubspline_to_bezier(const curve4_points& cp)
+ {
+ return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3],
+ cp[4], cp[5], cp[6], cp[7]);
+ }
+
+
+
+
+ //------------------------------------------------------hermite_to_bezier
+ inline curve4_points hermite_to_bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ // Trans. matrix Hermite to Bezier
+ //
+ // 1 0 0 0
+ // 1 0 1/3 0
+ // 0 1 0 -1/3
+ // 0 1 0 0
+ //
+ return curve4_points(
+ x1,
+ y1,
+ (3*x1 + x3) / 3,
+ (3*y1 + y3) / 3,
+ (3*x2 - x4) / 3,
+ (3*y2 - y4) / 3,
+ x2,
+ y2);
+ }
+
+
+
+ //-----------------------------------------------------------------------
+ inline curve4_points
+ hermite_to_bezier(const curve4_points& cp)
+ {
+ return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3],
+ cp[4], cp[5], cp[6], cp[7]);
+ }
+
+
+ //-------------------------------------------------------------curve4_div
+ class curve4_div
+ {
+ public:
+ curve4_div() :
+ m_approximation_scale(1.0),
+ m_angle_tolerance(0.0),
+ m_cusp_limit(0.0),
+ m_count(0)
+ {}
+
+ curve4_div(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4) :
+ m_approximation_scale(1.0),
+ m_angle_tolerance(0.0),
+ m_cusp_limit(0.0),
+ m_count(0)
+ {
+ init(x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ curve4_div(const curve4_points& cp) :
+ m_approximation_scale(1.0),
+ m_angle_tolerance(0.0),
+ m_count(0)
+ {
+ init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
+ }
+
+ void reset() { m_points.remove_all(); m_count = 0; }
+ void init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4);
+
+ void init(const curve4_points& cp)
+ {
+ init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
+ }
+
+ void approximation_method(curve_approximation_method_e) {}
+
+ curve_approximation_method_e approximation_method() const
+ {
+ return curve_div;
+ }
+
+ void approximation_scale(double s) { m_approximation_scale = s; }
+ double approximation_scale() const { return m_approximation_scale; }
+
+ void angle_tolerance(double a) { m_angle_tolerance = a; }
+ double angle_tolerance() const { return m_angle_tolerance; }
+
+ void cusp_limit(double v)
+ {
+ m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
+ }
+
+ double cusp_limit() const
+ {
+ return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
+ }
+
+ void rewind(unsigned)
+ {
+ m_count = 0;
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_count >= m_points.size()) return path_cmd_stop;
+ const point_d& p = m_points[m_count++];
+ *x = p.x;
+ *y = p.y;
+ return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
+ }
+
+ private:
+ void bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4);
+
+ void recursive_bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4,
+ unsigned level);
+
+ double m_approximation_scale;
+ double m_distance_tolerance_square;
+ double m_angle_tolerance;
+ double m_cusp_limit;
+ unsigned m_count;
+ pod_bvector<point_d> m_points;
+ };
+
+
+ //-----------------------------------------------------------------curve3
+ class curve3
+ {
+ public:
+ curve3() : m_approximation_method(curve_div) {}
+ curve3(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3) :
+ m_approximation_method(curve_div)
+ {
+ init(x1, y1, x2, y2, x3, y3);
+ }
+
+ void reset()
+ {
+ m_curve_inc.reset();
+ m_curve_div.reset();
+ }
+
+ void init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ if(m_approximation_method == curve_inc)
+ {
+ m_curve_inc.init(x1, y1, x2, y2, x3, y3);
+ }
+ else
+ {
+ m_curve_div.init(x1, y1, x2, y2, x3, y3);
+ }
+ }
+
+ void approximation_method(curve_approximation_method_e v)
+ {
+ m_approximation_method = v;
+ }
+
+ curve_approximation_method_e approximation_method() const
+ {
+ return m_approximation_method;
+ }
+
+ void approximation_scale(double s)
+ {
+ m_curve_inc.approximation_scale(s);
+ m_curve_div.approximation_scale(s);
+ }
+
+ double approximation_scale() const
+ {
+ return m_curve_inc.approximation_scale();
+ }
+
+ void angle_tolerance(double a)
+ {
+ m_curve_div.angle_tolerance(a);
+ }
+
+ double angle_tolerance() const
+ {
+ return m_curve_div.angle_tolerance();
+ }
+
+ void cusp_limit(double v)
+ {
+ m_curve_div.cusp_limit(v);
+ }
+
+ double cusp_limit() const
+ {
+ return m_curve_div.cusp_limit();
+ }
+
+ void rewind(unsigned path_id)
+ {
+ if(m_approximation_method == curve_inc)
+ {
+ m_curve_inc.rewind(path_id);
+ }
+ else
+ {
+ m_curve_div.rewind(path_id);
+ }
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_approximation_method == curve_inc)
+ {
+ return m_curve_inc.vertex(x, y);
+ }
+ return m_curve_div.vertex(x, y);
+ }
+
+ private:
+ curve3_inc m_curve_inc;
+ curve3_div m_curve_div;
+ curve_approximation_method_e m_approximation_method;
+ };
+
+
+
+
+
+ //-----------------------------------------------------------------curve4
+ class curve4
+ {
+ public:
+ curve4() : m_approximation_method(curve_div) {}
+ curve4(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4) :
+ m_approximation_method(curve_div)
+ {
+ init(x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ curve4(const curve4_points& cp) :
+ m_approximation_method(curve_div)
+ {
+ init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
+ }
+
+ void reset()
+ {
+ m_curve_inc.reset();
+ m_curve_div.reset();
+ }
+
+ void init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ if(m_approximation_method == curve_inc)
+ {
+ m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+ else
+ {
+ m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+ }
+
+ void init(const curve4_points& cp)
+ {
+ init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
+ }
+
+ void approximation_method(curve_approximation_method_e v)
+ {
+ m_approximation_method = v;
+ }
+
+ curve_approximation_method_e approximation_method() const
+ {
+ return m_approximation_method;
+ }
+
+ void approximation_scale(double s)
+ {
+ m_curve_inc.approximation_scale(s);
+ m_curve_div.approximation_scale(s);
+ }
+ double approximation_scale() const { return m_curve_inc.approximation_scale(); }
+
+ void angle_tolerance(double v)
+ {
+ m_curve_div.angle_tolerance(v);
+ }
+
+ double angle_tolerance() const
+ {
+ return m_curve_div.angle_tolerance();
+ }
+
+ void cusp_limit(double v)
+ {
+ m_curve_div.cusp_limit(v);
+ }
+
+ double cusp_limit() const
+ {
+ return m_curve_div.cusp_limit();
+ }
+
+ void rewind(unsigned path_id)
+ {
+ if(m_approximation_method == curve_inc)
+ {
+ m_curve_inc.rewind(path_id);
+ }
+ else
+ {
+ m_curve_div.rewind(path_id);
+ }
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_approximation_method == curve_inc)
+ {
+ return m_curve_inc.vertex(x, y);
+ }
+ return m_curve_div.vertex(x, y);
+ }
+
+ private:
+ curve4_inc m_curve_inc;
+ curve4_div m_curve_div;
+ curve_approximation_method_e m_approximation_method;
+ };
+
+
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_dda_line.h b/plugins/Clist_ng/AGG/include/agg_dda_line.h new file mode 100644 index 0000000000..92bb0462a1 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_dda_line.h @@ -0,0 +1,295 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_DDA_LINE_INCLUDED
+#define AGG_DDA_LINE_INCLUDED
+
+#include <stdlib.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //===================================================dda_line_interpolator
+ template<int FractionShift, int YShift=0> class dda_line_interpolator
+ {
+ public:
+ //--------------------------------------------------------------------
+ dda_line_interpolator() {}
+
+ //--------------------------------------------------------------------
+ dda_line_interpolator(int y1, int y2, unsigned count) :
+ m_y(y1),
+ m_inc(((y2 - y1) << FractionShift) / int(count)),
+ m_dy(0)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void operator ++ ()
+ {
+ m_dy += m_inc;
+ }
+
+ //--------------------------------------------------------------------
+ void operator -- ()
+ {
+ m_dy -= m_inc;
+ }
+
+ //--------------------------------------------------------------------
+ void operator += (unsigned n)
+ {
+ m_dy += m_inc * n;
+ }
+
+ //--------------------------------------------------------------------
+ void operator -= (unsigned n)
+ {
+ m_dy -= m_inc * n;
+ }
+
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y + (m_dy >> (FractionShift-YShift)); }
+ int dy() const { return m_dy; }
+
+
+ private:
+ int m_y;
+ int m_inc;
+ int m_dy;
+ };
+
+
+
+
+
+ //=================================================dda2_line_interpolator
+ class dda2_line_interpolator
+ {
+ public:
+ typedef int save_data_type;
+ enum save_size_e { save_size = 2 };
+
+ //--------------------------------------------------------------------
+ dda2_line_interpolator() {}
+
+ //-------------------------------------------- Forward-adjusted line
+ dda2_line_interpolator(int y1, int y2, int count) :
+ m_cnt(count <= 0 ? 1 : count),
+ m_lft((y2 - y1) / m_cnt),
+ m_rem((y2 - y1) % m_cnt),
+ m_mod(m_rem),
+ m_y(y1)
+ {
+ if(m_mod <= 0)
+ {
+ m_mod += count;
+ m_rem += count;
+ m_lft--;
+ }
+ m_mod -= count;
+ }
+
+ //-------------------------------------------- Backward-adjusted line
+ dda2_line_interpolator(int y1, int y2, int count, int) :
+ m_cnt(count <= 0 ? 1 : count),
+ m_lft((y2 - y1) / m_cnt),
+ m_rem((y2 - y1) % m_cnt),
+ m_mod(m_rem),
+ m_y(y1)
+ {
+ if(m_mod <= 0)
+ {
+ m_mod += count;
+ m_rem += count;
+ m_lft--;
+ }
+ }
+
+ //-------------------------------------------- Backward-adjusted line
+ dda2_line_interpolator(int y, int count) :
+ m_cnt(count <= 0 ? 1 : count),
+ m_lft(y / m_cnt),
+ m_rem(y % m_cnt),
+ m_mod(m_rem),
+ m_y(0)
+ {
+ if(m_mod <= 0)
+ {
+ m_mod += count;
+ m_rem += count;
+ m_lft--;
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void save(save_data_type* data) const
+ {
+ data[0] = m_mod;
+ data[1] = m_y;
+ }
+
+ //--------------------------------------------------------------------
+ void load(const save_data_type* data)
+ {
+ m_mod = data[0];
+ m_y = data[1];
+ }
+
+ //--------------------------------------------------------------------
+ void operator++()
+ {
+ m_mod += m_rem;
+ m_y += m_lft;
+ if(m_mod > 0)
+ {
+ m_mod -= m_cnt;
+ m_y++;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void operator--()
+ {
+ if(m_mod <= m_rem)
+ {
+ m_mod += m_cnt;
+ m_y--;
+ }
+ m_mod -= m_rem;
+ m_y -= m_lft;
+ }
+
+ //--------------------------------------------------------------------
+ void adjust_forward()
+ {
+ m_mod -= m_cnt;
+ }
+
+ //--------------------------------------------------------------------
+ void adjust_backward()
+ {
+ m_mod += m_cnt;
+ }
+
+ //--------------------------------------------------------------------
+ int mod() const { return m_mod; }
+ int rem() const { return m_rem; }
+ int lft() const { return m_lft; }
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y; }
+
+ private:
+ int m_cnt;
+ int m_lft;
+ int m_rem;
+ int m_mod;
+ int m_y;
+ };
+
+
+
+
+
+
+
+ //---------------------------------------------line_bresenham_interpolator
+ class line_bresenham_interpolator
+ {
+ public:
+ enum subpixel_scale_e
+ {
+ subpixel_shift = 8,
+ subpixel_scale = 1 << subpixel_shift,
+ subpixel_mask = subpixel_scale - 1
+ };
+
+ //--------------------------------------------------------------------
+ static int line_lr(int v) { return v >> subpixel_shift; }
+
+ //--------------------------------------------------------------------
+ line_bresenham_interpolator(int x1, int y1, int x2, int y2) :
+ m_x1_lr(line_lr(x1)),
+ m_y1_lr(line_lr(y1)),
+ m_x2_lr(line_lr(x2)),
+ m_y2_lr(line_lr(y2)),
+ m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)),
+ m_len(m_ver ? abs(m_y2_lr - m_y1_lr) :
+ abs(m_x2_lr - m_x1_lr)),
+ m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)),
+ m_interpolator(m_ver ? x1 : y1,
+ m_ver ? x2 : y2,
+ m_len)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool is_ver() const { return m_ver; }
+ unsigned len() const { return m_len; }
+ int inc() const { return m_inc; }
+
+ //--------------------------------------------------------------------
+ void hstep()
+ {
+ ++m_interpolator;
+ m_x1_lr += m_inc;
+ }
+
+ //--------------------------------------------------------------------
+ void vstep()
+ {
+ ++m_interpolator;
+ m_y1_lr += m_inc;
+ }
+
+ //--------------------------------------------------------------------
+ int x1() const { return m_x1_lr; }
+ int y1() const { return m_y1_lr; }
+ int x2() const { return line_lr(m_interpolator.y()); }
+ int y2() const { return line_lr(m_interpolator.y()); }
+ int x2_hr() const { return m_interpolator.y(); }
+ int y2_hr() const { return m_interpolator.y(); }
+
+ private:
+ int m_x1_lr;
+ int m_y1_lr;
+ int m_x2_lr;
+ int m_y2_lr;
+ bool m_ver;
+ unsigned m_len;
+ int m_inc;
+ dda2_line_interpolator m_interpolator;
+
+ };
+
+
+}
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_ellipse.h b/plugins/Clist_ng/AGG/include/agg_ellipse.h new file mode 100644 index 0000000000..8693a3c38e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_ellipse.h @@ -0,0 +1,128 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_ELLIPSE_INCLUDED
+#define AGG_ELLIPSE_INCLUDED
+
+#include "agg_basics.h"
+#include <math.h>
+
+namespace agg
+{
+
+ //----------------------------------------------------------------ellipse
+ class ellipse
+ {
+ public:
+ ellipse() :
+ m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
+ m_num(4), m_step(0), m_cw(false) {}
+
+ ellipse(double x, double y, double rx, double ry,
+ unsigned num_steps=0, bool cw=false) :
+ m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
+ m_num(num_steps), m_step(0), m_cw(cw)
+ {
+ if(m_num == 0) calc_num_steps();
+ }
+
+ void init(double x, double y, double rx, double ry,
+ unsigned num_steps=0, bool cw=false);
+
+ void approximation_scale(double scale);
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ void calc_num_steps();
+
+ double m_x;
+ double m_y;
+ double m_rx;
+ double m_ry;
+ double m_scale;
+ unsigned m_num;
+ unsigned m_step;
+ bool m_cw;
+ };
+
+ //------------------------------------------------------------------------
+ inline void ellipse::init(double x, double y, double rx, double ry,
+ unsigned num_steps, bool cw)
+ {
+ m_x = x;
+ m_y = y;
+ m_rx = rx;
+ m_ry = ry;
+ m_num = num_steps;
+ m_step = 0;
+ m_cw = cw;
+ if(m_num == 0) calc_num_steps();
+ }
+
+ //------------------------------------------------------------------------
+ inline void ellipse::approximation_scale(double scale)
+ {
+ m_scale = scale;
+ calc_num_steps();
+ }
+
+ //------------------------------------------------------------------------
+ inline void ellipse::calc_num_steps()
+ {
+ double ra = (fabs(m_rx) + fabs(m_ry)) / 2;
+ double da = acos(ra / (ra + 0.125 / m_scale)) * 2;
+ m_num = uround(2*pi / da);
+ }
+
+ //------------------------------------------------------------------------
+ inline void ellipse::rewind(unsigned)
+ {
+ m_step = 0;
+ }
+
+ //------------------------------------------------------------------------
+ inline unsigned ellipse::vertex(double* x, double* y)
+ {
+ if(m_step == m_num)
+ {
+ ++m_step;
+ return path_cmd_end_poly | path_flags_close | path_flags_ccw;
+ }
+ if(m_step > m_num) return path_cmd_stop;
+ double angle = double(m_step) / double(m_num) * 2.0 * pi;
+ if(m_cw) angle = 2.0 * pi - angle;
+ *x = m_x + cos(angle) * m_rx;
+ *y = m_y + sin(angle) * m_ry;
+ m_step++;
+ return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
+ }
+
+}
+
+
+
+#endif
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_ellipse_bresenham.h b/plugins/Clist_ng/AGG/include/agg_ellipse_bresenham.h new file mode 100644 index 0000000000..dfb66e874a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_ellipse_bresenham.h @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
+#define AGG_ELLIPSE_BRESENHAM_INCLUDED
+
+
+#include "agg_basics.h"
+
+
+namespace agg
+{
+
+ //------------------------------------------ellipse_bresenham_interpolator
+ class ellipse_bresenham_interpolator
+ {
+ public:
+ ellipse_bresenham_interpolator(int rx, int ry) :
+ m_rx2(rx * rx),
+ m_ry2(ry * ry),
+ m_two_rx2(m_rx2 << 1),
+ m_two_ry2(m_ry2 << 1),
+ m_dx(0),
+ m_dy(0),
+ m_inc_x(0),
+ m_inc_y(-ry * m_two_rx2),
+ m_cur_f(0)
+ {}
+
+ int dx() const { return m_dx; }
+ int dy() const { return m_dy; }
+
+ void operator++ ()
+ {
+ int mx, my, mxy, min_m;
+ int fx, fy, fxy;
+
+ mx = fx = m_cur_f + m_inc_x + m_ry2;
+ if(mx < 0) mx = -mx;
+
+ my = fy = m_cur_f + m_inc_y + m_rx2;
+ if(my < 0) my = -my;
+
+ mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2;
+ if(mxy < 0) mxy = -mxy;
+
+ min_m = mx;
+ bool flag = true;
+
+ if(min_m > my)
+ {
+ min_m = my;
+ flag = false;
+ }
+
+ m_dx = m_dy = 0;
+
+ if(min_m > mxy)
+ {
+ m_inc_x += m_two_ry2;
+ m_inc_y += m_two_rx2;
+ m_cur_f = fxy;
+ m_dx = 1;
+ m_dy = 1;
+ return;
+ }
+
+ if(flag)
+ {
+ m_inc_x += m_two_ry2;
+ m_cur_f = fx;
+ m_dx = 1;
+ return;
+ }
+
+ m_inc_y += m_two_rx2;
+ m_cur_f = fy;
+ m_dy = 1;
+ }
+
+ private:
+ int m_rx2;
+ int m_ry2;
+ int m_two_rx2;
+ int m_two_ry2;
+ int m_dx;
+ int m_dy;
+ int m_inc_x;
+ int m_inc_y;
+ int m_cur_f;
+
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_embedded_raster_fonts.h b/plugins/Clist_ng/AGG/include/agg_embedded_raster_fonts.h new file mode 100644 index 0000000000..795a90d000 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_embedded_raster_fonts.h @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED
+#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ extern const int8u gse4x6[];
+ extern const int8u gse4x8[];
+ extern const int8u gse5x7[];
+ extern const int8u gse5x9[];
+ extern const int8u gse6x12[];
+ extern const int8u gse6x9[];
+ extern const int8u gse7x11[];
+ extern const int8u gse7x11_bold[];
+ extern const int8u gse7x15[];
+ extern const int8u gse7x15_bold[];
+ extern const int8u gse8x16[];
+ extern const int8u gse8x16_bold[];
+ extern const int8u mcs11_prop[];
+ extern const int8u mcs11_prop_condensed[];
+ extern const int8u mcs12_prop[];
+ extern const int8u mcs13_prop[];
+ extern const int8u mcs5x10_mono[];
+ extern const int8u mcs5x11_mono[];
+ extern const int8u mcs6x10_mono[];
+ extern const int8u mcs6x11_mono[];
+ extern const int8u mcs7x12_mono_high[];
+ extern const int8u mcs7x12_mono_low[];
+ extern const int8u verdana12[];
+ extern const int8u verdana12_bold[];
+ extern const int8u verdana13[];
+ extern const int8u verdana13_bold[];
+ extern const int8u verdana14[];
+ extern const int8u verdana14_bold[];
+ extern const int8u verdana16[];
+ extern const int8u verdana16_bold[];
+ extern const int8u verdana17[];
+ extern const int8u verdana17_bold[];
+ extern const int8u verdana18[];
+ extern const int8u verdana18_bold[];
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_font_cache_manager.h b/plugins/Clist_ng/AGG/include/agg_font_cache_manager.h new file mode 100644 index 0000000000..637da849aa --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_font_cache_manager.h @@ -0,0 +1,418 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
+#define AGG_FONT_CACHE_MANAGER_INCLUDED
+
+#include <string.h>
+#include "agg_array.h"
+
+namespace agg
+{
+
+ //---------------------------------------------------------glyph_data_type
+ enum glyph_data_type
+ {
+ glyph_data_invalid = 0,
+ glyph_data_mono = 1,
+ glyph_data_gray8 = 2,
+ glyph_data_outline = 3
+ };
+
+
+ //-------------------------------------------------------------glyph_cache
+ struct glyph_cache
+ {
+ unsigned glyph_index;
+ int8u* data;
+ unsigned data_size;
+ glyph_data_type data_type;
+ rect_i bounds;
+ double advance_x;
+ double advance_y;
+ };
+
+
+ //--------------------------------------------------------------font_cache
+ class font_cache
+ {
+ public:
+ enum block_size_e { block_size = 16384-16 };
+
+ //--------------------------------------------------------------------
+ font_cache() :
+ m_allocator(block_size),
+ m_font_signature(0)
+ {}
+
+ //--------------------------------------------------------------------
+ void signature(const char* font_signature)
+ {
+ m_font_signature = (char*)m_allocator.allocate(lstrlenA(font_signature) + 1);
+ strcpy(m_font_signature, font_signature);
+ memset(m_glyphs, 0, sizeof(m_glyphs));
+ }
+
+ //--------------------------------------------------------------------
+ bool font_is(const char* font_signature) const
+ {
+ return strcmp(font_signature, m_font_signature) == 0;
+ }
+
+ //--------------------------------------------------------------------
+ const glyph_cache* find_glyph(unsigned glyph_code) const
+ {
+ unsigned msb = (glyph_code >> 8) & 0xFF;
+ if(m_glyphs[msb])
+ {
+ return m_glyphs[msb][glyph_code & 0xFF];
+ }
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ glyph_cache* cache_glyph(unsigned glyph_code,
+ unsigned glyph_index,
+ unsigned data_size,
+ glyph_data_type data_type,
+ const rect_i& bounds,
+ double advance_x,
+ double advance_y)
+ {
+ unsigned msb = (glyph_code >> 8) & 0xFF;
+ if(m_glyphs[msb] == 0)
+ {
+ m_glyphs[msb] =
+ (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
+ sizeof(glyph_cache*));
+ memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
+ }
+
+ unsigned lsb = glyph_code & 0xFF;
+ if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
+
+ glyph_cache* glyph =
+ (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
+ sizeof(double));
+
+ glyph->glyph_index = glyph_index;
+ glyph->data = m_allocator.allocate(data_size);
+ glyph->data_size = data_size;
+ glyph->data_type = data_type;
+ glyph->bounds = bounds;
+ glyph->advance_x = advance_x;
+ glyph->advance_y = advance_y;
+ return m_glyphs[msb][lsb] = glyph;
+ }
+
+ private:
+ block_allocator m_allocator;
+ glyph_cache** m_glyphs[256];
+ char* m_font_signature;
+ };
+
+
+
+
+
+
+
+ //---------------------------------------------------------font_cache_pool
+ class font_cache_pool
+ {
+ public:
+ //--------------------------------------------------------------------
+ ~font_cache_pool()
+ {
+ unsigned i;
+ for(i = 0; i < m_num_fonts; ++i)
+ {
+ obj_allocator<font_cache>::deallocate(m_fonts[i]);
+ }
+ pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
+ }
+
+ //--------------------------------------------------------------------
+ font_cache_pool(unsigned max_fonts=32) :
+ m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
+ m_max_fonts(max_fonts),
+ m_num_fonts(0),
+ m_cur_font(0)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void font(const char* font_signature, bool reset_cache = false)
+ {
+ int idx = find_font(font_signature);
+ if(idx >= 0)
+ {
+ if(reset_cache)
+ {
+ obj_allocator<font_cache>::deallocate(m_fonts[idx]);
+ m_fonts[idx] = obj_allocator<font_cache>::allocate();
+ m_fonts[idx]->signature(font_signature);
+ }
+ m_cur_font = m_fonts[idx];
+ }
+ else
+ {
+ if(m_num_fonts >= m_max_fonts)
+ {
+ obj_allocator<font_cache>::deallocate(m_fonts[0]);
+ memcpy(m_fonts,
+ m_fonts + 1,
+ (m_max_fonts - 1) * sizeof(font_cache*));
+ m_num_fonts = m_max_fonts - 1;
+ }
+ m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
+ m_fonts[m_num_fonts]->signature(font_signature);
+ m_cur_font = m_fonts[m_num_fonts];
+ ++m_num_fonts;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ const font_cache* font() const
+ {
+ return m_cur_font;
+ }
+
+ //--------------------------------------------------------------------
+ const glyph_cache* find_glyph(unsigned glyph_code) const
+ {
+ if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ glyph_cache* cache_glyph(unsigned glyph_code,
+ unsigned glyph_index,
+ unsigned data_size,
+ glyph_data_type data_type,
+ const rect_i& bounds,
+ double advance_x,
+ double advance_y)
+ {
+ if(m_cur_font)
+ {
+ return m_cur_font->cache_glyph(glyph_code,
+ glyph_index,
+ data_size,
+ data_type,
+ bounds,
+ advance_x,
+ advance_y);
+ }
+ return 0;
+ }
+
+
+ //--------------------------------------------------------------------
+ int find_font(const char* font_signature)
+ {
+ unsigned i;
+ for(i = 0; i < m_num_fonts; i++)
+ {
+ if(m_fonts[i]->font_is(font_signature)) return int(i);
+ }
+ return -1;
+ }
+
+ private:
+ font_cache** m_fonts;
+ unsigned m_max_fonts;
+ unsigned m_num_fonts;
+ font_cache* m_cur_font;
+ };
+
+
+
+
+ //------------------------------------------------------------------------
+ enum glyph_rendering
+ {
+ glyph_ren_native_mono,
+ glyph_ren_native_gray8,
+ glyph_ren_outline,
+ glyph_ren_agg_mono,
+ glyph_ren_agg_gray8
+ };
+
+
+
+
+ //------------------------------------------------------font_cache_manager
+ template<class FontEngine> class font_cache_manager
+ {
+ public:
+ typedef FontEngine font_engine_type;
+ typedef font_cache_manager<FontEngine> self_type;
+ typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
+ typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
+ typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
+ typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
+ typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
+
+ //--------------------------------------------------------------------
+ font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
+ m_fonts(max_fonts),
+ m_engine(engine),
+ m_change_stamp(-1),
+ m_prev_glyph(0),
+ m_last_glyph(0)
+ {}
+
+ //--------------------------------------------------------------------
+ void reset_last_glyph()
+ {
+ m_prev_glyph = m_last_glyph = 0;
+ }
+
+ //--------------------------------------------------------------------
+ const glyph_cache* glyph(unsigned glyph_code)
+ {
+ synchronize();
+ const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
+ if(gl)
+ {
+ m_prev_glyph = m_last_glyph;
+ return m_last_glyph = gl;
+ }
+ else
+ {
+ if(m_engine.prepare_glyph(glyph_code))
+ {
+ m_prev_glyph = m_last_glyph;
+ m_last_glyph = m_fonts.cache_glyph(glyph_code,
+ m_engine.glyph_index(),
+ m_engine.data_size(),
+ m_engine.data_type(),
+ m_engine.bounds(),
+ m_engine.advance_x(),
+ m_engine.advance_y());
+ m_engine.write_glyph_to(m_last_glyph->data);
+ return m_last_glyph;
+ }
+ }
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ void init_embedded_adaptors(const glyph_cache* gl,
+ double x, double y,
+ double scale=1.0)
+ {
+ if(gl)
+ {
+ switch(gl->data_type)
+ {
+ default: return;
+ case glyph_data_mono:
+ m_mono_adaptor.init(gl->data, gl->data_size, x, y);
+ break;
+
+ case glyph_data_gray8:
+ m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
+ break;
+
+ case glyph_data_outline:
+ m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
+ break;
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ path_adaptor_type& path_adaptor() { return m_path_adaptor; }
+ gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
+ gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
+ mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
+ mono_scanline_type& mono_scanline() { return m_mono_scanline; }
+
+ //--------------------------------------------------------------------
+ const glyph_cache* perv_glyph() const { return m_prev_glyph; }
+ const glyph_cache* last_glyph() const { return m_last_glyph; }
+
+ //--------------------------------------------------------------------
+ bool add_kerning(double* x, double* y)
+ {
+ if(m_prev_glyph && m_last_glyph)
+ {
+ return m_engine.add_kerning(m_prev_glyph->glyph_index,
+ m_last_glyph->glyph_index,
+ x, y);
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ void precache(unsigned from, unsigned to)
+ {
+ for(; from <= to; ++from) glyph(from);
+ }
+
+ //--------------------------------------------------------------------
+ void reset_cache()
+ {
+ m_fonts.font(m_engine.font_signature(), true);
+ m_change_stamp = m_engine.change_stamp();
+ m_prev_glyph = m_last_glyph = 0;
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ font_cache_manager(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ //--------------------------------------------------------------------
+ void synchronize()
+ {
+ if(m_change_stamp != m_engine.change_stamp())
+ {
+ m_fonts.font(m_engine.font_signature());
+ m_change_stamp = m_engine.change_stamp();
+ m_prev_glyph = m_last_glyph = 0;
+ }
+ }
+
+ font_cache_pool m_fonts;
+ font_engine_type& m_engine;
+ int m_change_stamp;
+ double m_dx;
+ double m_dy;
+ const glyph_cache* m_prev_glyph;
+ const glyph_cache* m_last_glyph;
+ path_adaptor_type m_path_adaptor;
+ gray8_adaptor_type m_gray8_adaptor;
+ gray8_scanline_type m_gray8_scanline;
+ mono_adaptor_type m_mono_adaptor;
+ mono_scanline_type m_mono_scanline;
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_font_freetype.h b/plugins/Clist_ng/AGG/include/agg_font_freetype.h new file mode 100644 index 0000000000..db923eb5a0 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_font_freetype.h @@ -0,0 +1,201 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_FONT_FREETYPE_INCLUDED
+#define AGG_FONT_FREETYPE_INCLUDED
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+#include "agg_scanline_storage_aa.h"
+#include "agg_scanline_storage_bin.h"
+#include "agg_scanline_u.h"
+#include "agg_scanline_bin.h"
+#include "agg_path_storage_integer.h"
+#include "agg_rasterizer_scanline_aa.h"
+#include "agg_conv_curve.h"
+#include "agg_font_cache_manager.h"
+#include "agg_trans_affine.h"
+
+namespace agg
+{
+
+
+ //-----------------------------------------------font_engine_freetype_base
+ class font_engine_freetype_base
+ {
+ public:
+ //--------------------------------------------------------------------
+ typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type;
+ typedef serialized_scanlines_adaptor_bin mono_adaptor_type;
+ typedef scanline_storage_aa8 scanlines_aa_type;
+ typedef scanline_storage_bin scanlines_bin_type;
+
+ //--------------------------------------------------------------------
+ ~font_engine_freetype_base();
+ font_engine_freetype_base(bool flag32, unsigned max_faces = 32);
+
+ // Set font parameters
+ //--------------------------------------------------------------------
+ void resolution(unsigned dpi);
+ bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type,
+ const char* font_mem = 0, const long font_mem_size = 0);
+ bool attach(const char* file_name);
+ bool char_map(FT_Encoding map);
+ bool height(double h);
+ bool width(double w);
+ void hinting(bool h);
+ void flip_y(bool f);
+ void transform(const trans_affine& affine);
+
+ // Set Gamma
+ //--------------------------------------------------------------------
+ template<class GammaF> void gamma(const GammaF& f)
+ {
+ m_rasterizer.gamma(f);
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+ int last_error() const { return m_last_error; }
+ unsigned resolution() const { return m_resolution; }
+ const char* name() const { return m_name; }
+ unsigned num_faces() const;
+ FT_Encoding char_map() const { return m_char_map; }
+ double height() const { return double(m_height) / 64.0; }
+ double width() const { return double(m_width) / 64.0; }
+ double ascender() const;
+ double descender() const;
+ bool hinting() const { return m_hinting; }
+ bool flip_y() const { return m_flip_y; }
+
+
+ // Interface mandatory to implement for font_cache_manager
+ //--------------------------------------------------------------------
+ const char* font_signature() const { return m_signature; }
+ int change_stamp() const { return m_change_stamp; }
+
+ bool prepare_glyph(unsigned glyph_code);
+ unsigned glyph_index() const { return m_glyph_index; }
+ unsigned data_size() const { return m_data_size; }
+ glyph_data_type data_type() const { return m_data_type; }
+ const rect_i& bounds() const { return m_bounds; }
+ double advance_x() const { return m_advance_x; }
+ double advance_y() const { return m_advance_y; }
+ void write_glyph_to(int8u* data) const;
+ bool add_kerning(unsigned first, unsigned second,
+ double* x, double* y);
+
+ private:
+ font_engine_freetype_base(const font_engine_freetype_base&);
+ const font_engine_freetype_base& operator = (const font_engine_freetype_base&);
+
+ void update_char_size();
+ void update_signature();
+ int find_face(const char* face_name) const;
+
+ bool m_flag32;
+ int m_change_stamp;
+ int m_last_error;
+ char* m_name;
+ unsigned m_name_len;
+ unsigned m_face_index;
+ FT_Encoding m_char_map;
+ char* m_signature;
+ unsigned m_height;
+ unsigned m_width;
+ bool m_hinting;
+ bool m_flip_y;
+ bool m_library_initialized;
+ FT_Library m_library; // handle to library
+ FT_Face* m_faces; // A pool of font faces
+ char** m_face_names;
+ unsigned m_num_faces;
+ unsigned m_max_faces;
+ FT_Face m_cur_face; // handle to the current face object
+ int m_resolution;
+ glyph_rendering m_glyph_rendering;
+ unsigned m_glyph_index;
+ unsigned m_data_size;
+ glyph_data_type m_data_type;
+ rect_i m_bounds;
+ double m_advance_x;
+ double m_advance_y;
+ trans_affine m_affine;
+
+ path_storage_integer<int16, 6> m_path16;
+ path_storage_integer<int32, 6> m_path32;
+ conv_curve<path_storage_integer<int16, 6> > m_curves16;
+ conv_curve<path_storage_integer<int32, 6> > m_curves32;
+ scanline_u8 m_scanline_aa;
+ scanline_bin m_scanline_bin;
+ scanlines_aa_type m_scanlines_aa;
+ scanlines_bin_type m_scanlines_bin;
+ rasterizer_scanline_aa<> m_rasterizer;
+ };
+
+
+
+
+ //------------------------------------------------font_engine_freetype_int16
+ // This class uses values of type int16 (10.6 format) for the vector cache.
+ // The vector cache is compact, but when rendering glyphs of height
+ // more that 200 there integer overflow can occur.
+ //
+ class font_engine_freetype_int16 : public font_engine_freetype_base
+ {
+ public:
+ typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type;
+ typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type;
+ typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type;
+ typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type;
+ typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type;
+
+ font_engine_freetype_int16(unsigned max_faces = 32) :
+ font_engine_freetype_base(false, max_faces) {}
+ };
+
+ //------------------------------------------------font_engine_freetype_int32
+ // This class uses values of type int32 (26.6 format) for the vector cache.
+ // The vector cache is twice larger than in font_engine_freetype_int16,
+ // but it allows you to render glyphs of very large sizes.
+ //
+ class font_engine_freetype_int32 : public font_engine_freetype_base
+ {
+ public:
+ typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type;
+ typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type;
+ typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type;
+ typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type;
+ typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type;
+
+ font_engine_freetype_int32(unsigned max_faces = 32) :
+ font_engine_freetype_base(true, max_faces) {}
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_font_win32_tt.h b/plugins/Clist_ng/AGG/include/agg_font_win32_tt.h new file mode 100644 index 0000000000..149a89a642 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_font_win32_tt.h @@ -0,0 +1,223 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_FONT_WIN32_TT_INCLUDED
+#define AGG_FONT_WIN32_TT_INCLUDED
+
+#include <windows.h>
+#include "agg_scanline_storage_aa.h"
+#include "agg_scanline_storage_bin.h"
+#include "agg_scanline_u.h"
+#include "agg_scanline_bin.h"
+#include "agg_path_storage_integer.h"
+#include "agg_rasterizer_scanline_aa.h"
+#include "agg_conv_curve.h"
+#include "agg_trans_affine.h"
+#include "agg_font_cache_manager.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------font_engine_win32_tt_base
+ class font_engine_win32_tt_base
+ {
+ enum { buf_size = 32768-32 };
+
+ public:
+ //--------------------------------------------------------------------
+ typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type;
+ typedef serialized_scanlines_adaptor_bin mono_adaptor_type;
+ typedef scanline_storage_aa8 scanlines_aa_type;
+ typedef scanline_storage_bin scanlines_bin_type;
+
+ //--------------------------------------------------------------------
+ ~font_engine_win32_tt_base();
+ font_engine_win32_tt_base(bool flag32, HDC dc, unsigned max_fonts = 32);
+
+ // Set font parameters
+ //--------------------------------------------------------------------
+ void resolution(unsigned dpi) { m_resolution = unsigned(dpi); }
+ void height(double h) { m_height = unsigned(h); }
+ void width(double w) { m_width = unsigned(w); }
+ void weight(int w) { m_weight = w; }
+ void italic(bool it) { m_italic = it; }
+ void char_set(DWORD c) { m_char_set = c; }
+ void pitch_and_family(DWORD p){ m_pitch_and_family = p; }
+ void flip_y(bool flip) { m_flip_y = flip; }
+ void hinting(bool h) { m_hinting = h; }
+ bool create_font(const char* typeface_, glyph_rendering ren_type);
+
+ bool create_font(const char* typeface_,
+ glyph_rendering ren_type,
+ double height_,
+ double width_=0.0,
+ int weight_=FW_REGULAR,
+ bool italic_=false,
+ DWORD char_set_=ANSI_CHARSET,
+ DWORD pitch_and_family_=FF_DONTCARE);
+
+ // Set Gamma
+ //--------------------------------------------------------------------
+ template<class GammaF> void gamma(const GammaF& f)
+ {
+ m_rasterizer.gamma(f);
+ }
+
+ //--------------------------------------------------------------------
+ void transform(const agg::trans_affine& mtx)
+ {
+ m_affine = mtx;
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+ unsigned resolution() const { return m_resolution; }
+ const char* typeface() const { return m_typeface; }
+ double height() const { return m_height; }
+ double width() const { return m_width; }
+ int weight() const { return m_weight; }
+ bool italic() const { return m_italic; }
+ DWORD char_set() const { return m_char_set; }
+ DWORD pitch_and_family() const { return m_pitch_and_family; }
+ bool hinting() const { return m_hinting; }
+ bool flip_y() const { return m_flip_y; }
+
+
+ // Interface mandatory to implement for font_cache_manager
+ //--------------------------------------------------------------------
+ const char* font_signature() const { return m_signature; }
+ int change_stamp() const { return m_change_stamp; }
+
+ bool prepare_glyph(unsigned glyph_code);
+ unsigned glyph_index() const { return m_glyph_index; }
+ unsigned data_size() const { return m_data_size; }
+ glyph_data_type data_type() const { return m_data_type; }
+ const rect_i& bounds() const { return m_bounds; }
+ double advance_x() const { return m_advance_x; }
+ double advance_y() const { return m_advance_y; }
+ void write_glyph_to(int8u* data) const;
+ bool add_kerning(unsigned first, unsigned second,
+ double* x, double* y);
+
+ private:
+ font_engine_win32_tt_base(const font_engine_win32_tt_base&);
+ const font_engine_win32_tt_base& operator = (const font_engine_win32_tt_base&);
+
+ void update_signature();
+ void load_kerning_pairs();
+ void sort_kerning_pairs();
+ int find_font(const char* name) const;
+
+ bool m_flag32;
+ HDC m_dc;
+ HFONT m_old_font;
+ HFONT* m_fonts;
+ unsigned m_num_fonts;
+ unsigned m_max_fonts;
+ char** m_font_names;
+ HFONT m_cur_font;
+
+ int m_change_stamp;
+ char* m_typeface;
+ unsigned m_typeface_len;
+ char* m_signature;
+ unsigned m_height;
+ unsigned m_width;
+ int m_weight;
+ bool m_italic;
+ DWORD m_char_set;
+ DWORD m_pitch_and_family;
+ bool m_hinting;
+ bool m_flip_y;
+
+ bool m_font_created;
+ unsigned m_resolution;
+ glyph_rendering m_glyph_rendering;
+ unsigned m_glyph_index;
+ unsigned m_data_size;
+ glyph_data_type m_data_type;
+ rect_i m_bounds;
+ double m_advance_x;
+ double m_advance_y;
+ MAT2 m_matrix;
+ char* m_gbuf;
+ KERNINGPAIR* m_kerning_pairs;
+ unsigned m_num_kerning_pairs;
+ unsigned m_max_kerning_pairs;
+ trans_affine m_affine;
+
+ path_storage_integer<int16, 6> m_path16;
+ path_storage_integer<int32, 6> m_path32;
+ conv_curve<path_storage_integer<int16, 6> > m_curves16;
+ conv_curve<path_storage_integer<int32, 6> > m_curves32;
+ scanline_u8 m_scanline_aa;
+ scanline_bin m_scanline_bin;
+ scanlines_aa_type m_scanlines_aa;
+ scanlines_bin_type m_scanlines_bin;
+ rasterizer_scanline_aa<> m_rasterizer;
+ };
+
+
+
+
+ //------------------------------------------------font_engine_win32_tt_int16
+ // This class uses values of type int16 (10.6 format) for the vector cache.
+ // The vector cache is compact, but when rendering glyphs of height
+ // more that 200 there integer overflow can occur.
+ //
+ class font_engine_win32_tt_int16 : public font_engine_win32_tt_base
+ {
+ public:
+ typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type;
+ typedef font_engine_win32_tt_base::gray8_adaptor_type gray8_adaptor_type;
+ typedef font_engine_win32_tt_base::mono_adaptor_type mono_adaptor_type;
+ typedef font_engine_win32_tt_base::scanlines_aa_type scanlines_aa_type;
+ typedef font_engine_win32_tt_base::scanlines_bin_type scanlines_bin_type;
+
+ font_engine_win32_tt_int16(HDC dc, unsigned max_fonts = 32) :
+ font_engine_win32_tt_base(false, dc, max_fonts) {}
+ };
+
+ //------------------------------------------------font_engine_win32_tt_int32
+ // This class uses values of type int32 (26.6 format) for the vector cache.
+ // The vector cache is twice larger than in font_engine_win32_tt_int16,
+ // but it allows you to render glyphs of very large sizes.
+ //
+ class font_engine_win32_tt_int32 : public font_engine_win32_tt_base
+ {
+ public:
+ typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type;
+ typedef font_engine_win32_tt_base::gray8_adaptor_type gray8_adaptor_type;
+ typedef font_engine_win32_tt_base::mono_adaptor_type mono_adaptor_type;
+ typedef font_engine_win32_tt_base::scanlines_aa_type scanlines_aa_type;
+ typedef font_engine_win32_tt_base::scanlines_bin_type scanlines_bin_type;
+
+ font_engine_win32_tt_int32(HDC dc, unsigned max_fonts = 32) :
+ font_engine_win32_tt_base(true, dc, max_fonts) {}
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_gamma_functions.h b/plugins/Clist_ng/AGG/include/agg_gamma_functions.h new file mode 100644 index 0000000000..8c49cfa7ef --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_gamma_functions.h @@ -0,0 +1,132 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
+#define AGG_GAMMA_FUNCTIONS_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+ //===============================================================gamma_none
+ struct gamma_none
+ {
+ double operator()(double x) const { return x; }
+ };
+
+
+ //==============================================================gamma_power
+ class gamma_power
+ {
+ public:
+ gamma_power() : m_gamma(1.0) {}
+ gamma_power(double g) : m_gamma(g) {}
+
+ void gamma(double g) { m_gamma = g; }
+ double gamma() const { return m_gamma; }
+
+ double operator() (double x) const
+ {
+ return pow(x, m_gamma);
+ }
+
+ private:
+ double m_gamma;
+ };
+
+
+ //==========================================================gamma_threshold
+ class gamma_threshold
+ {
+ public:
+ gamma_threshold() : m_threshold(0.5) {}
+ gamma_threshold(double t) : m_threshold(t) {}
+
+ void threshold(double t) { m_threshold = t; }
+ double threshold() const { return m_threshold; }
+
+ double operator() (double x) const
+ {
+ return (x < m_threshold) ? 0.0 : 1.0;
+ }
+
+ private:
+ double m_threshold;
+ };
+
+
+ //============================================================gamma_linear
+ class gamma_linear
+ {
+ public:
+ gamma_linear() : m_start(0.0), m_end(1.0) {}
+ gamma_linear(double s, double e) : m_start(s), m_end(e) {}
+
+ void set(double s, double e) { m_start = s; m_end = e; }
+ void start(double s) { m_start = s; }
+ void end(double e) { m_end = e; }
+ double start() const { return m_start; }
+ double end() const { return m_end; }
+
+ double operator() (double x) const
+ {
+ if(x < m_start) return 0.0;
+ if(x > m_end) return 1.0;
+ return (x - m_start) / (m_end - m_start);
+ }
+
+ private:
+ double m_start;
+ double m_end;
+ };
+
+
+ //==========================================================gamma_multiply
+ class gamma_multiply
+ {
+ public:
+ gamma_multiply() : m_mul(1.0) {}
+ gamma_multiply(double v) : m_mul(v) {}
+
+ void value(double v) { m_mul = v; }
+ double value() const { return m_mul; }
+
+ double operator() (double x) const
+ {
+ double y = x * m_mul;
+ if(y > 1.0) y = 1.0;
+ return y;
+ }
+
+ private:
+ double m_mul;
+ };
+
+}
+
+#endif
+
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_gamma_lut.h b/plugins/Clist_ng/AGG/include/agg_gamma_lut.h new file mode 100644 index 0000000000..e9ffbf580c --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_gamma_lut.h @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_GAMMA_LUT_INCLUDED
+#define AGG_GAMMA_LUT_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+ template<class LoResT=int8u,
+ class HiResT=int8u,
+ unsigned GammaShift=8,
+ unsigned HiResShift=8> class gamma_lut
+ {
+ public:
+ typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
+
+ enum gamma_scale_e
+ {
+ gamma_shift = GammaShift,
+ gamma_size = 1 << gamma_shift,
+ gamma_mask = gamma_size - 1
+ };
+
+ enum hi_res_scale_e
+ {
+ hi_res_shift = HiResShift,
+ hi_res_size = 1 << hi_res_shift,
+ hi_res_mask = hi_res_size - 1
+ };
+
+ ~gamma_lut()
+ {
+ pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
+ pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
+ }
+
+ gamma_lut() :
+ m_gamma(1.0),
+ m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
+ m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
+ {
+ unsigned i;
+ for(i = 0; i < gamma_size; i++)
+ {
+ m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
+ }
+
+ for(i = 0; i < hi_res_size; i++)
+ {
+ m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
+ }
+ }
+
+ gamma_lut(double g) :
+ m_gamma(1.0),
+ m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
+ m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
+ {
+ gamma(g);
+ }
+
+ void gamma(double g)
+ {
+ m_gamma = g;
+
+ unsigned i;
+ for(i = 0; i < gamma_size; i++)
+ {
+ m_dir_gamma[i] = (HiResT)
+ uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
+ }
+
+ double inv_g = 1.0 / g;
+ for(i = 0; i < hi_res_size; i++)
+ {
+ m_inv_gamma[i] = (LoResT)
+ uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
+ }
+ }
+
+ double gamma() const
+ {
+ return m_gamma;
+ }
+
+ HiResT dir(LoResT v) const
+ {
+ return m_dir_gamma[unsigned(v)];
+ }
+
+ LoResT inv(HiResT v) const
+ {
+ return m_inv_gamma[unsigned(v)];
+ }
+
+ private:
+ gamma_lut(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ double m_gamma;
+ HiResT* m_dir_gamma;
+ LoResT* m_inv_gamma;
+ };
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_glyph_raster_bin.h b/plugins/Clist_ng/AGG/include/agg_glyph_raster_bin.h new file mode 100644 index 0000000000..085f1f21bf --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_glyph_raster_bin.h @@ -0,0 +1,164 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_GLYPH_RASTER_BIN_INCLUDED
+#define AGG_GLYPH_RASTER_BIN_INCLUDED
+
+#include <string.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //========================================================glyph_raster_bin
+ template<class ColorT> class glyph_raster_bin
+ {
+ public:
+ typedef ColorT color_type;
+
+ //--------------------------------------------------------------------
+ struct glyph_rect
+ {
+ int x1,y1,x2,y2;
+ double dx, dy;
+ };
+
+ //--------------------------------------------------------------------
+ glyph_raster_bin(const int8u* font) :
+ m_font(font),
+ m_big_endian(false)
+ {
+ int t = 1;
+ if(*(char*)&t == 0) m_big_endian = true;
+ memset(m_span, 0, sizeof(m_span));
+ }
+
+ //--------------------------------------------------------------------
+ const int8u* font() const { return m_font; }
+ void font(const int8u* f) { m_font = f; }
+
+ //--------------------------------------------------------------------
+ double height() const { return m_font[0]; }
+ double base_line() const { return m_font[1]; }
+
+ //--------------------------------------------------------------------
+ template<class CharT>
+ double width(const CharT* str) const
+ {
+ unsigned start_char = m_font[2];
+ unsigned num_chars = m_font[3];
+
+ unsigned w = 0;
+ while(*str)
+ {
+ unsigned glyph = *str;
+ const int8u* bits = m_font + 4 + num_chars * 2 +
+ value(m_font + 4 + (glyph - start_char) * 2);
+ w += *bits;
+ ++str;
+ }
+ return w;
+ }
+
+ //--------------------------------------------------------------------
+ void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip)
+ {
+ unsigned start_char = m_font[2];
+ unsigned num_chars = m_font[3];
+
+ m_bits = m_font + 4 + num_chars * 2 +
+ value(m_font + 4 + (glyph - start_char) * 2);
+
+ m_glyph_width = *m_bits++;
+ m_glyph_byte_width = (m_glyph_width + 7) >> 3;
+
+ r->x1 = int(x);
+ r->x2 = r->x1 + m_glyph_width - 1;
+ if(flip)
+ {
+ r->y1 = int(y) - m_font[0] + m_font[1];
+ r->y2 = r->y1 + m_font[0] - 1;
+ }
+ else
+ {
+ r->y1 = int(y) - m_font[1] + 1;
+ r->y2 = r->y1 + m_font[0] - 1;
+ }
+ r->dx = m_glyph_width;
+ r->dy = 0;
+ }
+
+ //--------------------------------------------------------------------
+ const cover_type* span(unsigned i)
+ {
+ i = m_font[0] - i - 1;
+ const int8u* bits = m_bits + i * m_glyph_byte_width;
+ unsigned j;
+ unsigned val = *bits;
+ unsigned nb = 0;
+ for(j = 0; j < m_glyph_width; ++j)
+ {
+ m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none);
+ val <<= 1;
+ if(++nb >= 8)
+ {
+ val = *++bits;
+ nb = 0;
+ }
+ }
+ return m_span;
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ int16u value(const int8u* p) const
+ {
+ int16u v;
+ if(m_big_endian)
+ {
+ *(int8u*)&v = p[1];
+ *((int8u*)&v + 1) = p[0];
+ }
+ else
+ {
+ *(int8u*)&v = p[0];
+ *((int8u*)&v + 1) = p[1];
+ }
+ return v;
+ }
+
+
+ //--------------------------------------------------------------------
+ const int8u* m_font;
+ bool m_big_endian;
+ cover_type m_span[32];
+ const int8u* m_bits;
+ unsigned m_glyph_width;
+ unsigned m_glyph_byte_width;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_gradient_lut.h b/plugins/Clist_ng/AGG/include/agg_gradient_lut.h new file mode 100644 index 0000000000..905780bd3c --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_gradient_lut.h @@ -0,0 +1,253 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_GRADIENT_LUT_INCLUDED
+#define AGG_GRADIENT_LUT_INCLUDED
+
+#include "agg_array.h"
+#include "agg_dda_line.h"
+#include "agg_color_rgba.h"
+#include "agg_color_gray.h"
+
+namespace agg
+{
+
+ //======================================================color_interpolator
+ template<class ColorT> struct color_interpolator
+ {
+ public:
+ typedef ColorT color_type;
+
+ color_interpolator(const color_type& c1,
+ const color_type& c2,
+ unsigned len) :
+ m_c1(c1),
+ m_c2(c2),
+ m_len(len),
+ m_count(0)
+ {}
+
+ void operator ++ ()
+ {
+ ++m_count;
+ }
+
+ color_type color() const
+ {
+ return m_c1.gradient(m_c2, double(m_count) / m_len);
+ }
+
+ private:
+ color_type m_c1;
+ color_type m_c2;
+ unsigned m_len;
+ unsigned m_count;
+ };
+
+ //========================================================================
+ // Fast specialization for rgba8
+ template<> struct color_interpolator<rgba8>
+ {
+ public:
+ typedef rgba8 color_type;
+
+ color_interpolator(const color_type& c1,
+ const color_type& c2,
+ unsigned len) :
+ r(c1.r, c2.r, len),
+ g(c1.g, c2.g, len),
+ b(c1.b, c2.b, len),
+ a(c1.a, c2.a, len)
+ {}
+
+ void operator ++ ()
+ {
+ ++r; ++g; ++b; ++a;
+ }
+
+ color_type color() const
+ {
+ return color_type(r.y(), g.y(), b.y(), a.y());
+ }
+
+ private:
+ agg::dda_line_interpolator<14> r, g, b, a;
+ };
+
+ //========================================================================
+ // Fast specialization for gray8
+ template<> struct color_interpolator<gray8>
+ {
+ public:
+ typedef gray8 color_type;
+
+ color_interpolator(const color_type& c1,
+ const color_type& c2,
+ unsigned len) :
+ v(c1.v, c2.v, len),
+ a(c1.a, c2.a, len)
+ {}
+
+ void operator ++ ()
+ {
+ ++v; ++a;
+ }
+
+ color_type color() const
+ {
+ return color_type(v.y(), a.y());
+ }
+
+ private:
+ agg::dda_line_interpolator<14> v,a;
+ };
+
+ //============================================================gradient_lut
+ template<class ColorInterpolator,
+ unsigned ColorLutSize=256> class gradient_lut
+ {
+ public:
+ typedef ColorInterpolator interpolator_type;
+ typedef typename interpolator_type::color_type color_type;
+ enum { color_lut_size = ColorLutSize };
+
+ //--------------------------------------------------------------------
+ gradient_lut() : m_color_lut(color_lut_size) {}
+
+ // Build Gradient Lut
+ // First, call remove_all(), then add_color() at least twice,
+ // then build_lut(). Argument "offset" in add_color must be
+ // in range [0...1] and defines a color stop as it is described
+ // in SVG specification, section Gradients and Patterns.
+ // The simplest linear gradient is:
+ // gradient_lut.add_color(0.0, start_color);
+ // gradient_lut.add_color(1.0, end_color);
+ //--------------------------------------------------------------------
+ void remove_all();
+ void add_color(double offset, const color_type& color);
+ void build_lut();
+
+ // Size-index Interface. This class can be used directly as the
+ // ColorF in span_gradient. All it needs is two access methods
+ // size() and operator [].
+ //--------------------------------------------------------------------
+ static unsigned size()
+ {
+ return color_lut_size;
+ }
+ const color_type& operator [] (unsigned i) const
+ {
+ return m_color_lut[i];
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ struct color_point
+ {
+ double offset;
+ color_type color;
+
+ color_point() {}
+ color_point(double off, const color_type& c) :
+ offset(off), color(c)
+ {
+ if(offset < 0.0) offset = 0.0;
+ if(offset > 1.0) offset = 1.0;
+ }
+ };
+ typedef agg::pod_bvector<color_point, 4> color_profile_type;
+ typedef agg::pod_array<color_type> color_lut_type;
+
+ static bool offset_less(const color_point& a, const color_point& b)
+ {
+ return a.offset < b.offset;
+ }
+ static bool offset_equal(const color_point& a, const color_point& b)
+ {
+ return a.offset == b.offset;
+ }
+
+ //--------------------------------------------------------------------
+ color_profile_type m_color_profile;
+ color_lut_type m_color_lut;
+ };
+
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void gradient_lut<T,S>::remove_all()
+ {
+ m_color_profile.remove_all();
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void gradient_lut<T,S>::add_color(double offset, const color_type& color)
+ {
+ m_color_profile.add(color_point(offset, color));
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void gradient_lut<T,S>::build_lut()
+ {
+ quick_sort(m_color_profile, offset_less);
+ m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
+ if(m_color_profile.size() >= 2)
+ {
+ unsigned i;
+ unsigned start = uround(m_color_profile[0].offset * color_lut_size);
+ unsigned end;
+ color_type c = m_color_profile[0].color;
+ for(i = 0; i < start; i++)
+ {
+ m_color_lut[i] = c;
+ }
+ for(i = 1; i < m_color_profile.size(); i++)
+ {
+ end = uround(m_color_profile[i].offset * color_lut_size);
+ interpolator_type ci(m_color_profile[i-1].color,
+ m_color_profile[i ].color,
+ end - start + 1);
+ while(start < end)
+ {
+ m_color_lut[start] = ci.color();
+ ++ci;
+ ++start;
+ }
+ }
+ c = m_color_profile.last().color;
+ for(; end < m_color_lut.size(); end++)
+ {
+ m_color_lut[end] = c;
+ }
+ }
+ }
+}
+
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_gsv_text.h b/plugins/Clist_ng/AGG/include/agg_gsv_text.h new file mode 100644 index 0000000000..adcefb4308 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_gsv_text.h @@ -0,0 +1,158 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_GSV_TEXT_INCLUDED
+#define AGG_GSV_TEXT_INCLUDED
+
+#include "agg_array.h"
+#include "agg_conv_stroke.h"
+#include "agg_conv_transform.h"
+
+namespace agg
+{
+
+
+ //---------------------------------------------------------------gsv_text
+ //
+ // See Implementation agg_gsv_text.cpp
+ //
+ class gsv_text
+ {
+ enum status
+ {
+ initial,
+ next_char,
+ start_glyph,
+ glyph
+ };
+
+ public:
+ gsv_text();
+
+ void font(const void* font);
+ void flip(bool flip_y) { m_flip = flip_y; }
+ void load_font(const char* file);
+ void size(double height, double width=0.0);
+ void space(double space);
+ void line_space(double line_space);
+ void start_point(double x, double y);
+ void text(const char* text);
+
+ double text_width();
+
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ // not supposed to be copied
+ gsv_text(const gsv_text&);
+ const gsv_text& operator = (const gsv_text&);
+
+ int16u value(const int8u* p) const
+ {
+ int16u v;
+ if(m_big_endian)
+ {
+ *(int8u*)&v = p[1];
+ *((int8u*)&v + 1) = p[0];
+ }
+ else
+ {
+ *(int8u*)&v = p[0];
+ *((int8u*)&v + 1) = p[1];
+ }
+ return v;
+ }
+
+ private:
+ double m_x;
+ double m_y;
+ double m_start_x;
+ double m_width;
+ double m_height;
+ double m_space;
+ double m_line_space;
+ char m_chr[2];
+ char* m_text;
+ pod_array<char> m_text_buf;
+ char* m_cur_chr;
+ const void* m_font;
+ pod_array<char> m_loaded_font;
+ status m_status;
+ bool m_big_endian;
+ bool m_flip;
+ int8u* m_indices;
+ int8* m_glyphs;
+ int8* m_bglyph;
+ int8* m_eglyph;
+ double m_w;
+ double m_h;
+ };
+
+
+
+
+ //--------------------------------------------------------gsv_text_outline
+ template<class Transformer = trans_affine> class gsv_text_outline
+ {
+ public:
+ gsv_text_outline(gsv_text& text, const Transformer& trans) :
+ m_polyline(text),
+ m_trans(m_polyline, trans)
+ {
+ }
+
+ void width(double w)
+ {
+ m_polyline.width(w);
+ }
+
+ void transformer(const Transformer* trans)
+ {
+ m_trans->transformer(trans);
+ }
+
+ void rewind(unsigned path_id)
+ {
+ m_trans.rewind(path_id);
+ m_polyline.line_join(round_join);
+ m_polyline.line_cap(round_cap);
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ return m_trans.vertex(x, y);
+ }
+
+ private:
+ conv_stroke<gsv_text> m_polyline;
+ conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
+ };
+
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_image_accessors.h b/plugins/Clist_ng/AGG/include/agg_image_accessors.h new file mode 100644 index 0000000000..b4d72a28a9 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_image_accessors.h @@ -0,0 +1,490 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_IMAGE_ACCESSORS_INCLUDED
+#define AGG_IMAGE_ACCESSORS_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------------image_accessor_clip
+ template<class PixFmt> class image_accessor_clip
+ {
+ public:
+ typedef PixFmt pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::order_type order_type;
+ typedef typename pixfmt_type::value_type value_type;
+ enum pix_width_e { pix_width = pixfmt_type::pix_width };
+
+ image_accessor_clip() {}
+ explicit image_accessor_clip(const pixfmt_type& pixf,
+ const color_type& bk) :
+ m_pixf(&pixf)
+ {
+ pixfmt_type::make_pix(m_bk_buf, bk);
+ }
+
+ void attach(const pixfmt_type& pixf)
+ {
+ m_pixf = &pixf;
+ }
+
+ void background_color(const color_type& bk)
+ {
+ pixfmt_type::make_pix(m_bk_buf, bk);
+ }
+
+ private:
+ AGG_INLINE const int8u* pixel() const
+ {
+ if(m_y >= 0 && m_y < (int)m_pixf->height() &&
+ m_x >= 0 && m_x < (int)m_pixf->width())
+ {
+ return m_pixf->pix_ptr(m_x, m_y);
+ }
+ return m_bk_buf;
+ }
+
+ public:
+ AGG_INLINE const int8u* span(int x, int y, unsigned len)
+ {
+ m_x = m_x0 = x;
+ m_y = y;
+ if(y >= 0 && y < (int)m_pixf->height() &&
+ x >= 0 && x+(int)len <= (int)m_pixf->width())
+ {
+ return m_pix_ptr = m_pixf->pix_ptr(x, y);
+ }
+ m_pix_ptr = 0;
+ return pixel();
+ }
+
+ AGG_INLINE const int8u* next_x()
+ {
+ if(m_pix_ptr) return m_pix_ptr += pix_width;
+ ++m_x;
+ return pixel();
+ }
+
+ AGG_INLINE const int8u* next_y()
+ {
+ ++m_y;
+ m_x = m_x0;
+ if(m_pix_ptr &&
+ m_y >= 0 && m_y < (int)m_pixf->height())
+ {
+ return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
+ }
+ m_pix_ptr = 0;
+ return pixel();
+ }
+
+ private:
+ const pixfmt_type* m_pixf;
+ int8u m_bk_buf[4];
+ int m_x, m_x0, m_y;
+ const int8u* m_pix_ptr;
+ };
+
+
+
+
+ //--------------------------------------------------image_accessor_no_clip
+ template<class PixFmt> class image_accessor_no_clip
+ {
+ public:
+ typedef PixFmt pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::order_type order_type;
+ typedef typename pixfmt_type::value_type value_type;
+ enum pix_width_e { pix_width = pixfmt_type::pix_width };
+
+ image_accessor_no_clip() {}
+ explicit image_accessor_no_clip(const pixfmt_type& pixf) :
+ m_pixf(&pixf)
+ {}
+
+ void attach(const pixfmt_type& pixf)
+ {
+ m_pixf = &pixf;
+ }
+
+ AGG_INLINE const int8u* span(int x, int y, unsigned)
+ {
+ m_x = x;
+ m_y = y;
+ return m_pix_ptr = m_pixf->pix_ptr(x, y);
+ }
+
+ AGG_INLINE const int8u* next_x()
+ {
+ return m_pix_ptr += pix_width;
+ }
+
+ AGG_INLINE const int8u* next_y()
+ {
+ ++m_y;
+ return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
+ }
+
+ private:
+ const pixfmt_type* m_pixf;
+ int m_x, m_y;
+ const int8u* m_pix_ptr;
+ };
+
+
+
+
+ //----------------------------------------------------image_accessor_clone
+ template<class PixFmt> class image_accessor_clone
+ {
+ public:
+ typedef PixFmt pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::order_type order_type;
+ typedef typename pixfmt_type::value_type value_type;
+ enum pix_width_e { pix_width = pixfmt_type::pix_width };
+
+ image_accessor_clone() {}
+ explicit image_accessor_clone(const pixfmt_type& pixf) :
+ m_pixf(&pixf)
+ {}
+
+ void attach(const pixfmt_type& pixf)
+ {
+ m_pixf = &pixf;
+ }
+
+ private:
+ AGG_INLINE const int8u* pixel() const
+ {
+ register int x = m_x;
+ register int y = m_y;
+ if(x < 0) x = 0;
+ if(y < 0) y = 0;
+ if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1;
+ if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1;
+ return m_pixf->pix_ptr(x, y);
+ }
+
+ public:
+ AGG_INLINE const int8u* span(int x, int y, unsigned len)
+ {
+ m_x = m_x0 = x;
+ m_y = y;
+ if(y >= 0 && y < (int)m_pixf->height() &&
+ x >= 0 && x+len <= (int)m_pixf->width())
+ {
+ return m_pix_ptr = m_pixf->pix_ptr(x, y);
+ }
+ m_pix_ptr = 0;
+ return pixel();
+ }
+
+ AGG_INLINE const int8u* next_x()
+ {
+ if(m_pix_ptr) return m_pix_ptr += pix_width;
+ ++m_x;
+ return pixel();
+ }
+
+ AGG_INLINE const int8u* next_y()
+ {
+ ++m_y;
+ m_x = m_x0;
+ if(m_pix_ptr &&
+ m_y >= 0 && m_y < (int)m_pixf->height())
+ {
+ return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
+ }
+ m_pix_ptr = 0;
+ return pixel();
+ }
+
+ private:
+ const pixfmt_type* m_pixf;
+ int m_x, m_x0, m_y;
+ const int8u* m_pix_ptr;
+ };
+
+
+
+
+
+ //-----------------------------------------------------image_accessor_wrap
+ template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap
+ {
+ public:
+ typedef PixFmt pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::order_type order_type;
+ typedef typename pixfmt_type::value_type value_type;
+ enum pix_width_e { pix_width = pixfmt_type::pix_width };
+
+ image_accessor_wrap() {}
+ explicit image_accessor_wrap(const pixfmt_type& pixf) :
+ m_pixf(&pixf),
+ m_wrap_x(pixf.width()),
+ m_wrap_y(pixf.height())
+ {}
+
+ void attach(const pixfmt_type& pixf)
+ {
+ m_pixf = &pixf;
+ }
+
+ AGG_INLINE const int8u* span(int x, int y, unsigned)
+ {
+ m_x = x;
+ m_row_ptr = m_pixf->row_ptr(m_wrap_y(y));
+ return m_row_ptr + m_wrap_x(x) * pix_width;
+ }
+
+ AGG_INLINE const int8u* next_x()
+ {
+ int x = ++m_wrap_x;
+ return m_row_ptr + x * pix_width;
+ }
+
+ AGG_INLINE const int8u* next_y()
+ {
+ m_row_ptr = m_pixf->row_ptr(++m_wrap_y);
+ return m_row_ptr + m_wrap_x(m_x) * pix_width;
+ }
+
+ private:
+ const pixfmt_type* m_pixf;
+ const int8u* m_row_ptr;
+ int m_x;
+ WrapX m_wrap_x;
+ WrapY m_wrap_y;
+ };
+
+
+
+
+ //--------------------------------------------------------wrap_mode_repeat
+ class wrap_mode_repeat
+ {
+ public:
+ wrap_mode_repeat() {}
+ wrap_mode_repeat(unsigned size) :
+ m_size(size),
+ m_add(size * (0x3FFFFFFF / size)),
+ m_value(0)
+ {}
+
+ AGG_INLINE unsigned operator() (int v)
+ {
+ return m_value = (unsigned(v) + m_add) % m_size;
+ }
+
+ AGG_INLINE unsigned operator++ ()
+ {
+ ++m_value;
+ if(m_value >= m_size) m_value = 0;
+ return m_value;
+ }
+ private:
+ unsigned m_size;
+ unsigned m_add;
+ unsigned m_value;
+ };
+
+
+ //---------------------------------------------------wrap_mode_repeat_pow2
+ class wrap_mode_repeat_pow2
+ {
+ public:
+ wrap_mode_repeat_pow2() {}
+ wrap_mode_repeat_pow2(unsigned size) : m_value(0)
+ {
+ m_mask = 1;
+ while(m_mask < size) m_mask = (m_mask << 1) | 1;
+ m_mask >>= 1;
+ }
+ AGG_INLINE unsigned operator() (int v)
+ {
+ return m_value = unsigned(v) & m_mask;
+ }
+ AGG_INLINE unsigned operator++ ()
+ {
+ ++m_value;
+ if(m_value > m_mask) m_value = 0;
+ return m_value;
+ }
+ private:
+ unsigned m_mask;
+ unsigned m_value;
+ };
+
+
+ //----------------------------------------------wrap_mode_repeat_auto_pow2
+ class wrap_mode_repeat_auto_pow2
+ {
+ public:
+ wrap_mode_repeat_auto_pow2() {}
+ wrap_mode_repeat_auto_pow2(unsigned size) :
+ m_size(size),
+ m_add(size * (0x3FFFFFFF / size)),
+ m_mask((m_size & (m_size-1)) ? 0 : m_size-1),
+ m_value(0)
+ {}
+
+ AGG_INLINE unsigned operator() (int v)
+ {
+ if(m_mask) return m_value = unsigned(v) & m_mask;
+ return m_value = (unsigned(v) + m_add) % m_size;
+ }
+ AGG_INLINE unsigned operator++ ()
+ {
+ ++m_value;
+ if(m_value >= m_size) m_value = 0;
+ return m_value;
+ }
+
+ private:
+ unsigned m_size;
+ unsigned m_add;
+ unsigned m_mask;
+ unsigned m_value;
+ };
+
+
+ //-------------------------------------------------------wrap_mode_reflect
+ class wrap_mode_reflect
+ {
+ public:
+ wrap_mode_reflect() {}
+ wrap_mode_reflect(unsigned size) :
+ m_size(size),
+ m_size2(size * 2),
+ m_add(m_size2 * (0x3FFFFFFF / m_size2)),
+ m_value(0)
+ {}
+
+ AGG_INLINE unsigned operator() (int v)
+ {
+ m_value = (unsigned(v) + m_add) % m_size2;
+ if(m_value >= m_size) return m_size2 - m_value - 1;
+ return m_value;
+ }
+
+ AGG_INLINE unsigned operator++ ()
+ {
+ ++m_value;
+ if(m_value >= m_size2) m_value = 0;
+ if(m_value >= m_size) return m_size2 - m_value - 1;
+ return m_value;
+ }
+ private:
+ unsigned m_size;
+ unsigned m_size2;
+ unsigned m_add;
+ unsigned m_value;
+ };
+
+
+
+ //--------------------------------------------------wrap_mode_reflect_pow2
+ class wrap_mode_reflect_pow2
+ {
+ public:
+ wrap_mode_reflect_pow2() {}
+ wrap_mode_reflect_pow2(unsigned size) : m_value(0)
+ {
+ m_mask = 1;
+ m_size = 1;
+ while(m_mask < size)
+ {
+ m_mask = (m_mask << 1) | 1;
+ m_size <<= 1;
+ }
+ }
+ AGG_INLINE unsigned operator() (int v)
+ {
+ m_value = unsigned(v) & m_mask;
+ if(m_value >= m_size) return m_mask - m_value;
+ return m_value;
+ }
+ AGG_INLINE unsigned operator++ ()
+ {
+ ++m_value;
+ m_value &= m_mask;
+ if(m_value >= m_size) return m_mask - m_value;
+ return m_value;
+ }
+ private:
+ unsigned m_size;
+ unsigned m_mask;
+ unsigned m_value;
+ };
+
+
+
+ //---------------------------------------------wrap_mode_reflect_auto_pow2
+ class wrap_mode_reflect_auto_pow2
+ {
+ public:
+ wrap_mode_reflect_auto_pow2() {}
+ wrap_mode_reflect_auto_pow2(unsigned size) :
+ m_size(size),
+ m_size2(size * 2),
+ m_add(m_size2 * (0x3FFFFFFF / m_size2)),
+ m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1),
+ m_value(0)
+ {}
+
+ AGG_INLINE unsigned operator() (int v)
+ {
+ m_value = m_mask ? unsigned(v) & m_mask :
+ (unsigned(v) + m_add) % m_size2;
+ if(m_value >= m_size) return m_size2 - m_value - 1;
+ return m_value;
+ }
+ AGG_INLINE unsigned operator++ ()
+ {
+ ++m_value;
+ if(m_value >= m_size2) m_value = 0;
+ if(m_value >= m_size) return m_size2 - m_value - 1;
+ return m_value;
+ }
+
+ private:
+ unsigned m_size;
+ unsigned m_size2;
+ unsigned m_add;
+ unsigned m_mask;
+ unsigned m_value;
+ };
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_image_filters.h b/plugins/Clist_ng/AGG/include/agg_image_filters.h new file mode 100644 index 0000000000..e66f8a782a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_image_filters.h @@ -0,0 +1,453 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_IMAGE_FILTERS_INCLUDED
+#define AGG_IMAGE_FILTERS_INCLUDED
+
+#include "agg_array.h"
+#include "agg_math.h"
+
+namespace agg
+{
+
+ // See Implementation agg_image_filters.cpp
+
+ enum image_filter_scale_e
+ {
+ image_filter_shift = 14, //----image_filter_shift
+ image_filter_scale = 1 << image_filter_shift, //----image_filter_scale
+ image_filter_mask = image_filter_scale - 1 //----image_filter_mask
+ };
+
+ enum image_subpixel_scale_e
+ {
+ image_subpixel_shift = 8, //----image_subpixel_shift
+ image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale
+ image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask
+ };
+
+
+ //-----------------------------------------------------image_filter_lut
+ class image_filter_lut
+ {
+ public:
+ template<class FilterF> void calculate(const FilterF& filter,
+ bool normalization=true)
+ {
+ double r = filter.radius();
+ realloc_lut(r);
+ unsigned i;
+ unsigned pivot = diameter() << (image_subpixel_shift - 1);
+ for(i = 0; i < pivot; i++)
+ {
+ double x = double(i) / double(image_subpixel_scale);
+ double y = filter.calc_weight(x);
+ m_weight_array[pivot + i] =
+ m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
+ }
+ unsigned end = (diameter() << image_subpixel_shift) - 1;
+ m_weight_array[0] = m_weight_array[end];
+ if(normalization)
+ {
+ normalize();
+ }
+ }
+
+ image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
+
+ template<class FilterF> image_filter_lut(const FilterF& filter,
+ bool normalization=true)
+ {
+ calculate(filter, normalization);
+ }
+
+ double radius() const { return m_radius; }
+ unsigned diameter() const { return m_diameter; }
+ int start() const { return m_start; }
+ const int16* weight_array() const { return &m_weight_array[0]; }
+ void normalize();
+
+ private:
+ void realloc_lut(double radius);
+ image_filter_lut(const image_filter_lut&);
+ const image_filter_lut& operator = (const image_filter_lut&);
+
+ double m_radius;
+ unsigned m_diameter;
+ int m_start;
+ pod_array<int16> m_weight_array;
+ };
+
+
+
+ //--------------------------------------------------------image_filter
+ template<class FilterF> class image_filter : public image_filter_lut
+ {
+ public:
+ image_filter()
+ {
+ calculate(m_filter_function);
+ }
+ private:
+ FilterF m_filter_function;
+ };
+
+
+ //-----------------------------------------------image_filter_bilinear
+ struct image_filter_bilinear
+ {
+ static double radius() { return 1.0; }
+ static double calc_weight(double x)
+ {
+ return 1.0 - x;
+ }
+ };
+
+
+ //-----------------------------------------------image_filter_hanning
+ struct image_filter_hanning
+ {
+ static double radius() { return 1.0; }
+ static double calc_weight(double x)
+ {
+ return 0.5 + 0.5 * cos(pi * x);
+ }
+ };
+
+
+ //-----------------------------------------------image_filter_hamming
+ struct image_filter_hamming
+ {
+ static double radius() { return 1.0; }
+ static double calc_weight(double x)
+ {
+ return 0.54 + 0.46 * cos(pi * x);
+ }
+ };
+
+ //-----------------------------------------------image_filter_hermite
+ struct image_filter_hermite
+ {
+ static double radius() { return 1.0; }
+ static double calc_weight(double x)
+ {
+ return (2.0 * x - 3.0) * x * x + 1.0;
+ }
+ };
+
+ //------------------------------------------------image_filter_quadric
+ struct image_filter_quadric
+ {
+ static double radius() { return 1.5; }
+ static double calc_weight(double x)
+ {
+ double t;
+ if(x < 0.5) return 0.75 - x * x;
+ if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;}
+ return 0.0;
+ }
+ };
+
+ //------------------------------------------------image_filter_bicubic
+ class image_filter_bicubic
+ {
+ static double pow3(double x)
+ {
+ return (x <= 0.0) ? 0.0 : x * x * x;
+ }
+
+ public:
+ static double radius() { return 2.0; }
+ static double calc_weight(double x)
+ {
+ return
+ (1.0/6.0) *
+ (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
+ }
+ };
+
+ //-------------------------------------------------image_filter_kaiser
+ class image_filter_kaiser
+ {
+ double a;
+ double i0a;
+ double epsilon;
+
+ public:
+ image_filter_kaiser(double b = 6.33) :
+ a(b), epsilon(1e-12)
+ {
+ i0a = 1.0 / bessel_i0(b);
+ }
+
+ static double radius() { return 1.0; }
+ double calc_weight(double x) const
+ {
+ return bessel_i0(a * sqrt(1. - x * x)) * i0a;
+ }
+
+ private:
+ double bessel_i0(double x) const
+ {
+ int i;
+ double sum, y, t;
+
+ sum = 1.;
+ y = x * x / 4.;
+ t = y;
+
+ for(i = 2; t > epsilon; i++)
+ {
+ sum += t;
+ t *= (double)y / (i * i);
+ }
+ return sum;
+ }
+ };
+
+ //----------------------------------------------image_filter_catrom
+ struct image_filter_catrom
+ {
+ static double radius() { return 2.0; }
+ static double calc_weight(double x)
+ {
+ if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
+ if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
+ return 0.;
+ }
+ };
+
+ //---------------------------------------------image_filter_mitchell
+ class image_filter_mitchell
+ {
+ double p0, p2, p3;
+ double q0, q1, q2, q3;
+
+ public:
+ image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) :
+ p0((6.0 - 2.0 * b) / 6.0),
+ p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0),
+ p3((12.0 - 9.0 * b - 6.0 * c) / 6.0),
+ q0((8.0 * b + 24.0 * c) / 6.0),
+ q1((-12.0 * b - 48.0 * c) / 6.0),
+ q2((6.0 * b + 30.0 * c) / 6.0),
+ q3((-b - 6.0 * c) / 6.0)
+ {}
+
+ static double radius() { return 2.0; }
+ double calc_weight(double x) const
+ {
+ if(x < 1.0) return p0 + x * x * (p2 + x * p3);
+ if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3));
+ return 0.0;
+ }
+ };
+
+
+ //----------------------------------------------image_filter_spline16
+ struct image_filter_spline16
+ {
+ static double radius() { return 2.0; }
+ static double calc_weight(double x)
+ {
+ if(x < 1.0)
+ {
+ return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
+ }
+ return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
+ }
+ };
+
+
+ //---------------------------------------------image_filter_spline36
+ struct image_filter_spline36
+ {
+ static double radius() { return 3.0; }
+ static double calc_weight(double x)
+ {
+ if(x < 1.0)
+ {
+ return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
+ }
+ if(x < 2.0)
+ {
+ return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
+ }
+ return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2);
+ }
+ };
+
+
+ //----------------------------------------------image_filter_gaussian
+ struct image_filter_gaussian
+ {
+ static double radius() { return 2.0; }
+ static double calc_weight(double x)
+ {
+ return exp(-2.0 * x * x) * sqrt(2.0 / pi);
+ }
+ };
+
+
+ //------------------------------------------------image_filter_bessel
+ struct image_filter_bessel
+ {
+ static double radius() { return 3.2383; }
+ static double calc_weight(double x)
+ {
+ return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x);
+ }
+ };
+
+
+ //-------------------------------------------------image_filter_sinc
+ class image_filter_sinc
+ {
+ public:
+ image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
+ double radius() const { return m_radius; }
+ double calc_weight(double x) const
+ {
+ if(x == 0.0) return 1.0;
+ x *= pi;
+ return sin(x) / x;
+ }
+ private:
+ double m_radius;
+ };
+
+
+ //-----------------------------------------------image_filter_lanczos
+ class image_filter_lanczos
+ {
+ public:
+ image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
+ double radius() const { return m_radius; }
+ double calc_weight(double x) const
+ {
+ if(x == 0.0) return 1.0;
+ if(x > m_radius) return 0.0;
+ x *= pi;
+ double xr = x / m_radius;
+ return (sin(x) / x) * (sin(xr) / xr);
+ }
+ private:
+ double m_radius;
+ };
+
+
+ //----------------------------------------------image_filter_blackman
+ class image_filter_blackman
+ {
+ public:
+ image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
+ double radius() const { return m_radius; }
+ double calc_weight(double x) const
+ {
+ if(x == 0.0) return 1.0;
+ if(x > m_radius) return 0.0;
+ x *= pi;
+ double xr = x / m_radius;
+ return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr));
+ }
+ private:
+ double m_radius;
+ };
+
+ //------------------------------------------------image_filter_sinc36
+ class image_filter_sinc36 : public image_filter_sinc
+ { public: image_filter_sinc36() : image_filter_sinc(3.0){} };
+
+ //------------------------------------------------image_filter_sinc64
+ class image_filter_sinc64 : public image_filter_sinc
+ { public: image_filter_sinc64() : image_filter_sinc(4.0){} };
+
+ //-----------------------------------------------image_filter_sinc100
+ class image_filter_sinc100 : public image_filter_sinc
+ { public: image_filter_sinc100() : image_filter_sinc(5.0){} };
+
+ //-----------------------------------------------image_filter_sinc144
+ class image_filter_sinc144 : public image_filter_sinc
+ { public: image_filter_sinc144() : image_filter_sinc(6.0){} };
+
+ //-----------------------------------------------image_filter_sinc196
+ class image_filter_sinc196 : public image_filter_sinc
+ { public: image_filter_sinc196() : image_filter_sinc(7.0){} };
+
+ //-----------------------------------------------image_filter_sinc256
+ class image_filter_sinc256 : public image_filter_sinc
+ { public: image_filter_sinc256() : image_filter_sinc(8.0){} };
+
+ //---------------------------------------------image_filter_lanczos36
+ class image_filter_lanczos36 : public image_filter_lanczos
+ { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} };
+
+ //---------------------------------------------image_filter_lanczos64
+ class image_filter_lanczos64 : public image_filter_lanczos
+ { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} };
+
+ //--------------------------------------------image_filter_lanczos100
+ class image_filter_lanczos100 : public image_filter_lanczos
+ { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} };
+
+ //--------------------------------------------image_filter_lanczos144
+ class image_filter_lanczos144 : public image_filter_lanczos
+ { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} };
+
+ //--------------------------------------------image_filter_lanczos196
+ class image_filter_lanczos196 : public image_filter_lanczos
+ { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} };
+
+ //--------------------------------------------image_filter_lanczos256
+ class image_filter_lanczos256 : public image_filter_lanczos
+ { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} };
+
+ //--------------------------------------------image_filter_blackman36
+ class image_filter_blackman36 : public image_filter_blackman
+ { public: image_filter_blackman36() : image_filter_blackman(3.0){} };
+
+ //--------------------------------------------image_filter_blackman64
+ class image_filter_blackman64 : public image_filter_blackman
+ { public: image_filter_blackman64() : image_filter_blackman(4.0){} };
+
+ //-------------------------------------------image_filter_blackman100
+ class image_filter_blackman100 : public image_filter_blackman
+ { public: image_filter_blackman100() : image_filter_blackman(5.0){} };
+
+ //-------------------------------------------image_filter_blackman144
+ class image_filter_blackman144 : public image_filter_blackman
+ { public: image_filter_blackman144() : image_filter_blackman(6.0){} };
+
+ //-------------------------------------------image_filter_blackman196
+ class image_filter_blackman196 : public image_filter_blackman
+ { public: image_filter_blackman196() : image_filter_blackman(7.0){} };
+
+ //-------------------------------------------image_filter_blackman256
+ class image_filter_blackman256 : public image_filter_blackman
+ { public: image_filter_blackman256() : image_filter_blackman(8.0){} };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_line_aa_basics.h b/plugins/Clist_ng/AGG/include/agg_line_aa_basics.h new file mode 100644 index 0000000000..8c3d7ee200 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_line_aa_basics.h @@ -0,0 +1,199 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_LINE_AA_BASICS_INCLUDED
+#define AGG_LINE_AA_BASICS_INCLUDED
+
+#include <stdlib.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ // See Implementation agg_line_aa_basics.cpp
+
+ //-------------------------------------------------------------------------
+ enum line_subpixel_scale_e
+ {
+ line_subpixel_shift = 8, //----line_subpixel_shift
+ line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale
+ line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask
+ line_max_coord = (1 << 28) - 1, //----line_max_coord
+ line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length
+ };
+
+ //-------------------------------------------------------------------------
+ enum line_mr_subpixel_scale_e
+ {
+ line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
+ line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale
+ line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask
+ };
+
+ //------------------------------------------------------------------line_mr
+ AGG_INLINE int line_mr(int x)
+ {
+ return x >> (line_subpixel_shift - line_mr_subpixel_shift);
+ }
+
+ //-------------------------------------------------------------------line_hr
+ AGG_INLINE int line_hr(int x)
+ {
+ return x << (line_subpixel_shift - line_mr_subpixel_shift);
+ }
+
+ //---------------------------------------------------------------line_dbl_hr
+ AGG_INLINE int line_dbl_hr(int x)
+ {
+ return x << line_subpixel_shift;
+ }
+
+ //---------------------------------------------------------------line_coord
+ struct line_coord
+ {
+ AGG_INLINE static int conv(double x)
+ {
+ return iround(x * line_subpixel_scale);
+ }
+ };
+
+ //-----------------------------------------------------------line_coord_sat
+ struct line_coord_sat
+ {
+ AGG_INLINE static int conv(double x)
+ {
+ return saturation<line_max_coord>::iround(x * line_subpixel_scale);
+ }
+ };
+
+ //==========================================================line_parameters
+ struct line_parameters
+ {
+ //---------------------------------------------------------------------
+ line_parameters() {}
+ line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
+ x1(x1_), y1(y1_), x2(x2_), y2(y2_),
+ dx(abs(x2_ - x1_)),
+ dy(abs(y2_ - y1_)),
+ sx((x2_ > x1_) ? 1 : -1),
+ sy((y2_ > y1_) ? 1 : -1),
+ vertical(dy >= dx),
+ inc(vertical ? sy : sx),
+ len(len_),
+ octant((sy & 4) | (sx & 2) | int(vertical))
+ {
+ }
+
+ //---------------------------------------------------------------------
+ unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; }
+ unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; }
+
+ //---------------------------------------------------------------------
+ bool same_orthogonal_quadrant(const line_parameters& lp) const
+ {
+ return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
+ }
+
+ //---------------------------------------------------------------------
+ bool same_diagonal_quadrant(const line_parameters& lp) const
+ {
+ return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
+ }
+
+ //---------------------------------------------------------------------
+ void divide(line_parameters& lp1, line_parameters& lp2) const
+ {
+ int xmid = (x1 + x2) >> 1;
+ int ymid = (y1 + y2) >> 1;
+ int len2 = len >> 1;
+
+ lp1 = *this;
+ lp2 = *this;
+
+ lp1.x2 = xmid;
+ lp1.y2 = ymid;
+ lp1.len = len2;
+ lp1.dx = abs(lp1.x2 - lp1.x1);
+ lp1.dy = abs(lp1.y2 - lp1.y1);
+
+ lp2.x1 = xmid;
+ lp2.y1 = ymid;
+ lp2.len = len2;
+ lp2.dx = abs(lp2.x2 - lp2.x1);
+ lp2.dy = abs(lp2.y2 - lp2.y1);
+ }
+
+ //---------------------------------------------------------------------
+ int x1, y1, x2, y2, dx, dy, sx, sy;
+ bool vertical;
+ int inc;
+ int len;
+ int octant;
+
+ //---------------------------------------------------------------------
+ static const int8u s_orthogonal_quadrant[8];
+ static const int8u s_diagonal_quadrant[8];
+ };
+
+
+
+ // See Implementation agg_line_aa_basics.cpp
+
+ //----------------------------------------------------------------bisectrix
+ void bisectrix(const line_parameters& l1,
+ const line_parameters& l2,
+ int* x, int* y);
+
+
+ //-------------------------------------------fix_degenerate_bisectrix_start
+ void inline fix_degenerate_bisectrix_start(const line_parameters& lp,
+ int* x, int* y)
+ {
+ int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
+ double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
+ if(d < line_subpixel_scale/2)
+ {
+ *x = lp.x1 + (lp.y2 - lp.y1);
+ *y = lp.y1 - (lp.x2 - lp.x1);
+ }
+ }
+
+
+ //---------------------------------------------fix_degenerate_bisectrix_end
+ void inline fix_degenerate_bisectrix_end(const line_parameters& lp,
+ int* x, int* y)
+ {
+ int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
+ double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
+ if(d < line_subpixel_scale/2)
+ {
+ *x = lp.x2 + (lp.y2 - lp.y1);
+ *y = lp.y2 - (lp.x2 - lp.x1);
+ }
+ }
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_math.h b/plugins/Clist_ng/AGG/include/agg_math.h new file mode 100644 index 0000000000..62bc57c3c3 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_math.h @@ -0,0 +1,446 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
+// Contact: castor.vulgaris@gmail.com
+//----------------------------------------------------------------------------
+
+#ifndef AGG_MATH_INCLUDED
+#define AGG_MATH_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------vertex_dist_epsilon
+ // Coinciding points maximal distance (Epsilon)
+ const double vertex_dist_epsilon = 1e-14;
+
+ //-----------------------------------------------------intersection_epsilon
+ // See calc_intersection
+ const double intersection_epsilon = 1.0e-30;
+
+ //------------------------------------------------------------cross_product
+ AGG_INLINE double cross_product(double x1, double y1,
+ double x2, double y2,
+ double x, double y)
+ {
+ return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
+ }
+
+ //--------------------------------------------------------point_in_triangle
+ AGG_INLINE bool point_in_triangle(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x, double y)
+ {
+ bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
+ bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
+ bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
+ return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
+ }
+
+ //-----------------------------------------------------------calc_distance
+ AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
+ {
+ double dx = x2-x1;
+ double dy = y2-y1;
+ return sqrt(dx * dx + dy * dy);
+ }
+
+ //--------------------------------------------------------calc_sq_distance
+ AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
+ {
+ double dx = x2-x1;
+ double dy = y2-y1;
+ return dx * dx + dy * dy;
+ }
+
+ //------------------------------------------------calc_line_point_distance
+ AGG_INLINE double calc_line_point_distance(double x1, double y1,
+ double x2, double y2,
+ double x, double y)
+ {
+ double dx = x2-x1;
+ double dy = y2-y1;
+ double d = sqrt(dx * dx + dy * dy);
+ if(d < vertex_dist_epsilon)
+ {
+ return calc_distance(x1, y1, x, y);
+ }
+ return ((x - x2) * dy - (y - y2) * dx) / d;
+ }
+
+ //-------------------------------------------------------calc_line_point_u
+ AGG_INLINE double calc_segment_point_u(double x1, double y1,
+ double x2, double y2,
+ double x, double y)
+ {
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+
+ if(dx == 0 && dy == 0)
+ {
+ return 0;
+ }
+
+ double pdx = x - x1;
+ double pdy = y - y1;
+
+ return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
+ }
+
+ //---------------------------------------------calc_line_point_sq_distance
+ AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
+ double x2, double y2,
+ double x, double y,
+ double u)
+ {
+ if(u <= 0)
+ {
+ return calc_sq_distance(x, y, x1, y1);
+ }
+ else
+ if(u >= 1)
+ {
+ return calc_sq_distance(x, y, x2, y2);
+ }
+ return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
+ }
+
+ //---------------------------------------------calc_line_point_sq_distance
+ AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
+ double x2, double y2,
+ double x, double y)
+ {
+ return
+ calc_segment_point_sq_distance(
+ x1, y1, x2, y2, x, y,
+ calc_segment_point_u(x1, y1, x2, y2, x, y));
+ }
+
+ //-------------------------------------------------------calc_intersection
+ AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
+ double cx, double cy, double dx, double dy,
+ double* x, double* y)
+ {
+ double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
+ double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
+ if(fabs(den) < intersection_epsilon) return false;
+ double r = num / den;
+ *x = ax + r * (bx-ax);
+ *y = ay + r * (by-ay);
+ return true;
+ }
+
+ //-----------------------------------------------------intersection_exists
+ AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
+ double x3, double y3, double x4, double y4)
+ {
+ // It's less expensive but you can't control the
+ // boundary conditions: Less or LessEqual
+ double dx1 = x2 - x1;
+ double dy1 = y2 - y1;
+ double dx2 = x4 - x3;
+ double dy2 = y4 - y3;
+ return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) !=
+ ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
+ ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
+ ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
+
+ // It's is more expensive but more flexible
+ // in terms of boundary conditions.
+ //--------------------
+ //double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
+ //if(fabs(den) < intersection_epsilon) return false;
+ //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
+ //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
+ //double ua = nom1 / den;
+ //double ub = nom2 / den;
+ //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
+ }
+
+ //--------------------------------------------------------calc_orthogonal
+ AGG_INLINE void calc_orthogonal(double thickness,
+ double x1, double y1,
+ double x2, double y2,
+ double* x, double* y)
+ {
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+ double d = sqrt(dx*dx + dy*dy);
+ *x = thickness * dy / d;
+ *y = -thickness * dx / d;
+ }
+
+ //--------------------------------------------------------dilate_triangle
+ AGG_INLINE void dilate_triangle(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double *x, double* y,
+ double d)
+ {
+ double dx1=0.0;
+ double dy1=0.0;
+ double dx2=0.0;
+ double dy2=0.0;
+ double dx3=0.0;
+ double dy3=0.0;
+ double loc = cross_product(x1, y1, x2, y2, x3, y3);
+ if(fabs(loc) > intersection_epsilon)
+ {
+ if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0)
+ {
+ d = -d;
+ }
+ calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
+ calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
+ calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
+ }
+ *x++ = x1 + dx1; *y++ = y1 + dy1;
+ *x++ = x2 + dx1; *y++ = y2 + dy1;
+ *x++ = x2 + dx2; *y++ = y2 + dy2;
+ *x++ = x3 + dx2; *y++ = y3 + dy2;
+ *x++ = x3 + dx3; *y++ = y3 + dy3;
+ *x++ = x1 + dx3; *y++ = y1 + dy3;
+ }
+
+ //------------------------------------------------------calc_triangle_area
+ AGG_INLINE double calc_triangle_area(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
+ }
+
+ //-------------------------------------------------------calc_polygon_area
+ template<class Storage> double calc_polygon_area(const Storage& st)
+ {
+ unsigned i;
+ double sum = 0.0;
+ double x = st[0].x;
+ double y = st[0].y;
+ double xs = x;
+ double ys = y;
+
+ for(i = 1; i < st.size(); i++)
+ {
+ const typename Storage::value_type& v = st[i];
+ sum += x * v.y - y * v.x;
+ x = v.x;
+ y = v.y;
+ }
+ return (sum + x * ys - y * xs) * 0.5;
+ }
+
+ //------------------------------------------------------------------------
+ // Tables for fast sqrt
+ extern int16u g_sqrt_table[1024];
+ extern int8 g_elder_bit_table[256];
+
+
+ //---------------------------------------------------------------fast_sqrt
+ //Fast integer Sqrt - really fast: no cycles, divisions or multiplications
+ #if defined(_MSC_VER)
+ #pragma warning(push)
+ #pragma warning(disable : 4035) //Disable warning "no return value"
+ #endif
+ AGG_INLINE unsigned fast_sqrt(unsigned val)
+ {
+ #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
+ //For Ix86 family processors this assembler code is used.
+ //The key command here is bsr - determination the number of the most
+ //significant bit of the value. For other processors
+ //(and maybe compilers) the pure C "#else" section is used.
+ __asm
+ {
+ mov ebx, val
+ mov edx, 11
+ bsr ecx, ebx
+ sub ecx, 9
+ jle less_than_9_bits
+ shr ecx, 1
+ adc ecx, 0
+ sub edx, ecx
+ shl ecx, 1
+ shr ebx, cl
+ less_than_9_bits:
+ xor eax, eax
+ mov ax, g_sqrt_table[ebx*2]
+ mov ecx, edx
+ shr eax, cl
+ }
+ #else
+
+ //This code is actually pure C and portable to most
+ //arcitectures including 64bit ones.
+ unsigned t = val;
+ int bit=0;
+ unsigned shift = 11;
+
+ //The following piece of code is just an emulation of the
+ //Ix86 assembler command "bsr" (see above). However on old
+ //Intels (like Intel MMX 233MHz) this code is about twice
+ //faster (sic!) then just one "bsr". On PIII and PIV the
+ //bsr is optimized quite well.
+ bit = t >> 24;
+ if(bit)
+ {
+ bit = g_elder_bit_table[bit] + 24;
+ }
+ else
+ {
+ bit = (t >> 16) & 0xFF;
+ if(bit)
+ {
+ bit = g_elder_bit_table[bit] + 16;
+ }
+ else
+ {
+ bit = (t >> 8) & 0xFF;
+ if(bit)
+ {
+ bit = g_elder_bit_table[bit] + 8;
+ }
+ else
+ {
+ bit = g_elder_bit_table[t];
+ }
+ }
+ }
+
+ //This code calculates the sqrt.
+ bit -= 9;
+ if(bit > 0)
+ {
+ bit = (bit >> 1) + (bit & 1);
+ shift -= bit;
+ val >>= (bit << 1);
+ }
+ return g_sqrt_table[val] >> shift;
+ #endif
+ }
+ #if defined(_MSC_VER)
+ #pragma warning(pop)
+ #endif
+
+
+
+
+ //--------------------------------------------------------------------besj
+ // Function BESJ calculates Bessel function of first kind of order n
+ // Arguments:
+ // n - an integer (>=0), the order
+ // x - value at which the Bessel function is required
+ //--------------------
+ // C++ Mathematical Library
+ // Convereted from equivalent FORTRAN library
+ // Converetd by Gareth Walker for use by course 392 computational project
+ // All functions tested and yield the same results as the corresponding
+ // FORTRAN versions.
+ //
+ // If you have any problems using these functions please report them to
+ // M.Muldoon@UMIST.ac.uk
+ //
+ // Documentation available on the web
+ // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
+ // Version 1.0 8/98
+ // 29 October, 1999
+ //--------------------
+ // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
+ //------------------------------------------------------------------------
+ inline double besj(double x, int n)
+ {
+ if(n < 0)
+ {
+ return 0;
+ }
+ double d = 1E-6;
+ double b = 0;
+ if(fabs(x) <= d)
+ {
+ if(n != 0) return 0;
+ return 1;
+ }
+ double b1 = 0; // b1 is the value from the previous iteration
+ // Set up a starting order for recurrence
+ int m1 = (int)fabs(x) + 6;
+ if(fabs(x) > 5)
+ {
+ m1 = (int)(fabs(1.4 * x + 60 / x));
+ }
+ int m2 = (int)(n + 2 + fabs(x) / 4);
+ if (m1 > m2)
+ {
+ m2 = m1;
+ }
+
+ // Apply recurrence down from curent max order
+ for(;;)
+ {
+ double c3 = 0;
+ double c2 = 1E-30;
+ double c4 = 0;
+ int m8 = 1;
+ if (m2 / 2 * 2 == m2)
+ {
+ m8 = -1;
+ }
+ int imax = m2 - 2;
+ for (int i = 1; i <= imax; i++)
+ {
+ double c6 = 2 * (m2 - i) * c2 / x - c3;
+ c3 = c2;
+ c2 = c6;
+ if(m2 - i - 1 == n)
+ {
+ b = c6;
+ }
+ m8 = -1 * m8;
+ if (m8 > 0)
+ {
+ c4 = c4 + 2 * c6;
+ }
+ }
+ double c6 = 2 * c2 / x - c3;
+ if(n == 0)
+ {
+ b = c6;
+ }
+ c4 += c6;
+ b /= c4;
+ if(fabs(b - b1) < d)
+ {
+ return b;
+ }
+ b1 = b;
+ m2 += 3;
+ }
+ }
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_math_stroke.h b/plugins/Clist_ng/AGG/include/agg_math_stroke.h new file mode 100644 index 0000000000..11e66b12b7 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_math_stroke.h @@ -0,0 +1,531 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_STROKE_MATH_INCLUDED
+#define AGG_STROKE_MATH_INCLUDED
+
+#include "agg_math.h"
+#include "agg_vertex_sequence.h"
+
+namespace agg
+{
+ //-------------------------------------------------------------line_cap_e
+ enum line_cap_e
+ {
+ butt_cap,
+ square_cap,
+ round_cap
+ };
+
+ //------------------------------------------------------------line_join_e
+ enum line_join_e
+ {
+ miter_join = 0,
+ miter_join_revert = 1,
+ round_join = 2,
+ bevel_join = 3,
+ miter_join_round = 4
+ };
+
+
+ //-----------------------------------------------------------inner_join_e
+ enum inner_join_e
+ {
+ inner_bevel,
+ inner_miter,
+ inner_jag,
+ inner_round
+ };
+
+ //------------------------------------------------------------math_stroke
+ template<class VertexConsumer> class math_stroke
+ {
+ public:
+ typedef typename VertexConsumer::value_type coord_type;
+
+ math_stroke();
+
+ void line_cap(line_cap_e lc) { m_line_cap = lc; }
+ void line_join(line_join_e lj) { m_line_join = lj; }
+ void inner_join(inner_join_e ij) { m_inner_join = ij; }
+
+ line_cap_e line_cap() const { return m_line_cap; }
+ line_join_e line_join() const { return m_line_join; }
+ inner_join_e inner_join() const { return m_inner_join; }
+
+ void width(double w);
+ void miter_limit(double ml) { m_miter_limit = ml; }
+ void miter_limit_theta(double t);
+ void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
+ void approximation_scale(double as) { m_approx_scale = as; }
+
+ double width() const { return m_width * 2.0; }
+ double miter_limit() const { return m_miter_limit; }
+ double inner_miter_limit() const { return m_inner_miter_limit; }
+ double approximation_scale() const { return m_approx_scale; }
+
+ void calc_cap(VertexConsumer& vc,
+ const vertex_dist& v0,
+ const vertex_dist& v1,
+ double len);
+
+ void calc_join(VertexConsumer& vc,
+ const vertex_dist& v0,
+ const vertex_dist& v1,
+ const vertex_dist& v2,
+ double len1,
+ double len2);
+
+ private:
+ AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y)
+ {
+ vc.add(coord_type(x, y));
+ }
+
+ void calc_arc(VertexConsumer& vc,
+ double x, double y,
+ double dx1, double dy1,
+ double dx2, double dy2);
+
+ void calc_miter(VertexConsumer& vc,
+ const vertex_dist& v0,
+ const vertex_dist& v1,
+ const vertex_dist& v2,
+ double dx1, double dy1,
+ double dx2, double dy2,
+ line_join_e lj,
+ double mlimit,
+ double dbevel);
+
+ double m_width;
+ double m_width_abs;
+ double m_width_eps;
+ int m_width_sign;
+ double m_miter_limit;
+ double m_inner_miter_limit;
+ double m_approx_scale;
+ line_cap_e m_line_cap;
+ line_join_e m_line_join;
+ inner_join_e m_inner_join;
+ };
+
+ //-----------------------------------------------------------------------
+ template<class VC> math_stroke<VC>::math_stroke() :
+ m_width(0.5),
+ m_width_abs(0.5),
+ m_width_eps(0.5/1024.0),
+ m_width_sign(1),
+ m_miter_limit(4.0),
+ m_inner_miter_limit(1.01),
+ m_approx_scale(1.0),
+ m_line_cap(butt_cap),
+ m_line_join(miter_join),
+ m_inner_join(inner_miter)
+ {
+ }
+
+ //-----------------------------------------------------------------------
+ template<class VC> void math_stroke<VC>::width(double w)
+ {
+ m_width = w * 0.5;
+ if(m_width < 0)
+ {
+ m_width_abs = -m_width;
+ m_width_sign = -1;
+ }
+ else
+ {
+ m_width_abs = m_width;
+ m_width_sign = 1;
+ }
+ m_width_eps = m_width / 1024.0;
+ }
+
+ //-----------------------------------------------------------------------
+ template<class VC> void math_stroke<VC>::miter_limit_theta(double t)
+ {
+ m_miter_limit = 1.0 / sin(t * 0.5) ;
+ }
+
+ //-----------------------------------------------------------------------
+ template<class VC>
+ void math_stroke<VC>::calc_arc(VC& vc,
+ double x, double y,
+ double dx1, double dy1,
+ double dx2, double dy2)
+ {
+ double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign);
+ double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign);
+ double da = a1 - a2;
+ int i, n;
+
+ da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
+
+ add_vertex(vc, x + dx1, y + dy1);
+ if(m_width_sign > 0)
+ {
+ if(a1 > a2) a2 += 2 * pi;
+ n = int((a2 - a1) / da);
+ da = (a2 - a1) / (n + 1);
+ a1 += da;
+ for(i = 0; i < n; i++)
+ {
+ add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
+ a1 += da;
+ }
+ }
+ else
+ {
+ if(a1 < a2) a2 -= 2 * pi;
+ n = int((a1 - a2) / da);
+ da = (a1 - a2) / (n + 1);
+ a1 -= da;
+ for(i = 0; i < n; i++)
+ {
+ add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
+ a1 -= da;
+ }
+ }
+ add_vertex(vc, x + dx2, y + dy2);
+ }
+
+ //-----------------------------------------------------------------------
+ template<class VC>
+ void math_stroke<VC>::calc_miter(VC& vc,
+ const vertex_dist& v0,
+ const vertex_dist& v1,
+ const vertex_dist& v2,
+ double dx1, double dy1,
+ double dx2, double dy2,
+ line_join_e lj,
+ double mlimit,
+ double dbevel)
+ {
+ double xi = v1.x;
+ double yi = v1.y;
+ double di = 1;
+ double lim = m_width_abs * mlimit;
+ bool miter_limit_exceeded = true; // Assume the worst
+ bool intersection_failed = true; // Assume the worst
+
+ if(calc_intersection(v0.x + dx1, v0.y - dy1,
+ v1.x + dx1, v1.y - dy1,
+ v1.x + dx2, v1.y - dy2,
+ v2.x + dx2, v2.y - dy2,
+ &xi, &yi))
+ {
+ // Calculation of the intersection succeeded
+ //---------------------
+ di = calc_distance(v1.x, v1.y, xi, yi);
+ if(di <= lim)
+ {
+ // Inside the miter limit
+ //---------------------
+ add_vertex(vc, xi, yi);
+ miter_limit_exceeded = false;
+ }
+ intersection_failed = false;
+ }
+ else
+ {
+ // Calculation of the intersection failed, most probably
+ // the three points lie one straight line.
+ // First check if v0 and v2 lie on the opposite sides of vector:
+ // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
+ // to the line determined by vertices v0 and v1.
+ // This condition determines whether the next line segments continues
+ // the previous one or goes back.
+ //----------------
+ double x2 = v1.x + dx1;
+ double y2 = v1.y - dy1;
+ if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
+ (cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
+ {
+ // This case means that the next segment continues
+ // the previous one (straight line)
+ //-----------------
+ add_vertex(vc, v1.x + dx1, v1.y - dy1);
+ miter_limit_exceeded = false;
+ }
+ }
+
+ if(miter_limit_exceeded)
+ {
+ // Miter limit exceeded
+ //------------------------
+ switch(lj)
+ {
+ case miter_join_revert:
+ // For the compatibility with SVG, PDF, etc,
+ // we use a simple bevel join instead of
+ // "smart" bevel
+ //-------------------
+ add_vertex(vc, v1.x + dx1, v1.y - dy1);
+ add_vertex(vc, v1.x + dx2, v1.y - dy2);
+ break;
+
+ case miter_join_round:
+ calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
+ break;
+
+ default:
+ // If no miter-revert, calculate new dx1, dy1, dx2, dy2
+ //----------------
+ if(intersection_failed)
+ {
+ mlimit *= m_width_sign;
+ add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
+ v1.y - dy1 + dx1 * mlimit);
+ add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
+ v1.y - dy2 - dx2 * mlimit);
+ }
+ else
+ {
+ double x1 = v1.x + dx1;
+ double y1 = v1.y - dy1;
+ double x2 = v1.x + dx2;
+ double y2 = v1.y - dy2;
+ di = (lim - dbevel) / (di - dbevel);
+ add_vertex(vc, x1 + (xi - x1) * di,
+ y1 + (yi - y1) * di);
+ add_vertex(vc, x2 + (xi - x2) * di,
+ y2 + (yi - y2) * di);
+ }
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------stroke_calc_cap
+ template<class VC>
+ void math_stroke<VC>::calc_cap(VC& vc,
+ const vertex_dist& v0,
+ const vertex_dist& v1,
+ double len)
+ {
+ vc.remove_all();
+
+ double dx1 = (v1.y - v0.y) / len;
+ double dy1 = (v1.x - v0.x) / len;
+ double dx2 = 0;
+ double dy2 = 0;
+
+ dx1 *= m_width;
+ dy1 *= m_width;
+
+ if(m_line_cap != round_cap)
+ {
+ if(m_line_cap == square_cap)
+ {
+ dx2 = dy1 * m_width_sign;
+ dy2 = dx1 * m_width_sign;
+ }
+ add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
+ add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
+ }
+ else
+ {
+ double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
+ double a1;
+ int i;
+ int n = int(pi / da);
+
+ da = pi / (n + 1);
+ add_vertex(vc, v0.x - dx1, v0.y + dy1);
+ if(m_width_sign > 0)
+ {
+ a1 = atan2(dy1, -dx1);
+ a1 += da;
+ for(i = 0; i < n; i++)
+ {
+ add_vertex(vc, v0.x + cos(a1) * m_width,
+ v0.y + sin(a1) * m_width);
+ a1 += da;
+ }
+ }
+ else
+ {
+ a1 = atan2(-dy1, dx1);
+ a1 -= da;
+ for(i = 0; i < n; i++)
+ {
+ add_vertex(vc, v0.x + cos(a1) * m_width,
+ v0.y + sin(a1) * m_width);
+ a1 -= da;
+ }
+ }
+ add_vertex(vc, v0.x + dx1, v0.y - dy1);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ template<class VC>
+ void math_stroke<VC>::calc_join(VC& vc,
+ const vertex_dist& v0,
+ const vertex_dist& v1,
+ const vertex_dist& v2,
+ double len1,
+ double len2)
+ {
+ double dx1 = m_width * (v1.y - v0.y) / len1;
+ double dy1 = m_width * (v1.x - v0.x) / len1;
+ double dx2 = m_width * (v2.y - v1.y) / len2;
+ double dy2 = m_width * (v2.x - v1.x) / len2;
+
+ vc.remove_all();
+
+ double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
+ if(cp != 0 && (cp > 0) == (m_width > 0))
+ {
+ // Inner join
+ //---------------
+ double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
+ if(limit < m_inner_miter_limit)
+ {
+ limit = m_inner_miter_limit;
+ }
+
+ switch(m_inner_join)
+ {
+ default: // inner_bevel
+ add_vertex(vc, v1.x + dx1, v1.y - dy1);
+ add_vertex(vc, v1.x + dx2, v1.y - dy2);
+ break;
+
+ case inner_miter:
+ calc_miter(vc,
+ v0, v1, v2, dx1, dy1, dx2, dy2,
+ miter_join_revert,
+ limit, 0);
+ break;
+
+ case inner_jag:
+ case inner_round:
+ cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
+ if(cp < len1 * len1 && cp < len2 * len2)
+ {
+ calc_miter(vc,
+ v0, v1, v2, dx1, dy1, dx2, dy2,
+ miter_join_revert,
+ limit, 0);
+ }
+ else
+ {
+ if(m_inner_join == inner_jag)
+ {
+ add_vertex(vc, v1.x + dx1, v1.y - dy1);
+ add_vertex(vc, v1.x, v1.y );
+ add_vertex(vc, v1.x + dx2, v1.y - dy2);
+ }
+ else
+ {
+ add_vertex(vc, v1.x + dx1, v1.y - dy1);
+ add_vertex(vc, v1.x, v1.y );
+ calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
+ add_vertex(vc, v1.x, v1.y );
+ add_vertex(vc, v1.x + dx2, v1.y - dy2);
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ // Outer join
+ //---------------
+
+ // Calculate the distance between v1 and
+ // the central point of the bevel line segment
+ //---------------
+ double dx = (dx1 + dx2) / 2;
+ double dy = (dy1 + dy2) / 2;
+ double dbevel = sqrt(dx * dx + dy * dy);
+
+ if(m_line_join == round_join || m_line_join == bevel_join)
+ {
+ // This is an optimization that reduces the number of points
+ // in cases of almost collinear segments. If there's no
+ // visible difference between bevel and miter joins we'd rather
+ // use miter join because it adds only one point instead of two.
+ //
+ // Here we calculate the middle point between the bevel points
+ // and then, the distance between v1 and this middle point.
+ // At outer joins this distance always less than stroke width,
+ // because it's actually the height of an isosceles triangle of
+ // v1 and its two bevel points. If the difference between this
+ // width and this value is small (no visible bevel) we can
+ // add just one point.
+ //
+ // The constant in the expression makes the result approximately
+ // the same as in round joins and caps. You can safely comment
+ // out this entire "if".
+ //-------------------
+ if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
+ {
+ if(calc_intersection(v0.x + dx1, v0.y - dy1,
+ v1.x + dx1, v1.y - dy1,
+ v1.x + dx2, v1.y - dy2,
+ v2.x + dx2, v2.y - dy2,
+ &dx, &dy))
+ {
+ add_vertex(vc, dx, dy);
+ }
+ else
+ {
+ add_vertex(vc, v1.x + dx1, v1.y - dy1);
+ }
+ return;
+ }
+ }
+
+ switch(m_line_join)
+ {
+ case miter_join:
+ case miter_join_revert:
+ case miter_join_round:
+ calc_miter(vc,
+ v0, v1, v2, dx1, dy1, dx2, dy2,
+ m_line_join,
+ m_miter_limit,
+ dbevel);
+ break;
+
+ case round_join:
+ calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
+ break;
+
+ default: // Bevel join
+ add_vertex(vc, v1.x + dx1, v1.y - dy1);
+ add_vertex(vc, v1.x + dx2, v1.y - dy2);
+ break;
+ }
+ }
+ }
+
+
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_path_length.h b/plugins/Clist_ng/AGG/include/agg_path_length.h new file mode 100644 index 0000000000..487959e1f4 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_path_length.h @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PATH_LENGTH_INCLUDED
+#define AGG_PATH_LENGTH_INCLUDED
+
+#include "agg_math.h"
+
+namespace agg
+{
+ template<class VertexSource>
+ double path_length(VertexSource& vs, unsigned path_id = 0)
+ {
+ double len = 0.0;
+ double start_x = 0.0;
+ double start_y = 0.0;
+ double x1 = 0.0;
+ double y1 = 0.0;
+ double x2 = 0.0;
+ double y2 = 0.0;
+ bool first = true;
+
+ unsigned cmd;
+ vs.rewind(path_id);
+ while(!is_stop(cmd = vs.vertex(&x2, &y2)))
+ {
+ if(is_vertex(cmd))
+ {
+ if(first || is_move_to(cmd))
+ {
+ start_x = x2;
+ start_y = y2;
+ }
+ else
+ {
+ len += calc_distance(x1, y1, x2, y2);
+ }
+ x1 = x2;
+ y1 = y2;
+ first = false;
+ }
+ else
+ {
+ if(is_close(cmd) && !first)
+ {
+ len += calc_distance(x1, y1, start_x, start_y);
+ }
+ }
+ }
+ return len;
+ }
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_path_storage.h b/plugins/Clist_ng/AGG/include/agg_path_storage.h new file mode 100644 index 0000000000..e8cb7ab48b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_path_storage.h @@ -0,0 +1,1554 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PATH_STORAGE_INCLUDED
+#define AGG_PATH_STORAGE_INCLUDED
+
+#include <string.h>
+#include <math.h>
+#include "agg_math.h"
+#include "agg_array.h"
+#include "agg_bezier_arc.h"
+
+namespace agg
+{
+
+
+ //----------------------------------------------------vertex_block_storage
+ template<class T, unsigned BlockShift=8, unsigned BlockPool=256>
+ class vertex_block_storage
+ {
+ public:
+ // Allocation parameters
+ enum block_scale_e
+ {
+ block_shift = BlockShift,
+ block_size = 1 << block_shift,
+ block_mask = block_size - 1,
+ block_pool = BlockPool
+ };
+
+ typedef T value_type;
+ typedef vertex_block_storage<T, BlockShift, BlockPool> self_type;
+
+ ~vertex_block_storage();
+ vertex_block_storage();
+ vertex_block_storage(const self_type& v);
+ const self_type& operator = (const self_type& ps);
+
+ void remove_all();
+ void free_all();
+
+ void add_vertex(double x, double y, unsigned cmd);
+ void modify_vertex(unsigned idx, double x, double y);
+ void modify_vertex(unsigned idx, double x, double y, unsigned cmd);
+ void modify_command(unsigned idx, unsigned cmd);
+ void swap_vertices(unsigned v1, unsigned v2);
+
+ unsigned last_command() const;
+ unsigned last_vertex(double* x, double* y) const;
+ unsigned prev_vertex(double* x, double* y) const;
+
+ double last_x() const;
+ double last_y() const;
+
+ unsigned total_vertices() const;
+ unsigned vertex(unsigned idx, double* x, double* y) const;
+ unsigned command(unsigned idx) const;
+
+ private:
+ void allocate_block(unsigned nb);
+ int8u* storage_ptrs(T** xy_ptr);
+
+ private:
+ unsigned m_total_vertices;
+ unsigned m_total_blocks;
+ unsigned m_max_blocks;
+ T** m_coord_blocks;
+ int8u** m_cmd_blocks;
+ };
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ void vertex_block_storage<T,S,P>::free_all()
+ {
+ if(m_total_blocks)
+ {
+ T** coord_blk = m_coord_blocks + m_total_blocks - 1;
+ while(m_total_blocks--)
+ {
+ pod_allocator<T>::deallocate(
+ *coord_blk,
+ block_size * 2 +
+ block_size / (sizeof(T) / sizeof(unsigned char)));
+ --coord_blk;
+ }
+ pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
+ m_total_blocks = 0;
+ m_max_blocks = 0;
+ m_coord_blocks = 0;
+ m_cmd_blocks = 0;
+ m_total_vertices = 0;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ vertex_block_storage<T,S,P>::~vertex_block_storage()
+ {
+ free_all();
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ vertex_block_storage<T,S,P>::vertex_block_storage() :
+ m_total_vertices(0),
+ m_total_blocks(0),
+ m_max_blocks(0),
+ m_coord_blocks(0),
+ m_cmd_blocks(0)
+ {
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ vertex_block_storage<T,S,P>::vertex_block_storage(const vertex_block_storage<T,S,P>& v) :
+ m_total_vertices(0),
+ m_total_blocks(0),
+ m_max_blocks(0),
+ m_coord_blocks(0),
+ m_cmd_blocks(0)
+ {
+ *this = v;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ const vertex_block_storage<T,S,P>&
+ vertex_block_storage<T,S,P>::operator = (const vertex_block_storage<T,S,P>& v)
+ {
+ remove_all();
+ unsigned i;
+ for(i = 0; i < v.total_vertices(); i++)
+ {
+ double x, y;
+ unsigned cmd = v.vertex(i, &x, &y);
+ add_vertex(x, y, cmd);
+ }
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::remove_all()
+ {
+ m_total_vertices = 0;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::add_vertex(double x, double y,
+ unsigned cmd)
+ {
+ T* coord_ptr = 0;
+ *storage_ptrs(&coord_ptr) = (int8u)cmd;
+ coord_ptr[0] = T(x);
+ coord_ptr[1] = T(y);
+ m_total_vertices++;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx,
+ double x, double y)
+ {
+ T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1);
+ pv[0] = T(x);
+ pv[1] = T(y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx,
+ double x, double y,
+ unsigned cmd)
+ {
+ unsigned block = idx >> block_shift;
+ unsigned offset = idx & block_mask;
+ T* pv = m_coord_blocks[block] + (offset << 1);
+ pv[0] = T(x);
+ pv[1] = T(y);
+ m_cmd_blocks[block][offset] = (int8u)cmd;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::modify_command(unsigned idx,
+ unsigned cmd)
+ {
+ m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::swap_vertices(unsigned v1, unsigned v2)
+ {
+ unsigned b1 = v1 >> block_shift;
+ unsigned b2 = v2 >> block_shift;
+ unsigned o1 = v1 & block_mask;
+ unsigned o2 = v2 & block_mask;
+ T* pv1 = m_coord_blocks[b1] + (o1 << 1);
+ T* pv2 = m_coord_blocks[b2] + (o2 << 1);
+ T val;
+ val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val;
+ val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val;
+ int8u cmd = m_cmd_blocks[b1][o1];
+ m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2];
+ m_cmd_blocks[b2][o2] = cmd;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::last_command() const
+ {
+ if(m_total_vertices) return command(m_total_vertices - 1);
+ return path_cmd_stop;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::last_vertex(double* x, double* y) const
+ {
+ if(m_total_vertices) return vertex(m_total_vertices - 1, x, y);
+ return path_cmd_stop;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::prev_vertex(double* x, double* y) const
+ {
+ if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y);
+ return path_cmd_stop;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline double vertex_block_storage<T,S,P>::last_x() const
+ {
+ if(m_total_vertices)
+ {
+ unsigned idx = m_total_vertices - 1;
+ return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1];
+ }
+ return 0.0;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline double vertex_block_storage<T,S,P>::last_y() const
+ {
+ if(m_total_vertices)
+ {
+ unsigned idx = m_total_vertices - 1;
+ return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1];
+ }
+ return 0.0;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::total_vertices() const
+ {
+ return m_total_vertices;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::vertex(unsigned idx,
+ double* x, double* y) const
+ {
+ unsigned nb = idx >> block_shift;
+ const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1);
+ *x = pv[0];
+ *y = pv[1];
+ return m_cmd_blocks[nb][idx & block_mask];
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::command(unsigned idx) const
+ {
+ return m_cmd_blocks[idx >> block_shift][idx & block_mask];
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ void vertex_block_storage<T,S,P>::allocate_block(unsigned nb)
+ {
+ if(nb >= m_max_blocks)
+ {
+ T** new_coords =
+ pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2);
+
+ unsigned char** new_cmds =
+ (unsigned char**)(new_coords + m_max_blocks + block_pool);
+
+ if(m_coord_blocks)
+ {
+ memcpy(new_coords,
+ m_coord_blocks,
+ m_max_blocks * sizeof(T*));
+
+ memcpy(new_cmds,
+ m_cmd_blocks,
+ m_max_blocks * sizeof(unsigned char*));
+
+ pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
+ }
+ m_coord_blocks = new_coords;
+ m_cmd_blocks = new_cmds;
+ m_max_blocks += block_pool;
+ }
+ m_coord_blocks[nb] =
+ pod_allocator<T>::allocate(block_size * 2 +
+ block_size / (sizeof(T) / sizeof(unsigned char)));
+
+ m_cmd_blocks[nb] =
+ (unsigned char*)(m_coord_blocks[nb] + block_size * 2);
+
+ m_total_blocks++;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ int8u* vertex_block_storage<T,S,P>::storage_ptrs(T** xy_ptr)
+ {
+ unsigned nb = m_total_vertices >> block_shift;
+ if(nb >= m_total_blocks)
+ {
+ allocate_block(nb);
+ }
+ *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1);
+ return m_cmd_blocks[nb] + (m_total_vertices & block_mask);
+ }
+
+
+
+
+ //-----------------------------------------------------poly_plain_adaptor
+ template<class T> class poly_plain_adaptor
+ {
+ public:
+ typedef T value_type;
+
+ poly_plain_adaptor() :
+ m_data(0),
+ m_ptr(0),
+ m_end(0),
+ m_closed(false),
+ m_stop(false)
+ {}
+
+ poly_plain_adaptor(const T* data, unsigned num_points, bool closed) :
+ m_data(data),
+ m_ptr(data),
+ m_end(data + num_points * 2),
+ m_closed(closed),
+ m_stop(false)
+ {}
+
+ void init(const T* data, unsigned num_points, bool closed)
+ {
+ m_data = data;
+ m_ptr = data;
+ m_end = data + num_points * 2;
+ m_closed = closed;
+ m_stop = false;
+ }
+
+ void rewind(unsigned)
+ {
+ m_ptr = m_data;
+ m_stop = false;
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_ptr < m_end)
+ {
+ bool first = m_ptr == m_data;
+ *x = *m_ptr++;
+ *y = *m_ptr++;
+ return first ? path_cmd_move_to : path_cmd_line_to;
+ }
+ *x = *y = 0.0;
+ if(m_closed && !m_stop)
+ {
+ m_stop = true;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ return path_cmd_stop;
+ }
+
+ private:
+ const T* m_data;
+ const T* m_ptr;
+ const T* m_end;
+ bool m_closed;
+ bool m_stop;
+ };
+
+
+
+
+
+ //-------------------------------------------------poly_container_adaptor
+ template<class Container> class poly_container_adaptor
+ {
+ public:
+ typedef typename Container::value_type vertex_type;
+
+ poly_container_adaptor() :
+ m_container(0),
+ m_index(0),
+ m_closed(false),
+ m_stop(false)
+ {}
+
+ poly_container_adaptor(const Container& data, bool closed) :
+ m_container(&data),
+ m_index(0),
+ m_closed(closed),
+ m_stop(false)
+ {}
+
+ void init(const Container& data, bool closed)
+ {
+ m_container = &data;
+ m_index = 0;
+ m_closed = closed;
+ m_stop = false;
+ }
+
+ void rewind(unsigned)
+ {
+ m_index = 0;
+ m_stop = false;
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_index < m_container->size())
+ {
+ bool first = m_index == 0;
+ const vertex_type& v = (*m_container)[m_index++];
+ *x = v.x;
+ *y = v.y;
+ return first ? path_cmd_move_to : path_cmd_line_to;
+ }
+ *x = *y = 0.0;
+ if(m_closed && !m_stop)
+ {
+ m_stop = true;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ return path_cmd_stop;
+ }
+
+ private:
+ const Container* m_container;
+ unsigned m_index;
+ bool m_closed;
+ bool m_stop;
+ };
+
+
+
+ //-----------------------------------------poly_container_reverse_adaptor
+ template<class Container> class poly_container_reverse_adaptor
+ {
+ public:
+ typedef typename Container::value_type vertex_type;
+
+ poly_container_reverse_adaptor() :
+ m_container(0),
+ m_index(-1),
+ m_closed(false),
+ m_stop(false)
+ {}
+
+ poly_container_reverse_adaptor(const Container& data, bool closed) :
+ m_container(&data),
+ m_index(-1),
+ m_closed(closed),
+ m_stop(false)
+ {}
+
+ void init(const Container& data, bool closed)
+ {
+ m_container = &data;
+ m_index = m_container->size() - 1;
+ m_closed = closed;
+ m_stop = false;
+ }
+
+ void rewind(unsigned)
+ {
+ m_index = m_container->size() - 1;
+ m_stop = false;
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_index >= 0)
+ {
+ bool first = m_index == int(m_container->size() - 1);
+ const vertex_type& v = (*m_container)[m_index--];
+ *x = v.x;
+ *y = v.y;
+ return first ? path_cmd_move_to : path_cmd_line_to;
+ }
+ *x = *y = 0.0;
+ if(m_closed && !m_stop)
+ {
+ m_stop = true;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ return path_cmd_stop;
+ }
+
+ private:
+ const Container* m_container;
+ int m_index;
+ bool m_closed;
+ bool m_stop;
+ };
+
+
+
+
+
+ //--------------------------------------------------------line_adaptor
+ class line_adaptor
+ {
+ public:
+ typedef double value_type;
+
+ line_adaptor() : m_line(m_coord, 2, false) {}
+ line_adaptor(double x1, double y1, double x2, double y2) :
+ m_line(m_coord, 2, false)
+ {
+ m_coord[0] = x1;
+ m_coord[1] = y1;
+ m_coord[2] = x2;
+ m_coord[3] = y2;
+ }
+
+ void init(double x1, double y1, double x2, double y2)
+ {
+ m_coord[0] = x1;
+ m_coord[1] = y1;
+ m_coord[2] = x2;
+ m_coord[3] = y2;
+ m_line.rewind(0);
+ }
+
+ void rewind(unsigned)
+ {
+ m_line.rewind(0);
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ return m_line.vertex(x, y);
+ }
+
+ private:
+ double m_coord[4];
+ poly_plain_adaptor<double> m_line;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //---------------------------------------------------------------path_base
+ // A container to store vertices with their flags.
+ // A path consists of a number of contours separated with "move_to"
+ // commands. The path storage can keep and maintain more than one
+ // path.
+ // To navigate to the beginning of a particular path, use rewind(path_id);
+ // Where path_id is what start_new_path() returns. So, when you call
+ // start_new_path() you need to store its return value somewhere else
+ // to navigate to the path afterwards.
+ //
+ // See also: vertex_source concept
+ //------------------------------------------------------------------------
+ template<class VertexContainer> class path_base
+ {
+ public:
+ typedef VertexContainer container_type;
+ typedef path_base<VertexContainer> self_type;
+
+ //--------------------------------------------------------------------
+ path_base() : m_vertices(), m_iterator(0) {}
+ void remove_all() { m_vertices.remove_all(); m_iterator = 0; }
+ void free_all() { m_vertices.free_all(); m_iterator = 0; }
+
+ // Make path functions
+ //--------------------------------------------------------------------
+ unsigned start_new_path();
+
+ void move_to(double x, double y);
+ void move_rel(double dx, double dy);
+
+ void line_to(double x, double y);
+ void line_rel(double dx, double dy);
+
+ void hline_to(double x);
+ void hline_rel(double dx);
+
+ void vline_to(double y);
+ void vline_rel(double dy);
+
+ void arc_to(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double x, double y);
+
+ void arc_rel(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double dx, double dy);
+
+ void curve3(double x_ctrl, double y_ctrl,
+ double x_to, double y_to);
+
+ void curve3_rel(double dx_ctrl, double dy_ctrl,
+ double dx_to, double dy_to);
+
+ void curve3(double x_to, double y_to);
+
+ void curve3_rel(double dx_to, double dy_to);
+
+ void curve4(double x_ctrl1, double y_ctrl1,
+ double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to);
+
+ void curve4_rel(double dx_ctrl1, double dy_ctrl1,
+ double dx_ctrl2, double dy_ctrl2,
+ double dx_to, double dy_to);
+
+ void curve4(double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to);
+
+ void curve4_rel(double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to);
+
+
+ void end_poly(unsigned flags = path_flags_close);
+ void close_polygon(unsigned flags = path_flags_none);
+
+ // Accessors
+ //--------------------------------------------------------------------
+ const container_type& vertices() const { return m_vertices; }
+ container_type& vertices() { return m_vertices; }
+
+ unsigned total_vertices() const;
+
+ void rel_to_abs(double* x, double* y) const;
+
+ unsigned last_vertex(double* x, double* y) const;
+ unsigned prev_vertex(double* x, double* y) const;
+
+ double last_x() const;
+ double last_y() const;
+
+ unsigned vertex(unsigned idx, double* x, double* y) const;
+ unsigned command(unsigned idx) const;
+
+ void modify_vertex(unsigned idx, double x, double y);
+ void modify_vertex(unsigned idx, double x, double y, unsigned cmd);
+ void modify_command(unsigned idx, unsigned cmd);
+
+ // VertexSource interface
+ //--------------------------------------------------------------------
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ // Arrange the orientation of a polygon, all polygons in a path,
+ // or in all paths. After calling arrange_orientations() or
+ // arrange_orientations_all_paths(), all the polygons will have
+ // the same orientation, i.e. path_flags_cw or path_flags_ccw
+ //--------------------------------------------------------------------
+ unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation);
+ unsigned arrange_orientations(unsigned path_id, path_flags_e orientation);
+ void arrange_orientations_all_paths(path_flags_e orientation);
+ void invert_polygon(unsigned start);
+
+ // Flip all vertices horizontally or vertically,
+ // between x1 and x2, or between y1 and y2 respectively
+ //--------------------------------------------------------------------
+ void flip_x(double x1, double x2);
+ void flip_y(double y1, double y2);
+
+ // Concatenate path. The path is added as is.
+ //--------------------------------------------------------------------
+ template<class VertexSource>
+ void concat_path(VertexSource& vs, unsigned path_id = 0)
+ {
+ double x, y;
+ unsigned cmd;
+ vs.rewind(path_id);
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ m_vertices.add_vertex(x, y, cmd);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ // Join path. The path is joined with the existing one, that is,
+ // it behaves as if the pen of a plotter was always down (drawing)
+ template<class VertexSource>
+ void join_path(VertexSource& vs, unsigned path_id = 0)
+ {
+ double x, y;
+ unsigned cmd;
+ vs.rewind(path_id);
+ cmd = vs.vertex(&x, &y);
+ if(!is_stop(cmd))
+ {
+ if(is_vertex(cmd))
+ {
+ double x0, y0;
+ unsigned cmd0 = last_vertex(&x0, &y0);
+ if(is_vertex(cmd0))
+ {
+ if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon)
+ {
+ if(is_move_to(cmd)) cmd = path_cmd_line_to;
+ m_vertices.add_vertex(x, y, cmd);
+ }
+ }
+ else
+ {
+ if(is_stop(cmd0))
+ {
+ cmd = path_cmd_move_to;
+ }
+ else
+ {
+ if(is_move_to(cmd)) cmd = path_cmd_line_to;
+ }
+ m_vertices.add_vertex(x, y, cmd);
+ }
+ }
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ m_vertices.add_vertex(x, y, is_move_to(cmd) ?
+ unsigned(path_cmd_line_to) :
+ cmd);
+ }
+ }
+ }
+
+ // Concatenate polygon/polyline.
+ //--------------------------------------------------------------------
+ template<class T> void concat_poly(const T* data,
+ unsigned num_points,
+ bool closed)
+ {
+ poly_plain_adaptor<T> poly(data, num_points, closed);
+ concat_path(poly);
+ }
+
+ // Join polygon/polyline continuously.
+ //--------------------------------------------------------------------
+ template<class T> void join_poly(const T* data,
+ unsigned num_points,
+ bool closed)
+ {
+ poly_plain_adaptor<T> poly(data, num_points, closed);
+ join_path(poly);
+ }
+
+ //--------------------------------------------------------------------
+ void translate(double dx, double dy, unsigned path_id=0);
+ void translate_all_paths(double dx, double dy);
+
+ //--------------------------------------------------------------------
+ template<class Trans>
+ void transform(const Trans& trans, unsigned path_id=0)
+ {
+ unsigned num_ver = m_vertices.total_vertices();
+ for(; path_id < num_ver; path_id++)
+ {
+ double x, y;
+ unsigned cmd = m_vertices.vertex(path_id, &x, &y);
+ if(is_stop(cmd)) break;
+ if(is_vertex(cmd))
+ {
+ trans.transform(&x, &y);
+ m_vertices.modify_vertex(path_id, x, y);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class Trans>
+ void transform_all_paths(const Trans& trans)
+ {
+ unsigned idx;
+ unsigned num_ver = m_vertices.total_vertices();
+ for(idx = 0; idx < num_ver; idx++)
+ {
+ double x, y;
+ if(is_vertex(m_vertices.vertex(idx, &x, &y)))
+ {
+ trans.transform(&x, &y);
+ m_vertices.modify_vertex(idx, x, y);
+ }
+ }
+ }
+
+
+
+ private:
+ unsigned perceive_polygon_orientation(unsigned start, unsigned end);
+ void invert_polygon(unsigned start, unsigned end);
+
+ VertexContainer m_vertices;
+ unsigned m_iterator;
+ };
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::start_new_path()
+ {
+ if(!is_stop(m_vertices.last_command()))
+ {
+ m_vertices.add_vertex(0.0, 0.0, path_cmd_stop);
+ }
+ return m_vertices.total_vertices();
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::rel_to_abs(double* x, double* y) const
+ {
+ if(m_vertices.total_vertices())
+ {
+ double x2;
+ double y2;
+ if(is_vertex(m_vertices.last_vertex(&x2, &y2)))
+ {
+ *x += x2;
+ *y += y2;
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::move_to(double x, double y)
+ {
+ m_vertices.add_vertex(x, y, path_cmd_move_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::move_rel(double dx, double dy)
+ {
+ rel_to_abs(&dx, &dy);
+ m_vertices.add_vertex(dx, dy, path_cmd_move_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::line_to(double x, double y)
+ {
+ m_vertices.add_vertex(x, y, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::line_rel(double dx, double dy)
+ {
+ rel_to_abs(&dx, &dy);
+ m_vertices.add_vertex(dx, dy, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::hline_to(double x)
+ {
+ m_vertices.add_vertex(x, last_y(), path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::hline_rel(double dx)
+ {
+ double dy = 0;
+ rel_to_abs(&dx, &dy);
+ m_vertices.add_vertex(dx, dy, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::vline_to(double y)
+ {
+ m_vertices.add_vertex(last_x(), y, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::vline_rel(double dy)
+ {
+ double dx = 0;
+ rel_to_abs(&dx, &dy);
+ m_vertices.add_vertex(dx, dy, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::arc_to(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double x, double y)
+ {
+ if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command()))
+ {
+ const double epsilon = 1e-30;
+ double x0 = 0.0;
+ double y0 = 0.0;
+ m_vertices.last_vertex(&x0, &y0);
+
+ rx = fabs(rx);
+ ry = fabs(ry);
+
+ // Ensure radii are valid
+ //-------------------------
+ if(rx < epsilon || ry < epsilon)
+ {
+ line_to(x, y);
+ return;
+ }
+
+ if(calc_distance(x0, y0, x, y) < epsilon)
+ {
+ // If the endpoints (x, y) and (x0, y0) are identical, then this
+ // is equivalent to omitting the elliptical arc segment entirely.
+ return;
+ }
+ bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y);
+ if(a.radii_ok())
+ {
+ join_path(a);
+ }
+ else
+ {
+ line_to(x, y);
+ }
+ }
+ else
+ {
+ move_to(x, y);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::arc_rel(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double dx, double dy)
+ {
+ rel_to_abs(&dx, &dy);
+ arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3(double x_ctrl, double y_ctrl,
+ double x_to, double y_to)
+ {
+ m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3);
+ m_vertices.add_vertex(x_to, y_to, path_cmd_curve3);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3_rel(double dx_ctrl, double dy_ctrl,
+ double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_ctrl, &dy_ctrl);
+ rel_to_abs(&dx_to, &dy_to);
+ m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3);
+ m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3(double x_to, double y_to)
+ {
+ double x0;
+ double y0;
+ if(is_vertex(m_vertices.last_vertex(&x0, &y0)))
+ {
+ double x_ctrl;
+ double y_ctrl;
+ unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl);
+ if(is_curve(cmd))
+ {
+ x_ctrl = x0 + x0 - x_ctrl;
+ y_ctrl = y0 + y0 - y_ctrl;
+ }
+ else
+ {
+ x_ctrl = x0;
+ y_ctrl = y0;
+ }
+ curve3(x_ctrl, y_ctrl, x_to, y_to);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3_rel(double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_to, &dy_to);
+ curve3(dx_to, dy_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4(double x_ctrl1, double y_ctrl1,
+ double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to)
+ {
+ m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4);
+ m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4);
+ m_vertices.add_vertex(x_to, y_to, path_cmd_curve4);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4_rel(double dx_ctrl1, double dy_ctrl1,
+ double dx_ctrl2, double dy_ctrl2,
+ double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_ctrl1, &dy_ctrl1);
+ rel_to_abs(&dx_ctrl2, &dy_ctrl2);
+ rel_to_abs(&dx_to, &dy_to);
+ m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4);
+ m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4);
+ m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4(double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to)
+ {
+ double x0;
+ double y0;
+ if(is_vertex(last_vertex(&x0, &y0)))
+ {
+ double x_ctrl1;
+ double y_ctrl1;
+ unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1);
+ if(is_curve(cmd))
+ {
+ x_ctrl1 = x0 + x0 - x_ctrl1;
+ y_ctrl1 = y0 + y0 - y_ctrl1;
+ }
+ else
+ {
+ x_ctrl1 = x0;
+ y_ctrl1 = y0;
+ }
+ curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4_rel(double dx_ctrl2, double dy_ctrl2,
+ double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_ctrl2, &dy_ctrl2);
+ rel_to_abs(&dx_to, &dy_to);
+ curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::end_poly(unsigned flags)
+ {
+ if(is_vertex(m_vertices.last_command()))
+ {
+ m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::close_polygon(unsigned flags)
+ {
+ end_poly(path_flags_close | flags);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::total_vertices() const
+ {
+ return m_vertices.total_vertices();
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::last_vertex(double* x, double* y) const
+ {
+ return m_vertices.last_vertex(x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::prev_vertex(double* x, double* y) const
+ {
+ return m_vertices.prev_vertex(x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline double path_base<VC>::last_x() const
+ {
+ return m_vertices.last_x();
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline double path_base<VC>::last_y() const
+ {
+ return m_vertices.last_y();
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::vertex(unsigned idx, double* x, double* y) const
+ {
+ return m_vertices.vertex(idx, x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::command(unsigned idx) const
+ {
+ return m_vertices.command(idx);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::modify_vertex(unsigned idx, double x, double y)
+ {
+ m_vertices.modify_vertex(idx, x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::modify_vertex(unsigned idx, double x, double y, unsigned cmd)
+ {
+ m_vertices.modify_vertex(idx, x, y, cmd);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::modify_command(unsigned idx, unsigned cmd)
+ {
+ m_vertices.modify_command(idx, cmd);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::rewind(unsigned path_id)
+ {
+ m_iterator = path_id;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::vertex(double* x, double* y)
+ {
+ if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop;
+ return m_vertices.vertex(m_iterator++, x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::perceive_polygon_orientation(unsigned start,
+ unsigned end)
+ {
+ // Calculate signed area (double area to be exact)
+ //---------------------
+ unsigned np = end - start;
+ double area = 0.0;
+ unsigned i;
+ for(i = 0; i < np; i++)
+ {
+ double x1, y1, x2, y2;
+ m_vertices.vertex(start + i, &x1, &y1);
+ m_vertices.vertex(start + (i + 1) % np, &x2, &y2);
+ area += x1 * y2 - y1 * x2;
+ }
+ return (area < 0.0) ? path_flags_cw : path_flags_ccw;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::invert_polygon(unsigned start, unsigned end)
+ {
+ unsigned i;
+ unsigned tmp_cmd = m_vertices.command(start);
+
+ --end; // Make "end" inclusive
+
+ // Shift all commands to one position
+ for(i = start; i < end; i++)
+ {
+ m_vertices.modify_command(i, m_vertices.command(i + 1));
+ }
+
+ // Assign starting command to the ending command
+ m_vertices.modify_command(end, tmp_cmd);
+
+ // Reverse the polygon
+ while(end > start)
+ {
+ m_vertices.swap_vertices(start++, end--);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::invert_polygon(unsigned start)
+ {
+ // Skip all non-vertices at the beginning
+ while(start < m_vertices.total_vertices() &&
+ !is_vertex(m_vertices.command(start))) ++start;
+
+ // Skip all insignificant move_to
+ while(start+1 < m_vertices.total_vertices() &&
+ is_move_to(m_vertices.command(start)) &&
+ is_move_to(m_vertices.command(start+1))) ++start;
+
+ // Find the last vertex
+ unsigned end = start + 1;
+ while(end < m_vertices.total_vertices() &&
+ !is_next_poly(m_vertices.command(end))) ++end;
+
+ invert_polygon(start, end);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::arrange_polygon_orientation(unsigned start,
+ path_flags_e orientation)
+ {
+ if(orientation == path_flags_none) return start;
+
+ // Skip all non-vertices at the beginning
+ while(start < m_vertices.total_vertices() &&
+ !is_vertex(m_vertices.command(start))) ++start;
+
+ // Skip all insignificant move_to
+ while(start+1 < m_vertices.total_vertices() &&
+ is_move_to(m_vertices.command(start)) &&
+ is_move_to(m_vertices.command(start+1))) ++start;
+
+ // Find the last vertex
+ unsigned end = start + 1;
+ while(end < m_vertices.total_vertices() &&
+ !is_next_poly(m_vertices.command(end))) ++end;
+
+ if(end - start > 2)
+ {
+ if(perceive_polygon_orientation(start, end) != unsigned(orientation))
+ {
+ // Invert polygon, set orientation flag, and skip all end_poly
+ invert_polygon(start, end);
+ unsigned cmd;
+ while(end < m_vertices.total_vertices() &&
+ is_end_poly(cmd = m_vertices.command(end)))
+ {
+ m_vertices.modify_command(end++, set_orientation(cmd, orientation));
+ }
+ }
+ }
+ return end;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::arrange_orientations(unsigned start,
+ path_flags_e orientation)
+ {
+ if(orientation != path_flags_none)
+ {
+ while(start < m_vertices.total_vertices())
+ {
+ start = arrange_polygon_orientation(start, orientation);
+ if(is_stop(m_vertices.command(start)))
+ {
+ ++start;
+ break;
+ }
+ }
+ }
+ return start;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation)
+ {
+ if(orientation != path_flags_none)
+ {
+ unsigned start = 0;
+ while(start < m_vertices.total_vertices())
+ {
+ start = arrange_orientations(start, orientation);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::flip_x(double x1, double x2)
+ {
+ unsigned i;
+ double x, y;
+ for(i = 0; i < m_vertices.total_vertices(); i++)
+ {
+ unsigned cmd = m_vertices.vertex(i, &x, &y);
+ if(is_vertex(cmd))
+ {
+ m_vertices.modify_vertex(i, x2 - x + x1, y);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::flip_y(double y1, double y2)
+ {
+ unsigned i;
+ double x, y;
+ for(i = 0; i < m_vertices.total_vertices(); i++)
+ {
+ unsigned cmd = m_vertices.vertex(i, &x, &y);
+ if(is_vertex(cmd))
+ {
+ m_vertices.modify_vertex(i, x, y2 - y + y1);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::translate(double dx, double dy, unsigned path_id)
+ {
+ unsigned num_ver = m_vertices.total_vertices();
+ for(; path_id < num_ver; path_id++)
+ {
+ double x, y;
+ unsigned cmd = m_vertices.vertex(path_id, &x, &y);
+ if(is_stop(cmd)) break;
+ if(is_vertex(cmd))
+ {
+ x += dx;
+ y += dy;
+ m_vertices.modify_vertex(path_id, x, y);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::translate_all_paths(double dx, double dy)
+ {
+ unsigned idx;
+ unsigned num_ver = m_vertices.total_vertices();
+ for(idx = 0; idx < num_ver; idx++)
+ {
+ double x, y;
+ if(is_vertex(m_vertices.vertex(idx, &x, &y)))
+ {
+ x += dx;
+ y += dy;
+ m_vertices.modify_vertex(idx, x, y);
+ }
+ }
+ }
+
+ //-----------------------------------------------------vertex_stl_storage
+ template<class Container> class vertex_stl_storage
+ {
+ public:
+ typedef typename Container::value_type vertex_type;
+ typedef typename vertex_type::value_type value_type;
+
+ void remove_all() { m_vertices.clear(); }
+ void free_all() { m_vertices.clear(); }
+
+ void add_vertex(double x, double y, unsigned cmd)
+ {
+ m_vertices.push_back(vertex_type(value_type(x),
+ value_type(y),
+ int8u(cmd)));
+ }
+
+ void modify_vertex(unsigned idx, double x, double y)
+ {
+ vertex_type& v = m_vertices[idx];
+ v.x = value_type(x);
+ v.y = value_type(y);
+ }
+
+ void modify_vertex(unsigned idx, double x, double y, unsigned cmd)
+ {
+ vertex_type& v = m_vertices[idx];
+ v.x = value_type(x);
+ v.y = value_type(y);
+ v.cmd = int8u(cmd);
+ }
+
+ void modify_command(unsigned idx, unsigned cmd)
+ {
+ m_vertices[idx].cmd = int8u(cmd);
+ }
+
+ void swap_vertices(unsigned v1, unsigned v2)
+ {
+ vertex_type t = m_vertices[v1];
+ m_vertices[v1] = m_vertices[v2];
+ m_vertices[v2] = t;
+ }
+
+ unsigned last_command() const
+ {
+ return m_vertices.size() ?
+ m_vertices[m_vertices.size() - 1].cmd :
+ path_cmd_stop;
+ }
+
+ unsigned last_vertex(double* x, double* y) const
+ {
+ if(m_vertices.size() == 0)
+ {
+ *x = *y = 0.0;
+ return path_cmd_stop;
+ }
+ return vertex(m_vertices.size() - 1, x, y);
+ }
+
+ unsigned prev_vertex(double* x, double* y) const
+ {
+ if(m_vertices.size() < 2)
+ {
+ *x = *y = 0.0;
+ return path_cmd_stop;
+ }
+ return vertex(m_vertices.size() - 2, x, y);
+ }
+
+ double last_x() const
+ {
+ return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0;
+ }
+
+ double last_y() const
+ {
+ return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0;
+ }
+
+ unsigned total_vertices() const
+ {
+ return m_vertices.size();
+ }
+
+ unsigned vertex(unsigned idx, double* x, double* y) const
+ {
+ const vertex_type& v = m_vertices[idx];
+ *x = v.x;
+ *y = v.y;
+ return v.cmd;
+ }
+
+ unsigned command(unsigned idx) const
+ {
+ return m_vertices[idx].cmd;
+ }
+
+ private:
+ Container m_vertices;
+ };
+
+ //-----------------------------------------------------------path_storage
+ typedef path_base<vertex_block_storage<double> > path_storage;
+
+ // Example of declarations path_storage with pod_bvector as a container
+ //-----------------------------------------------------------------------
+ //typedef path_base<vertex_stl_storage<pod_bvector<vertex_d> > > path_storage;
+
+}
+
+
+
+// Example of declarations path_storage with std::vector as a container
+//---------------------------------------------------------------------------
+//#include <vector>
+//namespace agg
+//{
+// typedef path_base<vertex_stl_storage<std::vector<vertex_d> > > stl_path_storage;
+//}
+
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_path_storage_integer.h b/plugins/Clist_ng/AGG/include/agg_path_storage_integer.h new file mode 100644 index 0000000000..301e5f8af3 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_path_storage_integer.h @@ -0,0 +1,304 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
+#define AGG_PATH_STORAGE_INTEGER_INCLUDED
+
+#include <string.h>
+#include "agg_array.h"
+
+namespace agg
+{
+ //---------------------------------------------------------vertex_integer
+ template<class T, unsigned CoordShift=6> struct vertex_integer
+ {
+ enum path_cmd
+ {
+ cmd_move_to = 0,
+ cmd_line_to = 1,
+ cmd_curve3 = 2,
+ cmd_curve4 = 3
+ };
+
+ enum coord_scale_e
+ {
+ coord_shift = CoordShift,
+ coord_scale = 1 << coord_shift
+ };
+
+ T x,y;
+ vertex_integer() {}
+ vertex_integer(T x_, T y_, unsigned flag) :
+ x(((x_ << 1) & ~1) | (flag & 1)),
+ y(((y_ << 1) & ~1) | (flag >> 1)) {}
+
+ unsigned vertex(double* x_, double* y_,
+ double dx=0, double dy=0,
+ double scale=1.0) const
+ {
+ *x_ = dx + (double(x >> 1) / coord_scale) * scale;
+ *y_ = dy + (double(y >> 1) / coord_scale) * scale;
+ switch(((y & 1) << 1) | (x & 1))
+ {
+ case cmd_move_to: return path_cmd_move_to;
+ case cmd_line_to: return path_cmd_line_to;
+ case cmd_curve3: return path_cmd_curve3;
+ case cmd_curve4: return path_cmd_curve4;
+ }
+ return path_cmd_stop;
+ }
+ };
+
+
+ //---------------------------------------------------path_storage_integer
+ template<class T, unsigned CoordShift=6> class path_storage_integer
+ {
+ public:
+ typedef T value_type;
+ typedef vertex_integer<T, CoordShift> vertex_integer_type;
+
+ //--------------------------------------------------------------------
+ path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
+
+ //--------------------------------------------------------------------
+ void remove_all() { m_storage.remove_all(); }
+
+ //--------------------------------------------------------------------
+ void move_to(T x, T y)
+ {
+ m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
+ }
+
+ //--------------------------------------------------------------------
+ void line_to(T x, T y)
+ {
+ m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to));
+ }
+
+ //--------------------------------------------------------------------
+ void curve3(T x_ctrl, T y_ctrl,
+ T x_to, T y_to)
+ {
+ m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3));
+ m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3));
+ }
+
+ //--------------------------------------------------------------------
+ void curve4(T x_ctrl1, T y_ctrl1,
+ T x_ctrl2, T y_ctrl2,
+ T x_to, T y_to)
+ {
+ m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4));
+ m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4));
+ m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4));
+ }
+
+ //--------------------------------------------------------------------
+ void close_polygon() {}
+
+ //--------------------------------------------------------------------
+ unsigned size() const { return m_storage.size(); }
+ unsigned vertex(unsigned idx, double* x, double* y) const
+ {
+ return m_storage[idx].vertex(x, y);
+ }
+
+ //--------------------------------------------------------------------
+ unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
+ void serialize(int8u* ptr) const
+ {
+ unsigned i;
+ for(i = 0; i < m_storage.size(); i++)
+ {
+ memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
+ ptr += sizeof(vertex_integer_type);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void rewind(unsigned)
+ {
+ m_vertex_idx = 0;
+ m_closed = true;
+ }
+
+ //--------------------------------------------------------------------
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
+ {
+ *x = 0;
+ *y = 0;
+ return path_cmd_stop;
+ }
+ if(m_vertex_idx == m_storage.size())
+ {
+ *x = 0;
+ *y = 0;
+ ++m_vertex_idx;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ unsigned cmd = m_storage[m_vertex_idx].vertex(x, y);
+ if(is_move_to(cmd) && !m_closed)
+ {
+ *x = 0;
+ *y = 0;
+ m_closed = true;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ m_closed = false;
+ ++m_vertex_idx;
+ return cmd;
+ }
+
+ //--------------------------------------------------------------------
+ rect_d bounding_rect() const
+ {
+ rect_d bounds(1e100, 1e100, -1e100, -1e100);
+ if(m_storage.size() == 0)
+ {
+ bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
+ }
+ else
+ {
+ unsigned i;
+ for(i = 0; i < m_storage.size(); i++)
+ {
+ double x, y;
+ m_storage[i].vertex(&x, &y);
+ if(x < bounds.x1) bounds.x1 = x;
+ if(y < bounds.y1) bounds.y1 = y;
+ if(x > bounds.x2) bounds.x2 = x;
+ if(y > bounds.y2) bounds.y2 = y;
+ }
+ }
+ return bounds;
+ }
+
+ private:
+ pod_bvector<vertex_integer_type, 6> m_storage;
+ unsigned m_vertex_idx;
+ bool m_closed;
+ };
+
+
+
+
+ //-----------------------------------------serialized_integer_path_adaptor
+ template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
+ {
+ public:
+ typedef vertex_integer<T, CoordShift> vertex_integer_type;
+
+ //--------------------------------------------------------------------
+ serialized_integer_path_adaptor() :
+ m_data(0),
+ m_end(0),
+ m_ptr(0),
+ m_dx(0.0),
+ m_dy(0.0),
+ m_scale(1.0),
+ m_vertices(0)
+ {}
+
+ //--------------------------------------------------------------------
+ serialized_integer_path_adaptor(const int8u* data, unsigned size,
+ double dx, double dy) :
+ m_data(data),
+ m_end(data + size),
+ m_ptr(data),
+ m_dx(dx),
+ m_dy(dy),
+ m_vertices(0)
+ {}
+
+ //--------------------------------------------------------------------
+ void init(const int8u* data, unsigned size,
+ double dx, double dy, double scale=1.0)
+ {
+ m_data = data;
+ m_end = data + size;
+ m_ptr = data;
+ m_dx = dx;
+ m_dy = dy;
+ m_scale = scale;
+ m_vertices = 0;
+ }
+
+
+ //--------------------------------------------------------------------
+ void rewind(unsigned)
+ {
+ m_ptr = m_data;
+ m_vertices = 0;
+ }
+
+ //--------------------------------------------------------------------
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_data == 0 || m_ptr > m_end)
+ {
+ *x = 0;
+ *y = 0;
+ return path_cmd_stop;
+ }
+
+ if(m_ptr == m_end)
+ {
+ *x = 0;
+ *y = 0;
+ m_ptr += sizeof(vertex_integer_type);
+ return path_cmd_end_poly | path_flags_close;
+ }
+
+ vertex_integer_type v;
+ memcpy(&v, m_ptr, sizeof(vertex_integer_type));
+ unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
+ if(is_move_to(cmd) && m_vertices > 2)
+ {
+ *x = 0;
+ *y = 0;
+ m_vertices = 0;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ ++m_vertices;
+ m_ptr += sizeof(vertex_integer_type);
+ return cmd;
+ }
+
+ private:
+ const int8u* m_data;
+ const int8u* m_end;
+ const int8u* m_ptr;
+ double m_dx;
+ double m_dy;
+ double m_scale;
+ unsigned m_vertices;
+ };
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_pattern_filters_rgba.h b/plugins/Clist_ng/AGG/include/agg_pattern_filters_rgba.h new file mode 100644 index 0000000000..a58cb66f57 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_pattern_filters_rgba.h @@ -0,0 +1,132 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED
+#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_line_aa_basics.h"
+#include "agg_color_rgba.h"
+
+
+namespace agg
+{
+
+ //=======================================================pattern_filter_nn
+ template<class ColorT> struct pattern_filter_nn
+ {
+ typedef ColorT color_type;
+ static unsigned dilation() { return 0; }
+
+ static void AGG_INLINE pixel_low_res(color_type const* const* buf,
+ color_type* p, int x, int y)
+ {
+ *p = buf[y][x];
+ }
+
+ static void AGG_INLINE pixel_high_res(color_type const* const* buf,
+ color_type* p, int x, int y)
+ {
+ *p = buf[y >> line_subpixel_shift]
+ [x >> line_subpixel_shift];
+ }
+ };
+
+ typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
+ typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
+
+
+ //===========================================pattern_filter_bilinear_rgba
+ template<class ColorT> struct pattern_filter_bilinear_rgba
+ {
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+
+
+ static unsigned dilation() { return 1; }
+
+ static AGG_INLINE void pixel_low_res(color_type const* const* buf,
+ color_type* p, int x, int y)
+ {
+ *p = buf[y][x];
+ }
+
+ static AGG_INLINE void pixel_high_res(color_type const* const* buf,
+ color_type* p, int x, int y)
+ {
+ calc_type r, g, b, a;
+ r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2;
+
+ calc_type weight;
+ int x_lr = x >> line_subpixel_shift;
+ int y_lr = y >> line_subpixel_shift;
+
+ x &= line_subpixel_mask;
+ y &= line_subpixel_mask;
+ const color_type* ptr = buf[y_lr] + x_lr;
+
+ weight = (line_subpixel_scale - x) *
+ (line_subpixel_scale - y);
+ r += weight * ptr->r;
+ g += weight * ptr->g;
+ b += weight * ptr->b;
+ a += weight * ptr->a;
+
+ ++ptr;
+
+ weight = x * (line_subpixel_scale - y);
+ r += weight * ptr->r;
+ g += weight * ptr->g;
+ b += weight * ptr->b;
+ a += weight * ptr->a;
+
+ ptr = buf[y_lr + 1] + x_lr;
+
+ weight = (line_subpixel_scale - x) * y;
+ r += weight * ptr->r;
+ g += weight * ptr->g;
+ b += weight * ptr->b;
+ a += weight * ptr->a;
+
+ ++ptr;
+
+ weight = x * y;
+ r += weight * ptr->r;
+ g += weight * ptr->g;
+ b += weight * ptr->b;
+ a += weight * ptr->a;
+
+ p->r = (value_type)(r >> line_subpixel_shift * 2);
+ p->g = (value_type)(g >> line_subpixel_shift * 2);
+ p->b = (value_type)(b >> line_subpixel_shift * 2);
+ p->a = (value_type)(a >> line_subpixel_shift * 2);
+ }
+ };
+
+ typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
+ typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_pixfmt_amask_adaptor.h b/plugins/Clist_ng/AGG/include/agg_pixfmt_amask_adaptor.h new file mode 100644 index 0000000000..66d7bb1b3d --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_pixfmt_amask_adaptor.h @@ -0,0 +1,249 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
+#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
+
+
+#include <string.h>
+#include "agg_array.h"
+#include "agg_rendering_buffer.h"
+
+
+namespace agg
+{
+ //==================================================pixfmt_amask_adaptor
+ template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
+ {
+ public:
+ typedef PixFmt pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::row_data row_data;
+ typedef AlphaMask amask_type;
+ typedef typename amask_type::cover_type cover_type;
+
+ private:
+ enum span_extra_tail_e { span_extra_tail = 256 };
+
+ void realloc_span(unsigned len)
+ {
+ if(len > m_span.size())
+ {
+ m_span.resize(len + span_extra_tail);
+ }
+ }
+
+ void init_span(unsigned len)
+ {
+ realloc_span(len);
+ memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
+ }
+
+ void init_span(unsigned len, const cover_type* covers)
+ {
+ realloc_span(len);
+ memcpy(&m_span[0], covers, len * sizeof(cover_type));
+ }
+
+
+ public:
+ pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
+ m_pixf(&pixf), m_mask(&mask), m_span()
+ {}
+
+ void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
+ void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
+
+ //--------------------------------------------------------------------
+ template<class PixFmt2>
+ bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
+ {
+ return m_pixf->attach(pixf, x1, y1, x2, y2);
+ }
+
+ //--------------------------------------------------------------------
+ unsigned width() const { return m_pixf->width(); }
+ unsigned height() const { return m_pixf->height(); }
+
+ //--------------------------------------------------------------------
+ color_type pixel(int x, int y)
+ {
+ return m_pixf->pixel(x, y);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_pixel(int x, int y, const color_type& c)
+ {
+ m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
+ }
+
+ //--------------------------------------------------------------------
+ void blend_pixel(int x, int y, const color_type& c, cover_type cover)
+ {
+ m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
+ }
+
+ //--------------------------------------------------------------------
+ void copy_hline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ realloc_span(len);
+ m_mask->fill_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ cover_type cover)
+ {
+ init_span(len);
+ m_mask->combine_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_vline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ realloc_span(len);
+ m_mask->fill_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ cover_type cover)
+ {
+ init_span(len);
+ m_mask->combine_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_from(const rendering_buffer& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len)
+ {
+ m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const cover_type* covers)
+ {
+ init_span(len, covers);
+ m_mask->combine_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const cover_type* covers)
+ {
+ init_span(len, covers);
+ m_mask->combine_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
+ {
+ realloc_span(len);
+ m_mask->fill_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
+ {
+ realloc_span(len);
+ m_mask->fill_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const cover_type* covers,
+ cover_type cover = cover_full)
+ {
+ if(covers)
+ {
+ init_span(len, covers);
+ m_mask->combine_hspan(x, y, &m_span[0], len);
+ }
+ else
+ {
+ realloc_span(len);
+ m_mask->fill_hspan(x, y, &m_span[0], len);
+ }
+ m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const cover_type* covers,
+ cover_type cover = cover_full)
+ {
+ if(covers)
+ {
+ init_span(len, covers);
+ m_mask->combine_vspan(x, y, &m_span[0], len);
+ }
+ else
+ {
+ realloc_span(len);
+ m_mask->fill_vspan(x, y, &m_span[0], len);
+ }
+ m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
+ }
+
+ private:
+ pixfmt_type* m_pixf;
+ const amask_type* m_mask;
+ pod_array<cover_type> m_span;
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_pixfmt_gray.h b/plugins/Clist_ng/AGG/include/agg_pixfmt_gray.h new file mode 100644 index 0000000000..5870b9523e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_pixfmt_gray.h @@ -0,0 +1,679 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PIXFMT_GRAY_INCLUDED
+#define AGG_PIXFMT_GRAY_INCLUDED
+
+#include <string.h>
+#include "agg_basics.h"
+#include "agg_color_gray.h"
+#include "agg_rendering_buffer.h"
+
+namespace agg
+{
+
+ //============================================================blender_gray
+ template<class ColorT> struct blender_gray
+ {
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e { base_shift = color_type::base_shift };
+
+ static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
+ unsigned alpha, unsigned cover=0)
+ {
+ *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
+ }
+ };
+
+
+ //======================================================blender_gray_pre
+ template<class ColorT> struct blender_gray_pre
+ {
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e { base_shift = color_type::base_shift };
+
+ static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
+ unsigned alpha, unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ cover = (cover + 1) << (base_shift - 8);
+ *p = (value_type)((*p * alpha + cv * cover) >> base_shift);
+ }
+
+ static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
+ unsigned alpha)
+ {
+ *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv);
+ }
+ };
+
+
+
+ //=====================================================apply_gamma_dir_gray
+ template<class ColorT, class GammaLut> class apply_gamma_dir_gray
+ {
+ public:
+ typedef typename ColorT::value_type value_type;
+
+ apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {}
+
+ AGG_INLINE void operator () (value_type* p)
+ {
+ *p = m_gamma.dir(*p);
+ }
+
+ private:
+ const GammaLut& m_gamma;
+ };
+
+
+
+ //=====================================================apply_gamma_inv_gray
+ template<class ColorT, class GammaLut> class apply_gamma_inv_gray
+ {
+ public:
+ typedef typename ColorT::value_type value_type;
+
+ apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {}
+
+ AGG_INLINE void operator () (value_type* p)
+ {
+ *p = m_gamma.inv(*p);
+ }
+
+ private:
+ const GammaLut& m_gamma;
+ };
+
+
+
+ //=================================================pixfmt_alpha_blend_gray
+ template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0>
+ class pixfmt_alpha_blend_gray
+ {
+ public:
+ typedef RenBuf rbuf_type;
+ typedef typename rbuf_type::row_data row_data;
+ typedef Blender blender_type;
+ typedef typename blender_type::color_type color_type;
+ typedef int order_type; // A fake one
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_scale = color_type::base_scale,
+ base_mask = color_type::base_mask,
+ pix_width = sizeof(value_type),
+ pix_step = Step,
+ pix_offset = Offset
+ };
+
+ private:
+ //--------------------------------------------------------------------
+ static AGG_INLINE void copy_or_blend_pix(value_type* p,
+ const color_type& c,
+ unsigned cover)
+ {
+ if (c.a)
+ {
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ *p = c.v;
+ }
+ else
+ {
+ Blender::blend_pix(p, c.v, alpha, cover);
+ }
+ }
+ }
+
+
+ static AGG_INLINE void copy_or_blend_pix(value_type* p,
+ const color_type& c)
+ {
+ if (c.a)
+ {
+ if(c.a == base_mask)
+ {
+ *p = c.v;
+ }
+ else
+ {
+ Blender::blend_pix(p, c.v, c.a);
+ }
+ }
+ }
+
+
+ public:
+ //--------------------------------------------------------------------
+ explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
+ m_rbuf(&rb)
+ {}
+ void attach(rbuf_type& rb) { m_rbuf = &rb; }
+ //--------------------------------------------------------------------
+
+ template<class PixFmt>
+ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
+ {
+ rect_i r(x1, y1, x2, y2);
+ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
+ {
+ int stride = pixf.stride();
+ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
+ (r.x2 - r.x1) + 1,
+ (r.y2 - r.y1) + 1,
+ stride);
+ return true;
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned width() const { return m_rbuf->width(); }
+ AGG_INLINE unsigned height() const { return m_rbuf->height(); }
+ AGG_INLINE int stride() const { return m_rbuf->stride(); }
+
+ //--------------------------------------------------------------------
+ int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
+ const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
+ row_data row(int y) const { return m_rbuf->row(y); }
+
+ const int8u* pix_ptr(int x, int y) const
+ {
+ return m_rbuf->row_ptr(y) + x * Step + Offset;
+ }
+
+ int8u* pix_ptr(int x, int y)
+ {
+ return m_rbuf->row_ptr(y) + x * Step + Offset;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE static void make_pix(int8u* p, const color_type& c)
+ {
+ *(value_type*)p = c.v;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE color_type pixel(int x, int y) const
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
+ return color_type(*p);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
+ {
+ *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
+ {
+ copy_or_blend_pix((value_type*)
+ m_rbuf->row_ptr(x, y, 1) + x * Step + Offset,
+ c,
+ cover);
+ }
+
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_hline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+
+ do
+ {
+ *p = c.v;
+ p += Step;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_vline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ do
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+ *p = c.v;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ do
+ {
+ *p = c.v;
+ p += Step;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ Blender::blend_pix(p, c.v, alpha, cover);
+ p += Step;
+ }
+ while(--len);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ value_type* p;
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+ *p = c.v;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+ Blender::blend_pix(p, c.v, alpha, cover);
+ }
+ while(--len);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ if (c.a)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+
+ do
+ {
+ calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ *p = c.v;
+ }
+ else
+ {
+ Blender::blend_pix(p, c.v, alpha, *covers);
+ }
+ p += Step;
+ ++covers;
+ }
+ while(--len);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ if (c.a)
+ {
+ do
+ {
+ calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
+
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+ if(alpha == base_mask)
+ {
+ *p = c.v;
+ }
+ else
+ {
+ Blender::blend_pix(p, c.v, alpha, *covers);
+ }
+ ++covers;
+ }
+ while(--len);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+
+ do
+ {
+ *p = colors->v;
+ p += Step;
+ ++colors;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ do
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+ *p = colors->v;
+ ++colors;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+
+ if(covers)
+ {
+ do
+ {
+ copy_or_blend_pix(p, *colors++, *covers++);
+ p += Step;
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ if(colors->a == base_mask)
+ {
+ *p = colors->v;
+ }
+ else
+ {
+ copy_or_blend_pix(p, *colors);
+ }
+ p += Step;
+ ++colors;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ copy_or_blend_pix(p, *colors++, cover);
+ p += Step;
+ }
+ while(--len);
+ }
+ }
+ }
+
+
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ value_type* p;
+ if(covers)
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+ copy_or_blend_pix(p, *colors++, *covers++);
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+ if(colors->a == base_mask)
+ {
+ *p = colors->v;
+ }
+ else
+ {
+ copy_or_blend_pix(p, *colors);
+ }
+ ++colors;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+ copy_or_blend_pix(p, *colors++, cover);
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class Function> void for_each_pixel(Function f)
+ {
+ unsigned y;
+ for(y = 0; y < height(); ++y)
+ {
+ row_data r = m_rbuf->row(y);
+ if(r.ptr)
+ {
+ unsigned len = r.x2 - r.x1 + 1;
+
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset;
+
+ do
+ {
+ f(p);
+ p += Step;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf2>
+ void copy_from(const RenBuf2& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len)
+ {
+ const int8u* p = from.row_ptr(ysrc);
+ if(p)
+ {
+ memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
+ p + xsrc * pix_width,
+ len * pix_width);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_color(const SrcPixelFormatRenderer& from,
+ const color_type& color,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
+ do
+ {
+ copy_or_blend_pix(pdst,
+ color,
+ (*psrc * cover + base_mask) >> base_shift);
+ ++psrc;
+ ++pdst;
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_lut(const SrcPixelFormatRenderer& from,
+ const color_type* color_lut,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
+ do
+ {
+ copy_or_blend_pix(pdst, color_lut[*psrc], cover);
+ ++psrc;
+ ++pdst;
+ }
+ while(--len);
+ }
+ }
+
+ private:
+ rbuf_type* m_rbuf;
+ };
+
+ typedef blender_gray<gray8> blender_gray8;
+ typedef blender_gray_pre<gray8> blender_gray8_pre;
+ typedef blender_gray<gray16> blender_gray16;
+ typedef blender_gray_pre<gray16> blender_gray16_pre;
+
+ typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8
+ typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre
+ typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16
+ typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_pixfmt_rgb.h b/plugins/Clist_ng/AGG/include/agg_pixfmt_rgb.h new file mode 100644 index 0000000000..7f0ed184f7 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_pixfmt_rgb.h @@ -0,0 +1,869 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PIXFMT_RGB_INCLUDED
+#define AGG_PIXFMT_RGB_INCLUDED
+
+#include <string.h>
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+#include "agg_rendering_buffer.h"
+
+namespace agg
+{
+
+ //=====================================================apply_gamma_dir_rgb
+ template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
+ {
+ public:
+ typedef typename ColorT::value_type value_type;
+
+ apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
+
+ AGG_INLINE void operator () (value_type* p)
+ {
+ p[Order::R] = m_gamma.dir(p[Order::R]);
+ p[Order::G] = m_gamma.dir(p[Order::G]);
+ p[Order::B] = m_gamma.dir(p[Order::B]);
+ }
+
+ private:
+ const GammaLut& m_gamma;
+ };
+
+
+
+ //=====================================================apply_gamma_inv_rgb
+ template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
+ {
+ public:
+ typedef typename ColorT::value_type value_type;
+
+ apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
+
+ AGG_INLINE void operator () (value_type* p)
+ {
+ p[Order::R] = m_gamma.inv(p[Order::R]);
+ p[Order::G] = m_gamma.inv(p[Order::G]);
+ p[Order::B] = m_gamma.inv(p[Order::B]);
+ }
+
+ private:
+ const GammaLut& m_gamma;
+ };
+
+
+ //=========================================================blender_rgb
+ template<class ColorT, class Order> struct blender_rgb
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e { base_shift = color_type::base_shift };
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover=0)
+ {
+ p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift);
+ p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift);
+ p[Order::B] += (value_type)(((cb - p[Order::B]) * alpha) >> base_shift);
+ }
+ };
+
+
+ //======================================================blender_rgb_pre
+ template<class ColorT, class Order> struct blender_rgb_pre
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e { base_shift = color_type::base_shift };
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ cover = (cover + 1) << (base_shift - 8);
+ p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
+ p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
+ p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha)
+ {
+ alpha = color_type::base_mask - alpha;
+ p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
+ p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
+ p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
+ }
+
+ };
+
+
+
+ //===================================================blender_rgb_gamma
+ template<class ColorT, class Order, class Gamma> class blender_rgb_gamma
+ {
+ public:
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef Gamma gamma_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e { base_shift = color_type::base_shift };
+
+ //--------------------------------------------------------------------
+ blender_rgb_gamma() : m_gamma(0) {}
+ void gamma(const gamma_type& g) { m_gamma = &g; }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover=0)
+ {
+ calc_type r = m_gamma->dir(p[Order::R]);
+ calc_type g = m_gamma->dir(p[Order::G]);
+ calc_type b = m_gamma->dir(p[Order::B]);
+ p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r);
+ p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g);
+ p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b);
+ }
+
+ private:
+ const gamma_type* m_gamma;
+ };
+
+
+
+
+ //==================================================pixfmt_alpha_blend_rgb
+ template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb
+ {
+ public:
+ typedef RenBuf rbuf_type;
+ typedef Blender blender_type;
+ typedef typename rbuf_type::row_data row_data;
+ typedef typename blender_type::color_type color_type;
+ typedef typename blender_type::order_type order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_scale = color_type::base_scale,
+ base_mask = color_type::base_mask,
+ pix_width = sizeof(value_type) * 3
+ };
+
+ private:
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_or_blend_pix(value_type* p,
+ const color_type& c,
+ unsigned cover)
+ {
+ if (c.a)
+ {
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ }
+ else
+ {
+ m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_or_blend_pix(value_type* p,
+ const color_type& c)
+ {
+ if (c.a)
+ {
+ if(c.a == base_mask)
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ }
+ else
+ {
+ m_blender.blend_pix(p, c.r, c.g, c.b, c.a);
+ }
+ }
+ }
+
+
+ public:
+ //--------------------------------------------------------------------
+ explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
+ m_rbuf(&rb)
+ {}
+ void attach(rbuf_type& rb) { m_rbuf = &rb; }
+
+ //--------------------------------------------------------------------
+ template<class PixFmt>
+ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
+ {
+ rect_i r(x1, y1, x2, y2);
+ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
+ {
+ int stride = pixf.stride();
+ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
+ (r.x2 - r.x1) + 1,
+ (r.y2 - r.y1) + 1,
+ stride);
+ return true;
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ Blender& blender() { return m_blender; }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned width() const { return m_rbuf->width(); }
+ AGG_INLINE unsigned height() const { return m_rbuf->height(); }
+ AGG_INLINE int stride() const { return m_rbuf->stride(); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
+ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
+ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* pix_ptr(int x, int y)
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+ AGG_INLINE const int8u* pix_ptr(int x, int y) const
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE static void make_pix(int8u* p, const color_type& c)
+ {
+ ((value_type*)p)[order_type::R] = c.r;
+ ((value_type*)p)[order_type::G] = c.g;
+ ((value_type*)p)[order_type::B] = c.b;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE color_type pixel(int x, int y) const
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x;
+ return color_type(p[order_type::R],
+ p[order_type::G],
+ p[order_type::B]);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x;
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
+ {
+ copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover);
+ }
+
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_hline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + x + x + x;
+ do
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ p += 3;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_vline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ do
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x + x + x;
+
+ calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ do
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ p += 3;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ p += 3;
+ }
+ while(--len);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ value_type* p;
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+
+ m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ }
+ while(--len);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ if (c.a)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x + x + x;
+
+ do
+ {
+ calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ }
+ else
+ {
+ m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
+ }
+ p += 3;
+ ++covers;
+ }
+ while(--len);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ if (c.a)
+ {
+ do
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+
+ calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ }
+ else
+ {
+ m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
+ }
+ ++covers;
+ }
+ while(--len);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x + x + x;
+
+ do
+ {
+ p[order_type::R] = colors->r;
+ p[order_type::G] = colors->g;
+ p[order_type::B] = colors->b;
+ ++colors;
+ p += 3;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ do
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+ p[order_type::R] = colors->r;
+ p[order_type::G] = colors->g;
+ p[order_type::B] = colors->b;
+ ++colors;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(x, y, len) + x + x + x;
+
+ if(covers)
+ {
+ do
+ {
+ copy_or_blend_pix(p, *colors++, *covers++);
+ p += 3;
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ copy_or_blend_pix(p, *colors++);
+ p += 3;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ copy_or_blend_pix(p, *colors++, cover);
+ p += 3;
+ }
+ while(--len);
+ }
+ }
+ }
+
+
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ value_type* p;
+ if(covers)
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+
+ copy_or_blend_pix(p, *colors++, *covers++);
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+
+ copy_or_blend_pix(p, *colors++);
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ p = (value_type*)
+ m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+
+ copy_or_blend_pix(p, *colors++, cover);
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class Function> void for_each_pixel(Function f)
+ {
+ unsigned y;
+ for(y = 0; y < height(); ++y)
+ {
+ row_data r = m_rbuf->row(y);
+ if(r.ptr)
+ {
+ unsigned len = r.x2 - r.x1 + 1;
+ value_type* p = (value_type*)
+ m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3;
+ do
+ {
+ f(p);
+ p += 3;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf2>
+ void copy_from(const RenBuf2& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len)
+ {
+ const int8u* p = from.row_ptr(ysrc);
+ if(p)
+ {
+ memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
+ p + xsrc * pix_width,
+ len * pix_width);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from(const SrcPixelFormatRenderer& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::order_type src_order;
+
+ const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ psrc += xsrc * 4;
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
+
+ if(cover == 255)
+ {
+ do
+ {
+ value_type alpha = psrc[src_order::A];
+ if(alpha)
+ {
+ if(alpha == base_mask)
+ {
+ pdst[order_type::R] = psrc[src_order::R];
+ pdst[order_type::G] = psrc[src_order::G];
+ pdst[order_type::B] = psrc[src_order::B];
+ }
+ else
+ {
+ m_blender.blend_pix(pdst,
+ psrc[src_order::R],
+ psrc[src_order::G],
+ psrc[src_order::B],
+ alpha);
+ }
+ }
+ psrc += 4;
+ pdst += 3;
+ }
+ while(--len);
+ }
+ else
+ {
+ color_type color;
+ do
+ {
+ color.r = psrc[src_order::R];
+ color.g = psrc[src_order::G];
+ color.b = psrc[src_order::B];
+ color.a = psrc[src_order::A];
+ copy_or_blend_pix(pdst, color, cover);
+ psrc += 4;
+ pdst += 3;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_color(const SrcPixelFormatRenderer& from,
+ const color_type& color,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
+ do
+ {
+ copy_or_blend_pix(pdst,
+ color,
+ (*psrc * cover + base_mask) >> base_shift);
+ ++psrc;
+ pdst += 3;
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_lut(const SrcPixelFormatRenderer& from,
+ const color_type* color_lut,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
+
+ if(cover == 255)
+ {
+ do
+ {
+ const color_type& color = color_lut[*psrc];
+ m_blender.blend_pix(pdst,
+ color.r, color.g, color.b, color.a);
+ ++psrc;
+ pdst += 3;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ copy_or_blend_pix(pdst, color_lut[*psrc], cover);
+ ++psrc;
+ pdst += 3;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ private:
+ rbuf_type* m_rbuf;
+ Blender m_blender;
+ };
+
+ typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //----pixfmt_rgb24
+ typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24; //----pixfmt_bgr24
+ typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48; //----pixfmt_rgb48
+ typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48; //----pixfmt_bgr48
+
+ typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
+ typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
+ typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre
+ typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre
+
+ //-----------------------------------------------------pixfmt_rgb24_gamma
+ template<class Gamma> class pixfmt_rgb24_gamma :
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>
+ {
+ public:
+ pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+ //-----------------------------------------------------pixfmt_bgr24_gamma
+ template<class Gamma> class pixfmt_bgr24_gamma :
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>
+ {
+ public:
+ pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+ //-----------------------------------------------------pixfmt_rgb48_gamma
+ template<class Gamma> class pixfmt_rgb48_gamma :
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>
+ {
+ public:
+ pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+ //-----------------------------------------------------pixfmt_bgr48_gamma
+ template<class Gamma> class pixfmt_bgr48_gamma :
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>
+ {
+ public:
+ pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_pixfmt_rgb_packed.h b/plugins/Clist_ng/AGG/include/agg_pixfmt_rgb_packed.h new file mode 100644 index 0000000000..28bb79d4f7 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_pixfmt_rgb_packed.h @@ -0,0 +1,1318 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PIXFMT_RGB_PACKED_INCLUDED
+#define AGG_PIXFMT_RGB_PACKED_INCLUDED
+
+#include <string.h>
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+#include "agg_rendering_buffer.h"
+
+namespace agg
+{
+ //=========================================================blender_rgb555
+ struct blender_rgb555
+ {
+ typedef rgba8 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int16u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 7) & 0xF8;
+ calc_type g = (rgb >> 2) & 0xF8;
+ calc_type b = (rgb << 3) & 0xF8;
+ *p = (pixel_type)
+ (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) |
+ ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) |
+ (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xF8) << 7) |
+ ((g & 0xF8) << 2) |
+ (b >> 3) | 0x8000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 7) & 0xF8,
+ (p >> 2) & 0xF8,
+ (p << 3) & 0xF8);
+ }
+ };
+
+
+ //=====================================================blender_rgb555_pre
+ struct blender_rgb555_pre
+ {
+ typedef rgba8 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int16u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 7) & 0xF8;
+ calc_type g = (rgb >> 2) & 0xF8;
+ calc_type b = (rgb << 3) & 0xF8;
+ *p = (pixel_type)
+ ((((r * alpha + cr * cover) >> 1) & 0x7C00) |
+ (((g * alpha + cg * cover) >> 6) & 0x03E0) |
+ ((b * alpha + cb * cover) >> 11) | 0x8000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xF8) << 7) |
+ ((g & 0xF8) << 2) |
+ (b >> 3) | 0x8000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 7) & 0xF8,
+ (p >> 2) & 0xF8,
+ (p << 3) & 0xF8);
+ }
+ };
+
+
+
+
+ //=====================================================blender_rgb555_gamma
+ template<class Gamma> class blender_rgb555_gamma
+ {
+ public:
+ typedef rgba8 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int16u pixel_type;
+ typedef Gamma gamma_type;
+
+ blender_rgb555_gamma() : m_gamma(0) {}
+ void gamma(const gamma_type& g) { m_gamma = &g; }
+
+ AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = m_gamma->dir((rgb >> 7) & 0xF8);
+ calc_type g = m_gamma->dir((rgb >> 2) & 0xF8);
+ calc_type b = m_gamma->dir((rgb << 3) & 0xF8);
+ *p = (pixel_type)
+ (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) |
+ ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) |
+ (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xF8) << 7) |
+ ((g & 0xF8) << 2) |
+ (b >> 3) | 0x8000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 7) & 0xF8,
+ (p >> 2) & 0xF8,
+ (p << 3) & 0xF8);
+ }
+
+ private:
+ const Gamma* m_gamma;
+ };
+
+
+
+
+
+ //=========================================================blender_rgb565
+ struct blender_rgb565
+ {
+ typedef rgba8 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int16u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 8) & 0xF8;
+ calc_type g = (rgb >> 3) & 0xFC;
+ calc_type b = (rgb << 3) & 0xF8;
+ *p = (pixel_type)
+ (((((cr - r) * alpha + (r << 8)) ) & 0xF800) |
+ ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) |
+ (((cb - b) * alpha + (b << 8)) >> 11));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 8) & 0xF8,
+ (p >> 3) & 0xFC,
+ (p << 3) & 0xF8);
+ }
+ };
+
+
+
+ //=====================================================blender_rgb565_pre
+ struct blender_rgb565_pre
+ {
+ typedef rgba8 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int16u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 8) & 0xF8;
+ calc_type g = (rgb >> 3) & 0xFC;
+ calc_type b = (rgb << 3) & 0xF8;
+ *p = (pixel_type)
+ ((((r * alpha + cr * cover) ) & 0xF800) |
+ (((g * alpha + cg * cover) >> 5 ) & 0x07E0) |
+ ((b * alpha + cb * cover) >> 11));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 8) & 0xF8,
+ (p >> 3) & 0xFC,
+ (p << 3) & 0xF8);
+ }
+ };
+
+
+
+ //=====================================================blender_rgb565_gamma
+ template<class Gamma> class blender_rgb565_gamma
+ {
+ public:
+ typedef rgba8 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int16u pixel_type;
+ typedef Gamma gamma_type;
+
+ blender_rgb565_gamma() : m_gamma(0) {}
+ void gamma(const gamma_type& g) { m_gamma = &g; }
+
+ AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = m_gamma->dir((rgb >> 8) & 0xF8);
+ calc_type g = m_gamma->dir((rgb >> 3) & 0xFC);
+ calc_type b = m_gamma->dir((rgb << 3) & 0xF8);
+ *p = (pixel_type)
+ (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) |
+ ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) |
+ (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 8) & 0xF8,
+ (p >> 3) & 0xFC,
+ (p << 3) & 0xF8);
+ }
+
+ private:
+ const Gamma* m_gamma;
+ };
+
+
+
+ //=====================================================blender_rgbAAA
+ struct blender_rgbAAA
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 14) & 0xFFC0;
+ calc_type g = (rgb >> 4) & 0xFFC0;
+ calc_type b = (rgb << 6) & 0xFFC0;
+ *p = (pixel_type)
+ (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) |
+ ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) |
+ (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xFFC0) << 14) |
+ ((g & 0xFFC0) << 4) |
+ (b >> 6) | 0xC0000000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 14) & 0xFFC0,
+ (p >> 4) & 0xFFC0,
+ (p << 6) & 0xFFC0);
+ }
+ };
+
+
+
+ //==================================================blender_rgbAAA_pre
+ struct blender_rgbAAA_pre
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ cover = (cover + 1) << (color_type::base_shift - 8);
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 14) & 0xFFC0;
+ calc_type g = (rgb >> 4) & 0xFFC0;
+ calc_type b = (rgb << 6) & 0xFFC0;
+ *p = (pixel_type)
+ ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) |
+ (((g * alpha + cg * cover) >> 12) & 0x000FFC00) |
+ ((b * alpha + cb * cover) >> 22) | 0xC0000000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xFFC0) << 14) |
+ ((g & 0xFFC0) << 4) |
+ (b >> 6) | 0xC0000000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 14) & 0xFFC0,
+ (p >> 4) & 0xFFC0,
+ (p << 6) & 0xFFC0);
+ }
+ };
+
+
+
+ //=================================================blender_rgbAAA_gamma
+ template<class Gamma> class blender_rgbAAA_gamma
+ {
+ public:
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+ typedef Gamma gamma_type;
+
+ blender_rgbAAA_gamma() : m_gamma(0) {}
+ void gamma(const gamma_type& g) { m_gamma = &g; }
+
+ AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0);
+ calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0);
+ calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0);
+ *p = (pixel_type)
+ (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) |
+ ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) |
+ (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xFFC0) << 14) |
+ ((g & 0xFFC0) << 4) |
+ (b >> 6) | 0xC0000000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 14) & 0xFFC0,
+ (p >> 4) & 0xFFC0,
+ (p << 6) & 0xFFC0);
+ }
+ private:
+ const Gamma* m_gamma;
+ };
+
+
+ //=====================================================blender_bgrAAA
+ struct blender_bgrAAA
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type bgr = *p;
+ calc_type b = (bgr >> 14) & 0xFFC0;
+ calc_type g = (bgr >> 4) & 0xFFC0;
+ calc_type r = (bgr << 6) & 0xFFC0;
+ *p = (pixel_type)
+ (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) |
+ ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) |
+ (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((b & 0xFFC0) << 14) |
+ ((g & 0xFFC0) << 4) |
+ (r >> 6) | 0xC0000000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p << 6) & 0xFFC0,
+ (p >> 4) & 0xFFC0,
+ (p >> 14) & 0xFFC0);
+ }
+ };
+
+
+
+ //=================================================blender_bgrAAA_pre
+ struct blender_bgrAAA_pre
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ cover = (cover + 1) << (color_type::base_shift - 8);
+ pixel_type bgr = *p;
+ calc_type b = (bgr >> 14) & 0xFFC0;
+ calc_type g = (bgr >> 4) & 0xFFC0;
+ calc_type r = (bgr << 6) & 0xFFC0;
+ *p = (pixel_type)
+ ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) |
+ (((g * alpha + cg * cover) >> 12) & 0x000FFC00) |
+ ((r * alpha + cr * cover) >> 22) | 0xC0000000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((b & 0xFFC0) << 14) |
+ ((g & 0xFFC0) << 4) |
+ (r >> 6) | 0xC0000000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p << 6) & 0xFFC0,
+ (p >> 4) & 0xFFC0,
+ (p >> 14) & 0xFFC0);
+ }
+ };
+
+
+
+ //=================================================blender_bgrAAA_gamma
+ template<class Gamma> class blender_bgrAAA_gamma
+ {
+ public:
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+ typedef Gamma gamma_type;
+
+ blender_bgrAAA_gamma() : m_gamma(0) {}
+ void gamma(const gamma_type& g) { m_gamma = &g; }
+
+ AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type bgr = *p;
+ calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0);
+ calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0);
+ calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0);
+ *p = (pixel_type)
+ (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) |
+ ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) |
+ (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000);
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((b & 0xFFC0) << 14) |
+ ((g & 0xFFC0) << 4) |
+ (r >> 6) | 0xC0000000);
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p << 6) & 0xFFC0,
+ (p >> 4) & 0xFFC0,
+ (p >> 14) & 0xFFC0);
+ }
+
+ private:
+ const Gamma* m_gamma;
+ };
+
+
+
+ //=====================================================blender_rgbBBA
+ struct blender_rgbBBA
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 16) & 0xFFE0;
+ calc_type g = (rgb >> 5) & 0xFFE0;
+ calc_type b = (rgb << 6) & 0xFFC0;
+ *p = (pixel_type)
+ (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) |
+ ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) |
+ (((cb - b) * alpha + (b << 16)) >> 22));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 16) & 0xFFE0,
+ (p >> 5) & 0xFFE0,
+ (p << 6) & 0xFFC0);
+ }
+ };
+
+
+ //=================================================blender_rgbBBA_pre
+ struct blender_rgbBBA_pre
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ cover = (cover + 1) << (color_type::base_shift - 8);
+ pixel_type rgb = *p;
+ calc_type r = (rgb >> 16) & 0xFFE0;
+ calc_type g = (rgb >> 5) & 0xFFE0;
+ calc_type b = (rgb << 6) & 0xFFC0;
+ *p = (pixel_type)
+ ((((r * alpha + cr * cover) ) & 0xFFE00000) |
+ (((g * alpha + cg * cover) >> 11) & 0x001FFC00) |
+ ((b * alpha + cb * cover) >> 22));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 16) & 0xFFE0,
+ (p >> 5) & 0xFFE0,
+ (p << 6) & 0xFFC0);
+ }
+ };
+
+
+
+ //=================================================blender_rgbBBA_gamma
+ template<class Gamma> class blender_rgbBBA_gamma
+ {
+ public:
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+ typedef Gamma gamma_type;
+
+ blender_rgbBBA_gamma() : m_gamma(0) {}
+ void gamma(const gamma_type& g) { m_gamma = &g; }
+
+ AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type rgb = *p;
+ calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0);
+ calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0);
+ calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0);
+ *p = (pixel_type)
+ (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) |
+ ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) |
+ (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p >> 16) & 0xFFE0,
+ (p >> 5) & 0xFFE0,
+ (p << 6) & 0xFFC0);
+ }
+
+ private:
+ const Gamma* m_gamma;
+ };
+
+
+ //=====================================================blender_bgrABB
+ struct blender_bgrABB
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type bgr = *p;
+ calc_type b = (bgr >> 16) & 0xFFC0;
+ calc_type g = (bgr >> 6) & 0xFFE0;
+ calc_type r = (bgr << 5) & 0xFFE0;
+ *p = (pixel_type)
+ (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) |
+ ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) |
+ (((cr - r) * alpha + (r << 16)) >> 21));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p << 5) & 0xFFE0,
+ (p >> 6) & 0xFFE0,
+ (p >> 16) & 0xFFC0);
+ }
+ };
+
+
+ //=================================================blender_bgrABB_pre
+ struct blender_bgrABB_pre
+ {
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+
+ static AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ cover = (cover + 1) << (color_type::base_shift - 8);
+ pixel_type bgr = *p;
+ calc_type b = (bgr >> 16) & 0xFFC0;
+ calc_type g = (bgr >> 6) & 0xFFE0;
+ calc_type r = (bgr << 5) & 0xFFE0;
+ *p = (pixel_type)
+ ((((b * alpha + cb * cover) ) & 0xFFC00000) |
+ (((g * alpha + cg * cover) >> 10) & 0x003FF800) |
+ ((r * alpha + cr * cover) >> 21));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p << 5) & 0xFFE0,
+ (p >> 6) & 0xFFE0,
+ (p >> 16) & 0xFFC0);
+ }
+ };
+
+
+
+ //=================================================blender_bgrABB_gamma
+ template<class Gamma> class blender_bgrABB_gamma
+ {
+ public:
+ typedef rgba16 color_type;
+ typedef color_type::value_type value_type;
+ typedef color_type::calc_type calc_type;
+ typedef int32u pixel_type;
+ typedef Gamma gamma_type;
+
+ blender_bgrABB_gamma() : m_gamma(0) {}
+ void gamma(const gamma_type& g) { m_gamma = &g; }
+
+ AGG_INLINE void blend_pix(pixel_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned)
+ {
+ pixel_type bgr = *p;
+ calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0);
+ calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0);
+ calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0);
+ *p = (pixel_type)
+ (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) |
+ ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) |
+ (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 ));
+ }
+
+ static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
+ {
+ return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
+ }
+
+ static AGG_INLINE color_type make_color(pixel_type p)
+ {
+ return color_type((p << 5) & 0xFFE0,
+ (p >> 6) & 0xFFE0,
+ (p >> 16) & 0xFFC0);
+ }
+
+ private:
+ const Gamma* m_gamma;
+ };
+
+
+
+ //===========================================pixfmt_alpha_blend_rgb_packed
+ template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_packed
+ {
+ public:
+ typedef RenBuf rbuf_type;
+ typedef typename rbuf_type::row_data row_data;
+ typedef Blender blender_type;
+ typedef typename blender_type::color_type color_type;
+ typedef typename blender_type::pixel_type pixel_type;
+ typedef int order_type; // A fake one
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_scale = color_type::base_scale,
+ base_mask = color_type::base_mask,
+ pix_width = sizeof(pixel_type)
+ };
+
+ private:
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
+ {
+ if (c.a)
+ {
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ *p = m_blender.make_pix(c.r, c.g, c.b);
+ }
+ else
+ {
+ m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ }
+ }
+ }
+
+ public:
+ //--------------------------------------------------------------------
+ explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {}
+ void attach(rbuf_type& rb) { m_rbuf = &rb; }
+
+ //--------------------------------------------------------------------
+ template<class PixFmt>
+ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
+ {
+ rect_i r(x1, y1, x2, y2);
+ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
+ {
+ int stride = pixf.stride();
+ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
+ (r.x2 - r.x1) + 1,
+ (r.y2 - r.y1) + 1,
+ stride);
+ return true;
+ }
+ return false;
+ }
+
+ Blender& blender() { return m_blender; }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned width() const { return m_rbuf->width(); }
+ AGG_INLINE unsigned height() const { return m_rbuf->height(); }
+ AGG_INLINE int stride() const { return m_rbuf->stride(); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
+ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
+ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* pix_ptr(int x, int y)
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+ AGG_INLINE const int8u* pix_ptr(int x, int y) const
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void make_pix(int8u* p, const color_type& c)
+ {
+ *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE color_type pixel(int x, int y) const
+ {
+ return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
+ {
+ ((pixel_type*)
+ m_rbuf->row_ptr(x, y, 1))[x] =
+ m_blender.make_pix(c.r, c.g, c.b);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
+ {
+ copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_hline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
+ pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
+ do
+ {
+ *p++ = v;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_vline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
+ do
+ {
+ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
+ *p = v;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
+ do
+ {
+ *p++ = v;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ ++p;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
+ do
+ {
+ ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ m_blender.blend_pix(
+ (pixel_type*)m_rbuf->row_ptr(x, y++, 1),
+ c.r, c.g, c.b, alpha, cover);
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
+ do
+ {
+ copy_or_blend_pix(p, c, *covers++);
+ ++p;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ do
+ {
+ copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x,
+ c, *covers++);
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
+ do
+ {
+ *p++ = m_blender.make_pix(colors->r, colors->g, colors->b);
+ ++colors;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ do
+ {
+ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
+ *p = m_blender.make_pix(colors->r, colors->g, colors->b);
+ ++colors;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
+ do
+ {
+ copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover);
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ do
+ {
+ copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x,
+ *colors++, covers ? *covers++ : cover);
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf2>
+ void copy_from(const RenBuf2& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len)
+ {
+ const int8u* p = from.row_ptr(ysrc);
+ if(p)
+ {
+ memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
+ p + xsrc * pix_width,
+ len * pix_width);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from(const SrcPixelFormatRenderer& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::order_type src_order;
+
+ const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ psrc += xsrc * 4;
+ pixel_type* pdst =
+ (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
+ do
+ {
+ value_type alpha = psrc[src_order::A];
+ if(alpha)
+ {
+ if(alpha == base_mask && cover == 255)
+ {
+ *pdst = m_blender.make_pix(psrc[src_order::R],
+ psrc[src_order::G],
+ psrc[src_order::B]);
+ }
+ else
+ {
+ m_blender.blend_pix(pdst,
+ psrc[src_order::R],
+ psrc[src_order::G],
+ psrc[src_order::B],
+ alpha,
+ cover);
+ }
+ }
+ psrc += 4;
+ ++pdst;
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_color(const SrcPixelFormatRenderer& from,
+ const color_type& color,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ pixel_type* pdst =
+ (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
+
+ do
+ {
+ m_blender.blend_pix(pdst,
+ color.r, color.g, color.b, color.a,
+ cover);
+ ++psrc;
+ ++pdst;
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_lut(const SrcPixelFormatRenderer& from,
+ const color_type* color_lut,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ pixel_type* pdst =
+ (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
+
+ do
+ {
+ const color_type& color = color_lut[*psrc];
+ m_blender.blend_pix(pdst,
+ color.r, color.g, color.b, color.a,
+ cover);
+ ++psrc;
+ ++pdst;
+ }
+ while(--len);
+ }
+ }
+
+
+
+ private:
+ rbuf_type* m_rbuf;
+ Blender m_blender;
+ };
+
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555, rendering_buffer> pixfmt_rgb555; //----pixfmt_rgb555
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565, rendering_buffer> pixfmt_rgb565; //----pixfmt_rgb565
+
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555_pre, rendering_buffer> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565_pre, rendering_buffer> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre
+
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA, rendering_buffer> pixfmt_rgbAAA; //----pixfmt_rgbAAA
+ typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA, rendering_buffer> pixfmt_bgrAAA; //----pixfmt_bgrAAA
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA, rendering_buffer> pixfmt_rgbBBA; //----pixfmt_rgbBBA
+ typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB, rendering_buffer> pixfmt_bgrABB; //----pixfmt_bgrABB
+
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_pre, rendering_buffer> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre
+ typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_pre, rendering_buffer> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre
+ typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_pre, rendering_buffer> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre
+ typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB_pre, rendering_buffer> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre
+
+
+ //-----------------------------------------------------pixfmt_rgb555_gamma
+ template<class Gamma> class pixfmt_rgb555_gamma :
+ public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>,
+ rendering_buffer>
+ {
+ public:
+ pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>,
+ rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+
+ //-----------------------------------------------------pixfmt_rgb565_gamma
+ template<class Gamma> class pixfmt_rgb565_gamma :
+ public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>
+ {
+ public:
+ pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+
+ //-----------------------------------------------------pixfmt_rgbAAA_gamma
+ template<class Gamma> class pixfmt_rgbAAA_gamma :
+ public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>,
+ rendering_buffer>
+ {
+ public:
+ pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>,
+ rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+
+ //-----------------------------------------------------pixfmt_bgrAAA_gamma
+ template<class Gamma> class pixfmt_bgrAAA_gamma :
+ public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>,
+ rendering_buffer>
+ {
+ public:
+ pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>,
+ rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+
+ //-----------------------------------------------------pixfmt_rgbBBA_gamma
+ template<class Gamma> class pixfmt_rgbBBA_gamma :
+ public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>,
+ rendering_buffer>
+ {
+ public:
+ pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>,
+ rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+
+ //-----------------------------------------------------pixfmt_bgrABB_gamma
+ template<class Gamma> class pixfmt_bgrABB_gamma :
+ public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>,
+ rendering_buffer>
+ {
+ public:
+ pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>,
+ rendering_buffer>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_pixfmt_rgba.h b/plugins/Clist_ng/AGG/include/agg_pixfmt_rgba.h new file mode 100644 index 0000000000..90a0309419 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_pixfmt_rgba.h @@ -0,0 +1,2903 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PIXFMT_RGBA_INCLUDED
+#define AGG_PIXFMT_RGBA_INCLUDED
+
+#include <string.h>
+#include <math.h>
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+#include "agg_rendering_buffer.h"
+
+namespace agg
+{
+
+ //=========================================================multiplier_rgba
+ template<class ColorT, class Order> struct multiplier_rgba
+ {
+ typedef typename ColorT::value_type value_type;
+ typedef typename ColorT::calc_type calc_type;
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void premultiply(value_type* p)
+ {
+ calc_type a = p[Order::A];
+ if(a < ColorT::base_mask)
+ {
+ if(a == 0)
+ {
+ p[Order::R] = p[Order::G] = p[Order::B] = 0;
+ return;
+ }
+ p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift);
+ p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift);
+ p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void demultiply(value_type* p)
+ {
+ calc_type a = p[Order::A];
+ if(a < ColorT::base_mask)
+ {
+ if(a == 0)
+ {
+ p[Order::R] = p[Order::G] = p[Order::B] = 0;
+ return;
+ }
+ calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a;
+ calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a;
+ calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a;
+ p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r);
+ p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g);
+ p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b);
+ }
+ }
+ };
+
+ //=====================================================apply_gamma_dir_rgba
+ template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba
+ {
+ public:
+ typedef typename ColorT::value_type value_type;
+
+ apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
+
+ AGG_INLINE void operator () (value_type* p)
+ {
+ p[Order::R] = m_gamma.dir(p[Order::R]);
+ p[Order::G] = m_gamma.dir(p[Order::G]);
+ p[Order::B] = m_gamma.dir(p[Order::B]);
+ }
+
+ private:
+ const GammaLut& m_gamma;
+ };
+
+ //=====================================================apply_gamma_inv_rgba
+ template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba
+ {
+ public:
+ typedef typename ColorT::value_type value_type;
+
+ apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
+
+ AGG_INLINE void operator () (value_type* p)
+ {
+ p[Order::R] = m_gamma.inv(p[Order::R]);
+ p[Order::G] = m_gamma.inv(p[Order::G]);
+ p[Order::B] = m_gamma.inv(p[Order::B]);
+ }
+
+ private:
+ const GammaLut& m_gamma;
+ };
+
+
+ //=============================================================blender_rgba
+ template<class ColorT, class Order> struct blender_rgba
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover=0)
+ {
+ calc_type r = p[Order::R];
+ calc_type g = p[Order::G];
+ calc_type b = p[Order::B];
+ calc_type a = p[Order::A];
+ p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift);
+ p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift);
+ p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift);
+ p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift));
+ }
+ };
+
+ //=========================================================blender_rgba_pre
+ template<class ColorT, class Order> struct blender_rgba_pre
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ alpha = color_type::base_mask - alpha;
+ cover = (cover + 1) << (base_shift - 8);
+ p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
+ p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
+ p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
+ p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha)
+ {
+ alpha = color_type::base_mask - alpha;
+ p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
+ p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
+ p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
+ p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift));
+ }
+ };
+
+ //======================================================blender_rgba_plain
+ template<class ColorT, class Order> struct blender_rgba_plain
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e { base_shift = color_type::base_shift };
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover=0)
+ {
+ if(alpha == 0) return;
+ calc_type a = p[Order::A];
+ calc_type r = p[Order::R] * a;
+ calc_type g = p[Order::G] * a;
+ calc_type b = p[Order::B] * a;
+ a = ((alpha + a) << base_shift) - alpha * a;
+ p[Order::A] = (value_type)(a >> base_shift);
+ p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a);
+ p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a);
+ p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a);
+ }
+ };
+
+
+
+
+
+
+
+
+
+
+
+ //=========================================================comp_op_rgba_clear
+ template<class ColorT, class Order> struct comp_op_rgba_clear
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned, unsigned, unsigned, unsigned,
+ unsigned cover)
+ {
+ if(cover < 255)
+ {
+ cover = 255 - cover;
+ p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8);
+ p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8);
+ p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8);
+ p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8);
+ }
+ else
+ {
+ p[0] = p[1] = p[2] = p[3] = 0;
+ }
+ }
+ };
+
+ //===========================================================comp_op_rgba_src
+ template<class ColorT, class Order> struct comp_op_rgba_src
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ unsigned alpha = 255 - cover;
+ p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8));
+ p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8));
+ p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8));
+ p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8));
+ }
+ else
+ {
+ p[Order::R] = sr;
+ p[Order::G] = sg;
+ p[Order::B] = sb;
+ p[Order::A] = sa;
+ }
+ }
+ };
+
+ //===========================================================comp_op_rgba_dst
+ template<class ColorT, class Order> struct comp_op_rgba_dst
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+
+ static AGG_INLINE void blend_pix(value_type*,
+ unsigned, unsigned, unsigned,
+ unsigned, unsigned)
+ {
+ }
+ };
+
+ //======================================================comp_op_rgba_src_over
+ template<class ColorT, class Order> struct comp_op_rgba_src_over
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca + Dca.(1 - Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ calc_type s1a = base_mask - sa;
+ p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift));
+ p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift));
+ p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift));
+ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
+ }
+ };
+
+ //======================================================comp_op_rgba_dst_over
+ template<class ColorT, class Order> struct comp_op_rgba_dst_over
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Dca + Sca.(1 - Da)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ calc_type d1a = base_mask - p[Order::A];
+ p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift));
+ p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift));
+ p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift));
+ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
+ }
+ };
+
+ //======================================================comp_op_rgba_src_in
+ template<class ColorT, class Order> struct comp_op_rgba_src_in
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca.Da
+ // Da' = Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ calc_type da = p[Order::A];
+ if(cover < 255)
+ {
+ unsigned alpha = 255 - cover;
+ p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ }
+ else
+ {
+ p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift);
+ p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift);
+ }
+ }
+ };
+
+ //======================================================comp_op_rgba_dst_in
+ template<class ColorT, class Order> struct comp_op_rgba_dst_in
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Dca.Sa
+ // Da' = Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned, unsigned, unsigned,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8);
+ }
+ p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift);
+ p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift);
+ }
+ };
+
+ //======================================================comp_op_rgba_src_out
+ template<class ColorT, class Order> struct comp_op_rgba_src_out
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca.(1 - Da)
+ // Da' = Sa.(1 - Da)
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ calc_type da = base_mask - p[Order::A];
+ if(cover < 255)
+ {
+ unsigned alpha = 255 - cover;
+ p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8));
+ }
+ else
+ {
+ p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift);
+ p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift);
+ }
+ }
+ };
+
+ //======================================================comp_op_rgba_dst_out
+ template<class ColorT, class Order> struct comp_op_rgba_dst_out
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Dca.(1 - Sa)
+ // Da' = Da.(1 - Sa)
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned, unsigned, unsigned,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sa = (sa * cover + 255) >> 8;
+ }
+ sa = base_mask - sa;
+ p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift);
+ p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift);
+ p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift);
+ p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift);
+ }
+ };
+
+ //=====================================================comp_op_rgba_src_atop
+ template<class ColorT, class Order> struct comp_op_rgba_src_atop
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca.Da + Dca.(1 - Sa)
+ // Da' = Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ calc_type da = p[Order::A];
+ sa = base_mask - sa;
+ p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift);
+ }
+ };
+
+ //=====================================================comp_op_rgba_dst_atop
+ template<class ColorT, class Order> struct comp_op_rgba_dst_atop
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Dca.Sa + Sca.(1 - Da)
+ // Da' = Sa
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ calc_type da = base_mask - p[Order::A];
+ if(cover < 255)
+ {
+ unsigned alpha = 255 - cover;
+ sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift;
+ sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift;
+ sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift;
+ p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8));
+ p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8));
+ p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8));
+ p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8));
+
+ }
+ else
+ {
+ p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift);
+ p[Order::A] = (value_type)sa;
+ }
+ }
+ };
+
+ //=========================================================comp_op_rgba_xor
+ template<class ColorT, class Order> struct comp_op_rgba_xor
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
+ // Da' = Sa + Da - 2.Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type s1a = base_mask - sa;
+ calc_type d1a = base_mask - p[Order::A];
+ p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift);
+ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1)));
+ }
+ }
+ };
+
+ //=========================================================comp_op_rgba_plus
+ template<class ColorT, class Order> struct comp_op_rgba_plus
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca + Dca
+ // Da' = Sa + Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type dr = p[Order::R] + sr;
+ calc_type dg = p[Order::G] + sg;
+ calc_type db = p[Order::B] + sb;
+ calc_type da = p[Order::A] + sa;
+ p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr;
+ p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg;
+ p[Order::B] = (db > base_mask) ? (value_type)base_mask : db;
+ p[Order::A] = (da > base_mask) ? (value_type)base_mask : da;
+ }
+ }
+ };
+
+ //========================================================comp_op_rgba_minus
+ template<class ColorT, class Order> struct comp_op_rgba_minus
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Dca - Sca
+ // Da' = 1 - (1 - Sa).(1 - Da)
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type dr = p[Order::R] - sr;
+ calc_type dg = p[Order::G] - sg;
+ calc_type db = p[Order::B] - sb;
+ p[Order::R] = (dr > base_mask) ? 0 : dr;
+ p[Order::G] = (dg > base_mask) ? 0 : dg;
+ p[Order::B] = (db > base_mask) ? 0 : db;
+ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
+ //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_multiply
+ template<class ColorT, class Order> struct comp_op_rgba_multiply
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type s1a = base_mask - sa;
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift);
+ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_screen
+ template<class ColorT, class Order> struct comp_op_rgba_screen
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca + Dca - Sca.Dca
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+ p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift));
+ p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift));
+ p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift));
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_overlay
+ template<class ColorT, class Order> struct comp_op_rgba_overlay
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // if 2.Dca < Da
+ // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ // otherwise
+ // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ //
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type s1a = base_mask - sa;
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+ calc_type sada = sa * p[Order::A];
+
+ p[Order::R] = (value_type)(((2*dr < da) ?
+ 2*sr*dr + sr*d1a + dr*s1a :
+ sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
+
+ p[Order::G] = (value_type)(((2*dg < da) ?
+ 2*sg*dg + sg*d1a + dg*s1a :
+ sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
+
+ p[Order::B] = (value_type)(((2*db < da) ?
+ 2*sb*db + sb*d1a + db*s1a :
+ sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
+
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+
+ template<class T> inline T sd_min(T a, T b) { return (a < b) ? a : b; }
+ template<class T> inline T sd_max(T a, T b) { return (a > b) ? a : b; }
+
+ //=====================================================comp_op_rgba_darken
+ template<class ColorT, class Order> struct comp_op_rgba_darken
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type s1a = base_mask - sa;
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+
+ p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_lighten
+ template<class ColorT, class Order> struct comp_op_rgba_lighten
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type s1a = base_mask - sa;
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+
+ p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_color_dodge
+ template<class ColorT, class Order> struct comp_op_rgba_color_dodge
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // if Sca.Da + Dca.Sa >= Sa.Da
+ // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
+ // otherwise
+ // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ //
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type s1a = base_mask - sa;
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+ long_type drsa = dr * sa;
+ long_type dgsa = dg * sa;
+ long_type dbsa = db * sa;
+ long_type srda = sr * da;
+ long_type sgda = sg * da;
+ long_type sbda = sb * da;
+ long_type sada = sa * da;
+
+ p[Order::R] = (value_type)((srda + drsa >= sada) ?
+ (sada + sr * d1a + dr * s1a + base_mask) >> base_shift :
+ drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift));
+
+ p[Order::G] = (value_type)((sgda + dgsa >= sada) ?
+ (sada + sg * d1a + dg * s1a + base_mask) >> base_shift :
+ dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift));
+
+ p[Order::B] = (value_type)((sbda + dbsa >= sada) ?
+ (sada + sb * d1a + db * s1a + base_mask) >> base_shift :
+ dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift));
+
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_color_burn
+ template<class ColorT, class Order> struct comp_op_rgba_color_burn
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // if Sca.Da + Dca.Sa <= Sa.Da
+ // Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
+ // otherwise
+ // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
+ //
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type s1a = base_mask - sa;
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+ long_type drsa = dr * sa;
+ long_type dgsa = dg * sa;
+ long_type dbsa = db * sa;
+ long_type srda = sr * da;
+ long_type sgda = sg * da;
+ long_type sbda = sb * da;
+ long_type sada = sa * da;
+
+ p[Order::R] = (value_type)(((srda + drsa <= sada) ?
+ sr * d1a + dr * s1a :
+ sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift);
+
+ p[Order::G] = (value_type)(((sgda + dgsa <= sada) ?
+ sg * d1a + dg * s1a :
+ sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift);
+
+ p[Order::B] = (value_type)(((sbda + dbsa <= sada) ?
+ sb * d1a + db * s1a :
+ sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift);
+
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_hard_light
+ template<class ColorT, class Order> struct comp_op_rgba_hard_light
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // if 2.Sca < Sa
+ // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ // otherwise
+ // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ //
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type s1a = base_mask - sa;
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+ calc_type sada = sa * da;
+
+ p[Order::R] = (value_type)(((2*sr < sa) ?
+ 2*sr*dr + sr*d1a + dr*s1a :
+ sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
+
+ p[Order::G] = (value_type)(((2*sg < sa) ?
+ 2*sg*dg + sg*d1a + dg*s1a :
+ sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
+
+ p[Order::B] = (value_type)(((2*sb < sa) ?
+ 2*sb*db + sb*d1a + db*s1a :
+ sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
+
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_soft_light
+ template<class ColorT, class Order> struct comp_op_rgba_soft_light
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // if 2.Sca < Sa
+ // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
+ // otherwise if 8.Dca <= Da
+ // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
+ // otherwise
+ // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
+ //
+ // Da' = Sa + Da - Sa.Da
+
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned r, unsigned g, unsigned b,
+ unsigned a, unsigned cover)
+ {
+ double sr = double(r * cover) / (base_mask * 255);
+ double sg = double(g * cover) / (base_mask * 255);
+ double sb = double(b * cover) / (base_mask * 255);
+ double sa = double(a * cover) / (base_mask * 255);
+ if(sa > 0)
+ {
+ double dr = double(p[Order::R]) / base_mask;
+ double dg = double(p[Order::G]) / base_mask;
+ double db = double(p[Order::B]) / base_mask;
+ double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask;
+ if(cover < 255)
+ {
+ a = (a * cover + 255) >> 8;
+ }
+
+ if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa);
+ else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa);
+ else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa);
+
+ if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa);
+ else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa);
+ else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa);
+
+ if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa);
+ else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa);
+ else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa);
+
+ p[Order::R] = (value_type)uround(dr * base_mask);
+ p[Order::G] = (value_type)uround(dg * base_mask);
+ p[Order::B] = (value_type)uround(db * base_mask);
+ p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_difference
+ template<class ColorT, class Order> struct comp_op_rgba_difference
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_scale = color_type::base_scale,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+ p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift));
+ p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift));
+ p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift));
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_exclusion
+ template<class ColorT, class Order> struct comp_op_rgba_exclusion
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type d1a = base_mask - p[Order::A];
+ calc_type s1a = base_mask - sa;
+ calc_type dr = p[Order::R];
+ calc_type dg = p[Order::G];
+ calc_type db = p[Order::B];
+ calc_type da = p[Order::A];
+ p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift);
+ p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift);
+ p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift);
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=====================================================comp_op_rgba_contrast
+ template<class ColorT, class Order> struct comp_op_rgba_contrast
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ long_type dr = p[Order::R];
+ long_type dg = p[Order::G];
+ long_type db = p[Order::B];
+ int da = p[Order::A];
+ long_type d2a = da >> 1;
+ unsigned s2a = sa >> 1;
+
+ int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a);
+ int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a);
+ int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a);
+
+ r = (r < 0) ? 0 : r;
+ g = (g < 0) ? 0 : g;
+ b = (b < 0) ? 0 : b;
+
+ p[Order::R] = (value_type)((r > da) ? da : r);
+ p[Order::G] = (value_type)((g > da) ? da : g);
+ p[Order::B] = (value_type)((b > da) ? da : b);
+ }
+ };
+
+ //=====================================================comp_op_rgba_invert
+ template<class ColorT, class Order> struct comp_op_rgba_invert
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ sa = (sa * cover + 255) >> 8;
+ if(sa)
+ {
+ calc_type da = p[Order::A];
+ calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift;
+ calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift;
+ calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift;
+ calc_type s1a = base_mask - sa;
+ p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
+ p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
+ p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+ //=================================================comp_op_rgba_invert_rgb
+ template<class ColorT, class Order> struct comp_op_rgba_invert_rgb
+ {
+ typedef ColorT color_type;
+ typedef Order order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa)
+ // Da' = Sa + Da - Sa.Da
+ static AGG_INLINE void blend_pix(value_type* p,
+ unsigned sr, unsigned sg, unsigned sb,
+ unsigned sa, unsigned cover)
+ {
+ if(cover < 255)
+ {
+ sr = (sr * cover + 255) >> 8;
+ sg = (sg * cover + 255) >> 8;
+ sb = (sb * cover + 255) >> 8;
+ sa = (sa * cover + 255) >> 8;
+ }
+ if(sa)
+ {
+ calc_type da = p[Order::A];
+ calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift;
+ calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift;
+ calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift;
+ calc_type s1a = base_mask - sa;
+ p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
+ p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
+ p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
+ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
+ }
+ }
+ };
+
+
+
+
+
+ //======================================================comp_op_table_rgba
+ template<class ColorT, class Order> struct comp_op_table_rgba
+ {
+ typedef typename ColorT::value_type value_type;
+ typedef void (*comp_op_func_type)(value_type* p,
+ unsigned cr,
+ unsigned cg,
+ unsigned cb,
+ unsigned ca,
+ unsigned cover);
+ static comp_op_func_type g_comp_op_func[];
+ };
+
+ //==========================================================g_comp_op_func
+ template<class ColorT, class Order>
+ typename comp_op_table_rgba<ColorT, Order>::comp_op_func_type
+ comp_op_table_rgba<ColorT, Order>::g_comp_op_func[] =
+ {
+ comp_op_rgba_clear <ColorT,Order>::blend_pix,
+ comp_op_rgba_src <ColorT,Order>::blend_pix,
+ comp_op_rgba_dst <ColorT,Order>::blend_pix,
+ comp_op_rgba_src_over <ColorT,Order>::blend_pix,
+ comp_op_rgba_dst_over <ColorT,Order>::blend_pix,
+ comp_op_rgba_src_in <ColorT,Order>::blend_pix,
+ comp_op_rgba_dst_in <ColorT,Order>::blend_pix,
+ comp_op_rgba_src_out <ColorT,Order>::blend_pix,
+ comp_op_rgba_dst_out <ColorT,Order>::blend_pix,
+ comp_op_rgba_src_atop <ColorT,Order>::blend_pix,
+ comp_op_rgba_dst_atop <ColorT,Order>::blend_pix,
+ comp_op_rgba_xor <ColorT,Order>::blend_pix,
+ comp_op_rgba_plus <ColorT,Order>::blend_pix,
+ comp_op_rgba_minus <ColorT,Order>::blend_pix,
+ comp_op_rgba_multiply <ColorT,Order>::blend_pix,
+ comp_op_rgba_screen <ColorT,Order>::blend_pix,
+ comp_op_rgba_overlay <ColorT,Order>::blend_pix,
+ comp_op_rgba_darken <ColorT,Order>::blend_pix,
+ comp_op_rgba_lighten <ColorT,Order>::blend_pix,
+ comp_op_rgba_color_dodge<ColorT,Order>::blend_pix,
+ comp_op_rgba_color_burn <ColorT,Order>::blend_pix,
+ comp_op_rgba_hard_light <ColorT,Order>::blend_pix,
+ comp_op_rgba_soft_light <ColorT,Order>::blend_pix,
+ comp_op_rgba_difference <ColorT,Order>::blend_pix,
+ comp_op_rgba_exclusion <ColorT,Order>::blend_pix,
+ comp_op_rgba_contrast <ColorT,Order>::blend_pix,
+ comp_op_rgba_invert <ColorT,Order>::blend_pix,
+ comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix,
+ 0
+ };
+
+
+ //==============================================================comp_op_e
+ enum comp_op_e
+ {
+ comp_op_clear, //----comp_op_clear
+ comp_op_src, //----comp_op_src
+ comp_op_dst, //----comp_op_dst
+ comp_op_src_over, //----comp_op_src_over
+ comp_op_dst_over, //----comp_op_dst_over
+ comp_op_src_in, //----comp_op_src_in
+ comp_op_dst_in, //----comp_op_dst_in
+ comp_op_src_out, //----comp_op_src_out
+ comp_op_dst_out, //----comp_op_dst_out
+ comp_op_src_atop, //----comp_op_src_atop
+ comp_op_dst_atop, //----comp_op_dst_atop
+ comp_op_xor, //----comp_op_xor
+ comp_op_plus, //----comp_op_plus
+ comp_op_minus, //----comp_op_minus
+ comp_op_multiply, //----comp_op_multiply
+ comp_op_screen, //----comp_op_screen
+ comp_op_overlay, //----comp_op_overlay
+ comp_op_darken, //----comp_op_darken
+ comp_op_lighten, //----comp_op_lighten
+ comp_op_color_dodge, //----comp_op_color_dodge
+ comp_op_color_burn, //----comp_op_color_burn
+ comp_op_hard_light, //----comp_op_hard_light
+ comp_op_soft_light, //----comp_op_soft_light
+ comp_op_difference, //----comp_op_difference
+ comp_op_exclusion, //----comp_op_exclusion
+ comp_op_contrast, //----comp_op_contrast
+ comp_op_invert, //----comp_op_invert
+ comp_op_invert_rgb, //----comp_op_invert_rgb
+
+ end_of_comp_op_e
+ };
+
+
+
+
+
+
+
+ //====================================================comp_op_adaptor_rgba
+ template<class ColorT, class Order> struct comp_op_adaptor_rgba
+ {
+ typedef Order order_type;
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(unsigned op, value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned ca,
+ unsigned cover)
+ {
+ comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
+ (p, (cr * ca + base_mask) >> base_shift,
+ (cg * ca + base_mask) >> base_shift,
+ (cb * ca + base_mask) >> base_shift,
+ ca, cover);
+ }
+ };
+
+ //=========================================comp_op_adaptor_clip_to_dst_rgba
+ template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba
+ {
+ typedef Order order_type;
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(unsigned op, value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned ca,
+ unsigned cover)
+ {
+ cr = (cr * ca + base_mask) >> base_shift;
+ cg = (cg * ca + base_mask) >> base_shift;
+ cb = (cb * ca + base_mask) >> base_shift;
+ unsigned da = p[Order::A];
+ comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
+ (p, (cr * da + base_mask) >> base_shift,
+ (cg * da + base_mask) >> base_shift,
+ (cb * da + base_mask) >> base_shift,
+ (ca * da + base_mask) >> base_shift,
+ cover);
+ }
+ };
+
+ //================================================comp_op_adaptor_rgba_pre
+ template<class ColorT, class Order> struct comp_op_adaptor_rgba_pre
+ {
+ typedef Order order_type;
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(unsigned op, value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned ca,
+ unsigned cover)
+ {
+ comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p, cr, cg, cb, ca, cover);
+ }
+ };
+
+ //=====================================comp_op_adaptor_clip_to_dst_rgba_pre
+ template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba_pre
+ {
+ typedef Order order_type;
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(unsigned op, value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned ca,
+ unsigned cover)
+ {
+ unsigned da = p[Order::A];
+ comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
+ (p, (cr * da + base_mask) >> base_shift,
+ (cg * da + base_mask) >> base_shift,
+ (cb * da + base_mask) >> base_shift,
+ (ca * da + base_mask) >> base_shift,
+ cover);
+ }
+ };
+
+ //=======================================================comp_adaptor_rgba
+ template<class BlenderPre> struct comp_adaptor_rgba
+ {
+ typedef typename BlenderPre::order_type order_type;
+ typedef typename BlenderPre::color_type color_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(unsigned op, value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned ca,
+ unsigned cover)
+ {
+ BlenderPre::blend_pix(p,
+ (cr * ca + base_mask) >> base_shift,
+ (cg * ca + base_mask) >> base_shift,
+ (cb * ca + base_mask) >> base_shift,
+ ca, cover);
+ }
+ };
+
+ //==========================================comp_adaptor_clip_to_dst_rgba
+ template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba
+ {
+ typedef typename BlenderPre::order_type order_type;
+ typedef typename BlenderPre::color_type color_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(unsigned op, value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned ca,
+ unsigned cover)
+ {
+ cr = (cr * ca + base_mask) >> base_shift;
+ cg = (cg * ca + base_mask) >> base_shift;
+ cb = (cb * ca + base_mask) >> base_shift;
+ unsigned da = p[order_type::A];
+ BlenderPre::blend_pix(p,
+ (cr * da + base_mask) >> base_shift,
+ (cg * da + base_mask) >> base_shift,
+ (cb * da + base_mask) >> base_shift,
+ (ca * da + base_mask) >> base_shift,
+ cover);
+ }
+ };
+
+ //======================================comp_adaptor_clip_to_dst_rgba_pre
+ template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba_pre
+ {
+ typedef typename BlenderPre::order_type order_type;
+ typedef typename BlenderPre::color_type color_type;
+ typedef typename color_type::value_type value_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ static AGG_INLINE void blend_pix(unsigned op, value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned ca,
+ unsigned cover)
+ {
+ unsigned da = p[order_type::A];
+ BlenderPre::blend_pix(p,
+ (cr * da + base_mask) >> base_shift,
+ (cg * da + base_mask) >> base_shift,
+ (cb * da + base_mask) >> base_shift,
+ (ca * da + base_mask) >> base_shift,
+ cover);
+ }
+ };
+
+
+
+
+
+
+ //===============================================copy_or_blend_rgba_wrapper
+ template<class Blender> struct copy_or_blend_rgba_wrapper
+ {
+ typedef typename Blender::color_type color_type;
+ typedef typename Blender::order_type order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_scale = color_type::base_scale,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void copy_or_blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha)
+ {
+ if(alpha)
+ {
+ if(alpha == base_mask)
+ {
+ p[order_type::R] = cr;
+ p[order_type::G] = cg;
+ p[order_type::B] = cb;
+ p[order_type::A] = base_mask;
+ }
+ else
+ {
+ Blender::blend_pix(p, cr, cg, cb, alpha);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void copy_or_blend_pix(value_type* p,
+ unsigned cr, unsigned cg, unsigned cb,
+ unsigned alpha,
+ unsigned cover)
+ {
+ if(cover == 255)
+ {
+ copy_or_blend_pix(p, cr, cg, cb, alpha);
+ }
+ else
+ {
+ if(alpha)
+ {
+ alpha = (alpha * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ p[order_type::R] = cr;
+ p[order_type::G] = cg;
+ p[order_type::B] = cb;
+ p[order_type::A] = base_mask;
+ }
+ else
+ {
+ Blender::blend_pix(p, cr, cg, cb, alpha, cover);
+ }
+ }
+ }
+ }
+ };
+
+
+
+
+
+
+ //=================================================pixfmt_alpha_blend_rgba
+ template<class Blender, class RenBuf, class PixelT = int32u>
+ class pixfmt_alpha_blend_rgba
+ {
+ public:
+ typedef RenBuf rbuf_type;
+ typedef typename rbuf_type::row_data row_data;
+ typedef PixelT pixel_type;
+ typedef Blender blender_type;
+ typedef typename blender_type::color_type color_type;
+ typedef typename blender_type::order_type order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ typedef copy_or_blend_rgba_wrapper<blender_type> cob_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_scale = color_type::base_scale,
+ base_mask = color_type::base_mask,
+ pix_width = sizeof(pixel_type)
+ };
+
+ //--------------------------------------------------------------------
+ pixfmt_alpha_blend_rgba() : m_rbuf(0) {}
+ explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
+ void attach(rbuf_type& rb) { m_rbuf = &rb; }
+
+ //--------------------------------------------------------------------
+ template<class PixFmt>
+ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
+ {
+ rect_i r(x1, y1, x2, y2);
+ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
+ {
+ int stride = pixf.stride();
+ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
+ (r.x2 - r.x1) + 1,
+ (r.y2 - r.y1) + 1,
+ stride);
+ return true;
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned width() const { return m_rbuf->width(); }
+ AGG_INLINE unsigned height() const { return m_rbuf->height(); }
+ AGG_INLINE int stride() const { return m_rbuf->stride(); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
+ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
+ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* pix_ptr(int x, int y)
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+ AGG_INLINE const int8u* pix_ptr(int x, int y) const
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+
+ //--------------------------------------------------------------------
+ AGG_INLINE static void make_pix(int8u* p, const color_type& c)
+ {
+ ((value_type*)p)[order_type::R] = c.r;
+ ((value_type*)p)[order_type::G] = c.g;
+ ((value_type*)p)[order_type::B] = c.b;
+ ((value_type*)p)[order_type::A] = c.a;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE color_type pixel(int x, int y) const
+ {
+ const value_type* p = (const value_type*)m_rbuf->row_ptr(y);
+ if(p)
+ {
+ p += x << 2;
+ return color_type(p[order_type::R],
+ p[order_type::G],
+ p[order_type::B],
+ p[order_type::A]);
+ }
+ return color_type::no_color();
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2);
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ p[order_type::A] = c.a;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
+ {
+ cob_type::copy_or_blend_pix(
+ (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2),
+ c.r, c.g, c.b, c.a,
+ cover);
+ }
+
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_hline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ pixel_type v;
+ ((value_type*)&v)[order_type::R] = c.r;
+ ((value_type*)&v)[order_type::G] = c.g;
+ ((value_type*)&v)[order_type::B] = c.b;
+ ((value_type*)&v)[order_type::A] = c.a;
+ do
+ {
+ *(pixel_type*)p = v;
+ p += 4;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_vline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ pixel_type v;
+ ((value_type*)&v)[order_type::R] = c.r;
+ ((value_type*)&v)[order_type::G] = c.g;
+ ((value_type*)&v)[order_type::B] = c.b;
+ ((value_type*)&v)[order_type::A] = c.a;
+ do
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ *(pixel_type*)p = v;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ pixel_type v;
+ ((value_type*)&v)[order_type::R] = c.r;
+ ((value_type*)&v)[order_type::G] = c.g;
+ ((value_type*)&v)[order_type::B] = c.b;
+ ((value_type*)&v)[order_type::A] = c.a;
+ do
+ {
+ *(pixel_type*)p = v;
+ p += 4;
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ blender_type::blend_pix(p, c.r, c.g, c.b, alpha);
+ p += 4;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ p += 4;
+ }
+ while(--len);
+ }
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ if (c.a)
+ {
+ value_type* p;
+ calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ pixel_type v;
+ ((value_type*)&v)[order_type::R] = c.r;
+ ((value_type*)&v)[order_type::G] = c.g;
+ ((value_type*)&v)[order_type::B] = c.b;
+ ((value_type*)&v)[order_type::A] = c.a;
+ do
+ {
+ p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ *(pixel_type*)p = v;
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ blender_type::blend_pix(p, c.r, c.g, c.b, alpha);
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ }
+ while(--len);
+ }
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ if (c.a)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ do
+ {
+ calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ p[order_type::A] = base_mask;
+ }
+ else
+ {
+ blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
+ }
+ p += 4;
+ ++covers;
+ }
+ while(--len);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ if (c.a)
+ {
+ do
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
+ if(alpha == base_mask)
+ {
+ p[order_type::R] = c.r;
+ p[order_type::G] = c.g;
+ p[order_type::B] = c.b;
+ p[order_type::A] = base_mask;
+ }
+ else
+ {
+ blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
+ }
+ ++covers;
+ }
+ while(--len);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ do
+ {
+ p[order_type::R] = colors->r;
+ p[order_type::G] = colors->g;
+ p[order_type::B] = colors->b;
+ p[order_type::A] = colors->a;
+ ++colors;
+ p += 4;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ do
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ p[order_type::R] = colors->r;
+ p[order_type::G] = colors->g;
+ p[order_type::B] = colors->b;
+ p[order_type::A] = colors->a;
+ ++colors;
+ }
+ while(--len);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ if(covers)
+ {
+ do
+ {
+ cob_type::copy_or_blend_pix(p,
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a,
+ *covers++);
+ p += 4;
+ ++colors;
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ cob_type::copy_or_blend_pix(p,
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a);
+ p += 4;
+ ++colors;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ cob_type::copy_or_blend_pix(p,
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a,
+ cover);
+ p += 4;
+ ++colors;
+ }
+ while(--len);
+ }
+ }
+ }
+
+
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ value_type* p;
+ if(covers)
+ {
+ do
+ {
+ p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ cob_type::copy_or_blend_pix(p,
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a,
+ *covers++);
+ ++colors;
+ }
+ while(--len);
+ }
+ else
+ {
+ if(cover == 255)
+ {
+ do
+ {
+ p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ cob_type::copy_or_blend_pix(p,
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a);
+ ++colors;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ cob_type::copy_or_blend_pix(p,
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a,
+ cover);
+ ++colors;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class Function> void for_each_pixel(Function f)
+ {
+ unsigned y;
+ for(y = 0; y < height(); ++y)
+ {
+ row_data r = m_rbuf->row(y);
+ if(r.ptr)
+ {
+ unsigned len = r.x2 - r.x1 + 1;
+ value_type* p =
+ (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2);
+ do
+ {
+ f(p);
+ p += 4;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void premultiply()
+ {
+ for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
+ }
+
+ //--------------------------------------------------------------------
+ void demultiply()
+ {
+ for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf2> void copy_from(const RenBuf2& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len)
+ {
+ const int8u* p = from.row_ptr(ysrc);
+ if(p)
+ {
+ memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
+ p + xsrc * pix_width,
+ len * pix_width);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from(const SrcPixelFormatRenderer& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::order_type src_order;
+ const value_type* psrc = (value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ psrc += xsrc << 2;
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
+ int incp = 4;
+ if(xdst > xsrc)
+ {
+ psrc += (len-1) << 2;
+ pdst += (len-1) << 2;
+ incp = -4;
+ }
+
+ if(cover == 255)
+ {
+ do
+ {
+ cob_type::copy_or_blend_pix(pdst,
+ psrc[src_order::R],
+ psrc[src_order::G],
+ psrc[src_order::B],
+ psrc[src_order::A]);
+ psrc += incp;
+ pdst += incp;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ cob_type::copy_or_blend_pix(pdst,
+ psrc[src_order::R],
+ psrc[src_order::G],
+ psrc[src_order::B],
+ psrc[src_order::A],
+ cover);
+ psrc += incp;
+ pdst += incp;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_color(const SrcPixelFormatRenderer& from,
+ const color_type& color,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
+ do
+ {
+ cob_type::copy_or_blend_pix(pdst,
+ color.r, color.g, color.b, color.a,
+ (*psrc * cover + base_mask) >> base_shift);
+ ++psrc;
+ pdst += 4;
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_lut(const SrcPixelFormatRenderer& from,
+ const color_type* color_lut,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
+
+ if(cover == 255)
+ {
+ do
+ {
+ const color_type& color = color_lut[*psrc];
+ cob_type::copy_or_blend_pix(pdst,
+ color.r, color.g, color.b, color.a);
+ ++psrc;
+ pdst += 4;
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ const color_type& color = color_lut[*psrc];
+ cob_type::copy_or_blend_pix(pdst,
+ color.r, color.g, color.b, color.a,
+ cover);
+ ++psrc;
+ pdst += 4;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ private:
+ rbuf_type* m_rbuf;
+ };
+
+
+
+
+ //================================================pixfmt_custom_blend_rgba
+ template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba
+ {
+ public:
+ typedef RenBuf rbuf_type;
+ typedef typename rbuf_type::row_data row_data;
+ typedef Blender blender_type;
+ typedef typename blender_type::color_type color_type;
+ typedef typename blender_type::order_type order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_scale = color_type::base_scale,
+ base_mask = color_type::base_mask,
+ pix_width = sizeof(value_type) * 4
+ };
+
+
+ //--------------------------------------------------------------------
+ pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {}
+ explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) :
+ m_rbuf(&rb),
+ m_comp_op(comp_op)
+ {}
+ void attach(rbuf_type& rb) { m_rbuf = &rb; }
+
+ //--------------------------------------------------------------------
+ template<class PixFmt>
+ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
+ {
+ rect_i r(x1, y1, x2, y2);
+ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
+ {
+ int stride = pixf.stride();
+ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
+ (r.x2 - r.x1) + 1,
+ (r.y2 - r.y1) + 1,
+ stride);
+ return true;
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned width() const { return m_rbuf->width(); }
+ AGG_INLINE unsigned height() const { return m_rbuf->height(); }
+ AGG_INLINE int stride() const { return m_rbuf->stride(); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
+ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
+ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE int8u* pix_ptr(int x, int y)
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+ AGG_INLINE const int8u* pix_ptr(int x, int y) const
+ {
+ return m_rbuf->row_ptr(y) + x * pix_width;
+ }
+
+ //--------------------------------------------------------------------
+ void comp_op(unsigned op) { m_comp_op = op; }
+ unsigned comp_op() const { return m_comp_op; }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE static void make_pix(int8u* p, const color_type& c)
+ {
+ ((value_type*)p)[order_type::R] = c.r;
+ ((value_type*)p)[order_type::G] = c.g;
+ ((value_type*)p)[order_type::B] = c.b;
+ ((value_type*)p)[order_type::A] = c.a;
+ }
+
+ //--------------------------------------------------------------------
+ color_type pixel(int x, int y) const
+ {
+ const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2);
+ return color_type(p[order_type::R],
+ p[order_type::G],
+ p[order_type::B],
+ p[order_type::A]);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_pixel(int x, int y, const color_type& c)
+ {
+ blender_type::blend_pix(
+ m_comp_op,
+ (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2),
+ c.r, c.g, c.b, c.a, 255);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_pixel(int x, int y, const color_type& c, int8u cover)
+ {
+ blender_type::blend_pix(
+ m_comp_op,
+ (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2),
+ c.r, c.g, c.b, c.a,
+ cover);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_hline(int x, int y, unsigned len, const color_type& c)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);;
+ do
+ {
+ blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255);
+ p += 4;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_vline(int x, int y, unsigned len, const color_type& c)
+ {
+ do
+ {
+ blender_type::blend_pix(
+ m_comp_op,
+ (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
+ c.r, c.g, c.b, c.a, 255);
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x, int y, unsigned len,
+ const color_type& c, int8u cover)
+ {
+
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ do
+ {
+ blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover);
+ p += 4;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y, unsigned len,
+ const color_type& c, int8u cover)
+ {
+
+ do
+ {
+ blender_type::blend_pix(
+ m_comp_op,
+ (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
+ c.r, c.g, c.b, c.a,
+ cover);
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y, unsigned len,
+ const color_type& c, const int8u* covers)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ do
+ {
+ blender_type::blend_pix(m_comp_op,
+ p, c.r, c.g, c.b, c.a,
+ *covers++);
+ p += 4;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y, unsigned len,
+ const color_type& c, const int8u* covers)
+ {
+ do
+ {
+ blender_type::blend_pix(
+ m_comp_op,
+ (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
+ c.r, c.g, c.b, c.a,
+ *covers++);
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ do
+ {
+ p[order_type::R] = colors->r;
+ p[order_type::G] = colors->g;
+ p[order_type::B] = colors->b;
+ p[order_type::A] = colors->a;
+ ++colors;
+ p += 4;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ do
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
+ p[order_type::R] = colors->r;
+ p[order_type::G] = colors->g;
+ p[order_type::B] = colors->b;
+ p[order_type::A] = colors->a;
+ ++colors;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y, unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
+ do
+ {
+ blender_type::blend_pix(m_comp_op,
+ p,
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a,
+ covers ? *covers++ : cover);
+ p += 4;
+ ++colors;
+ }
+ while(--len);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y, unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ do
+ {
+ blender_type::blend_pix(
+ m_comp_op,
+ (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
+ colors->r,
+ colors->g,
+ colors->b,
+ colors->a,
+ covers ? *covers++ : cover);
+ ++colors;
+ }
+ while(--len);
+
+ }
+
+ //--------------------------------------------------------------------
+ template<class Function> void for_each_pixel(Function f)
+ {
+ unsigned y;
+ for(y = 0; y < height(); ++y)
+ {
+ row_data r = m_rbuf->row(y);
+ if(r.ptr)
+ {
+ unsigned len = r.x2 - r.x1 + 1;
+ value_type* p =
+ (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2);
+ do
+ {
+ f(p);
+ p += 4;
+ }
+ while(--len);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void premultiply()
+ {
+ for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
+ }
+
+ //--------------------------------------------------------------------
+ void demultiply()
+ {
+ for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
+ {
+ for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
+ }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf2> void copy_from(const RenBuf2& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len)
+ {
+ const int8u* p = from.row_ptr(ysrc);
+ if(p)
+ {
+ memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
+ p + xsrc * pix_width,
+ len * pix_width);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from(const SrcPixelFormatRenderer& from,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::order_type src_order;
+ const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ psrc += xsrc << 2;
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
+
+ int incp = 4;
+ if(xdst > xsrc)
+ {
+ psrc += (len-1) << 2;
+ pdst += (len-1) << 2;
+ incp = -4;
+ }
+
+ do
+ {
+ blender_type::blend_pix(m_comp_op,
+ pdst,
+ psrc[src_order::R],
+ psrc[src_order::G],
+ psrc[src_order::B],
+ psrc[src_order::A],
+ cover);
+ psrc += incp;
+ pdst += incp;
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_color(const SrcPixelFormatRenderer& from,
+ const color_type& color,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
+ do
+ {
+ blender_type::blend_pix(m_comp_op,
+ pdst,
+ color.r, color.g, color.b, color.a,
+ (*psrc * cover + base_mask) >> base_shift);
+ ++psrc;
+ pdst += 4;
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_lut(const SrcPixelFormatRenderer& from,
+ const color_type* color_lut,
+ int xdst, int ydst,
+ int xsrc, int ysrc,
+ unsigned len,
+ int8u cover)
+ {
+ typedef typename SrcPixelFormatRenderer::value_type src_value_type;
+ const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
+ if(psrc)
+ {
+ value_type* pdst =
+ (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
+ do
+ {
+ const color_type& color = color_lut[*psrc];
+ blender_type::blend_pix(m_comp_op,
+ pdst,
+ color.r, color.g, color.b, color.a,
+ cover);
+ ++psrc;
+ pdst += 4;
+ }
+ while(--len);
+ }
+ }
+
+ private:
+ rbuf_type* m_rbuf;
+ unsigned m_comp_op;
+ };
+
+
+
+
+ //-----------------------------------------------------------------------
+ typedef blender_rgba<rgba8, order_rgba> blender_rgba32; //----blender_rgba32
+ typedef blender_rgba<rgba8, order_argb> blender_argb32; //----blender_argb32
+ typedef blender_rgba<rgba8, order_abgr> blender_abgr32; //----blender_abgr32
+ typedef blender_rgba<rgba8, order_bgra> blender_bgra32; //----blender_bgra32
+
+ typedef blender_rgba_pre<rgba8, order_rgba> blender_rgba32_pre; //----blender_rgba32_pre
+ typedef blender_rgba_pre<rgba8, order_argb> blender_argb32_pre; //----blender_argb32_pre
+ typedef blender_rgba_pre<rgba8, order_abgr> blender_abgr32_pre; //----blender_abgr32_pre
+ typedef blender_rgba_pre<rgba8, order_bgra> blender_bgra32_pre; //----blender_bgra32_pre
+
+ typedef blender_rgba_plain<rgba8, order_rgba> blender_rgba32_plain; //----blender_rgba32_plain
+ typedef blender_rgba_plain<rgba8, order_argb> blender_argb32_plain; //----blender_argb32_plain
+ typedef blender_rgba_plain<rgba8, order_abgr> blender_abgr32_plain; //----blender_abgr32_plain
+ typedef blender_rgba_plain<rgba8, order_bgra> blender_bgra32_plain; //----blender_bgra32_plain
+
+ typedef blender_rgba<rgba16, order_rgba> blender_rgba64; //----blender_rgba64
+ typedef blender_rgba<rgba16, order_argb> blender_argb64; //----blender_argb64
+ typedef blender_rgba<rgba16, order_abgr> blender_abgr64; //----blender_abgr64
+ typedef blender_rgba<rgba16, order_bgra> blender_bgra64; //----blender_bgra64
+
+ typedef blender_rgba_pre<rgba16, order_rgba> blender_rgba64_pre; //----blender_rgba64_pre
+ typedef blender_rgba_pre<rgba16, order_argb> blender_argb64_pre; //----blender_argb64_pre
+ typedef blender_rgba_pre<rgba16, order_abgr> blender_abgr64_pre; //----blender_abgr64_pre
+ typedef blender_rgba_pre<rgba16, order_bgra> blender_bgra64_pre; //----blender_bgra64_pre
+
+
+ //-----------------------------------------------------------------------
+ typedef int32u pixel32_type;
+ typedef pixfmt_alpha_blend_rgba<blender_rgba32, rendering_buffer, pixel32_type> pixfmt_rgba32; //----pixfmt_rgba32
+ typedef pixfmt_alpha_blend_rgba<blender_argb32, rendering_buffer, pixel32_type> pixfmt_argb32; //----pixfmt_argb32
+ typedef pixfmt_alpha_blend_rgba<blender_abgr32, rendering_buffer, pixel32_type> pixfmt_abgr32; //----pixfmt_abgr32
+ typedef pixfmt_alpha_blend_rgba<blender_bgra32, rendering_buffer, pixel32_type> pixfmt_bgra32; //----pixfmt_bgra32
+
+ typedef pixfmt_alpha_blend_rgba<blender_rgba32_pre, rendering_buffer, pixel32_type> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre
+ typedef pixfmt_alpha_blend_rgba<blender_argb32_pre, rendering_buffer, pixel32_type> pixfmt_argb32_pre; //----pixfmt_argb32_pre
+ typedef pixfmt_alpha_blend_rgba<blender_abgr32_pre, rendering_buffer, pixel32_type> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre
+ typedef pixfmt_alpha_blend_rgba<blender_bgra32_pre, rendering_buffer, pixel32_type> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre
+
+ typedef pixfmt_alpha_blend_rgba<blender_rgba32_plain, rendering_buffer, pixel32_type> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain
+ typedef pixfmt_alpha_blend_rgba<blender_argb32_plain, rendering_buffer, pixel32_type> pixfmt_argb32_plain; //----pixfmt_argb32_plain
+ typedef pixfmt_alpha_blend_rgba<blender_abgr32_plain, rendering_buffer, pixel32_type> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain
+ typedef pixfmt_alpha_blend_rgba<blender_bgra32_plain, rendering_buffer, pixel32_type> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain
+
+ struct pixel64_type { int16u c[4]; };
+ typedef pixfmt_alpha_blend_rgba<blender_rgba64, rendering_buffer, pixel64_type> pixfmt_rgba64; //----pixfmt_rgba64
+ typedef pixfmt_alpha_blend_rgba<blender_argb64, rendering_buffer, pixel64_type> pixfmt_argb64; //----pixfmt_argb64
+ typedef pixfmt_alpha_blend_rgba<blender_abgr64, rendering_buffer, pixel64_type> pixfmt_abgr64; //----pixfmt_abgr64
+ typedef pixfmt_alpha_blend_rgba<blender_bgra64, rendering_buffer, pixel64_type> pixfmt_bgra64; //----pixfmt_bgra64
+
+ typedef pixfmt_alpha_blend_rgba<blender_rgba64_pre, rendering_buffer, pixel64_type> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre
+ typedef pixfmt_alpha_blend_rgba<blender_argb64_pre, rendering_buffer, pixel64_type> pixfmt_argb64_pre; //----pixfmt_argb64_pre
+ typedef pixfmt_alpha_blend_rgba<blender_abgr64_pre, rendering_buffer, pixel64_type> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre
+ typedef pixfmt_alpha_blend_rgba<blender_bgra64_pre, rendering_buffer, pixel64_type> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_pixfmt_transposer.h b/plugins/Clist_ng/AGG/include/agg_pixfmt_transposer.h new file mode 100644 index 0000000000..c5038d49ff --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_pixfmt_transposer.h @@ -0,0 +1,166 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_PIXFMT_TRANSPOSER_INCLUDED
+#define AGG_PIXFMT_TRANSPOSER_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //=======================================================pixfmt_transposer
+ template<class PixFmt> class pixfmt_transposer
+ {
+ public:
+ typedef PixFmt pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::row_data row_data;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+
+ //--------------------------------------------------------------------
+ pixfmt_transposer() : m_pixf(0) {}
+ explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {}
+ void attach(pixfmt_type& pixf) { m_pixf = &pixf; }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned width() const { return m_pixf->height(); }
+ AGG_INLINE unsigned height() const { return m_pixf->width(); }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE color_type pixel(int x, int y) const
+ {
+ return m_pixf->pixel(y, x);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
+ {
+ m_pixf->copy_pixel(y, x, c);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pixel(int x, int y,
+ const color_type& c,
+ int8u cover)
+ {
+ m_pixf->blend_pixel(y, x, c, cover);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_hline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ m_pixf->copy_vline(y, x, len, c);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_vline(int x, int y,
+ unsigned len,
+ const color_type& c)
+ {
+ m_pixf->copy_hline(y, x, len, c);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_hline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ m_pixf->blend_vline(y, x, len, c, cover);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_vline(int x, int y,
+ unsigned len,
+ const color_type& c,
+ int8u cover)
+ {
+ m_pixf->blend_hline(y, x, len, c, cover);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_solid_hspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ m_pixf->blend_solid_vspan(y, x, len, c, covers);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_solid_vspan(int x, int y,
+ unsigned len,
+ const color_type& c,
+ const int8u* covers)
+ {
+ m_pixf->blend_solid_hspan(y, x, len, c, covers);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ m_pixf->copy_color_vspan(y, x, len, colors);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors)
+ {
+ m_pixf->copy_color_hspan(y, x, len, colors);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_color_hspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ m_pixf->blend_color_vspan(y, x, len, colors, covers, cover);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_color_vspan(int x, int y,
+ unsigned len,
+ const color_type* colors,
+ const int8u* covers,
+ int8u cover)
+ {
+ m_pixf->blend_color_hspan(y, x, len, colors, covers, cover);
+ }
+
+ private:
+ pixfmt_type* m_pixf;
+ };
+}
+
+#endif
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_rasterizer_cells_aa.h b/plugins/Clist_ng/AGG/include/agg_rasterizer_cells_aa.h new file mode 100644 index 0000000000..789f2b7870 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rasterizer_cells_aa.h @@ -0,0 +1,764 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// The author gratefully acknowleges the support of David Turner,
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
+// libray - in producing this work. See http://www.freetype.org for details.
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED
+#define AGG_RASTERIZER_CELLS_AA_INCLUDED
+
+#include <string.h>
+#include <math.h>
+#include "agg_math.h"
+#include "agg_array.h"
+
+
+namespace agg
+{
+
+ //-----------------------------------------------------rasterizer_cells_aa
+ // An internal class that implements the main rasterization algorithm.
+ // Used in the rasterizer. Should not be used direcly.
+ template<class Cell> class rasterizer_cells_aa
+ {
+ enum cell_block_scale_e
+ {
+ cell_block_shift = 12,
+ cell_block_size = 1 << cell_block_shift,
+ cell_block_mask = cell_block_size - 1,
+ cell_block_pool = 256,
+ cell_block_limit = 1024
+ };
+
+ struct sorted_y
+ {
+ unsigned start;
+ unsigned num;
+ };
+
+ public:
+ typedef Cell cell_type;
+ typedef rasterizer_cells_aa<Cell> self_type;
+
+ ~rasterizer_cells_aa();
+ rasterizer_cells_aa();
+
+ void reset();
+ void style(const cell_type& style_cell);
+ void line(int x1, int y1, int x2, int y2);
+
+ int min_x() const { return m_min_x; }
+ int min_y() const { return m_min_y; }
+ int max_x() const { return m_max_x; }
+ int max_y() const { return m_max_y; }
+
+ void sort_cells();
+
+ unsigned total_cells() const
+ {
+ return m_num_cells;
+ }
+
+ unsigned scanline_num_cells(unsigned y) const
+ {
+ return m_sorted_y[y - m_min_y].num;
+ }
+
+ const cell_type* const* scanline_cells(unsigned y) const
+ {
+ return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start;
+ }
+
+ bool sorted() const { return m_sorted; }
+
+ private:
+ rasterizer_cells_aa(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ void set_curr_cell(int x, int y);
+ void add_curr_cell();
+ void render_hline(int ey, int x1, int y1, int x2, int y2);
+ void allocate_block();
+
+ private:
+ unsigned m_num_blocks;
+ unsigned m_max_blocks;
+ unsigned m_curr_block;
+ unsigned m_num_cells;
+ cell_type** m_cells;
+ cell_type* m_curr_cell_ptr;
+ pod_vector<cell_type*> m_sorted_cells;
+ pod_vector<sorted_y> m_sorted_y;
+ cell_type m_curr_cell;
+ cell_type m_style_cell;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+ bool m_sorted;
+ };
+
+
+
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ rasterizer_cells_aa<Cell>::~rasterizer_cells_aa()
+ {
+ if(m_num_blocks)
+ {
+ cell_type** ptr = m_cells + m_num_blocks - 1;
+ while(m_num_blocks--)
+ {
+ pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
+ ptr--;
+ }
+ pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ rasterizer_cells_aa<Cell>::rasterizer_cells_aa() :
+ m_num_blocks(0),
+ m_max_blocks(0),
+ m_curr_block(0),
+ m_num_cells(0),
+ m_cells(0),
+ m_curr_cell_ptr(0),
+ m_sorted_cells(),
+ m_sorted_y(),
+ m_min_x(0x7FFFFFFF),
+ m_min_y(0x7FFFFFFF),
+ m_max_x(-0x7FFFFFFF),
+ m_max_y(-0x7FFFFFFF),
+ m_sorted(false)
+ {
+ m_style_cell.initial();
+ m_curr_cell.initial();
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ void rasterizer_cells_aa<Cell>::reset()
+ {
+ m_num_cells = 0;
+ m_curr_block = 0;
+ m_curr_cell.initial();
+ m_style_cell.initial();
+ m_sorted = false;
+ m_min_x = 0x7FFFFFFF;
+ m_min_y = 0x7FFFFFFF;
+ m_max_x = -0x7FFFFFFF;
+ m_max_y = -0x7FFFFFFF;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell()
+ {
+ if(m_curr_cell.area | m_curr_cell.cover)
+ {
+ if((m_num_cells & cell_block_mask) == 0)
+ {
+ if(m_num_blocks >= cell_block_limit) return;
+ allocate_block();
+ }
+ *m_curr_cell_ptr++ = m_curr_cell;
+ ++m_num_cells;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y)
+ {
+ if(m_curr_cell.not_equal(x, y, m_style_cell))
+ {
+ add_curr_cell();
+ m_curr_cell.style(m_style_cell);
+ m_curr_cell.x = x;
+ m_curr_cell.y = y;
+ m_curr_cell.cover = 0;
+ m_curr_cell.area = 0;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey,
+ int x1, int y1,
+ int x2, int y2)
+ {
+ int ex1 = x1 >> poly_subpixel_shift;
+ int ex2 = x2 >> poly_subpixel_shift;
+ int fx1 = x1 & poly_subpixel_mask;
+ int fx2 = x2 & poly_subpixel_mask;
+
+ int delta, p, first, dx;
+ int incr, lift, mod, rem;
+
+ //trivial case. Happens often
+ if(y1 == y2)
+ {
+ set_curr_cell(ex2, ey);
+ return;
+ }
+
+ //everything is located in a single cell. That is easy!
+ if(ex1 == ex2)
+ {
+ delta = y2 - y1;
+ m_curr_cell.cover += delta;
+ m_curr_cell.area += (fx1 + fx2) * delta;
+ return;
+ }
+
+ //ok, we'll have to render a run of adjacent cells on the same
+ //hline...
+ p = (poly_subpixel_scale - fx1) * (y2 - y1);
+ first = poly_subpixel_scale;
+ incr = 1;
+
+ dx = x2 - x1;
+
+ if(dx < 0)
+ {
+ p = fx1 * (y2 - y1);
+ first = 0;
+ incr = -1;
+ dx = -dx;
+ }
+
+ delta = p / dx;
+ mod = p % dx;
+
+ if(mod < 0)
+ {
+ delta--;
+ mod += dx;
+ }
+
+ m_curr_cell.cover += delta;
+ m_curr_cell.area += (fx1 + first) * delta;
+
+ ex1 += incr;
+ set_curr_cell(ex1, ey);
+ y1 += delta;
+
+ if(ex1 != ex2)
+ {
+ p = poly_subpixel_scale * (y2 - y1 + delta);
+ lift = p / dx;
+ rem = p % dx;
+
+ if (rem < 0)
+ {
+ lift--;
+ rem += dx;
+ }
+
+ mod -= dx;
+
+ while (ex1 != ex2)
+ {
+ delta = lift;
+ mod += rem;
+ if(mod >= 0)
+ {
+ mod -= dx;
+ delta++;
+ }
+
+ m_curr_cell.cover += delta;
+ m_curr_cell.area += poly_subpixel_scale * delta;
+ y1 += delta;
+ ex1 += incr;
+ set_curr_cell(ex1, ey);
+ }
+ }
+ delta = y2 - y1;
+ m_curr_cell.cover += delta;
+ m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell)
+ {
+ m_style_cell.style(style_cell);
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2)
+ {
+ enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
+
+ int dx = x2 - x1;
+
+ if(dx >= dx_limit || dx <= -dx_limit)
+ {
+ int cx = (x1 + x2) >> 1;
+ int cy = (y1 + y2) >> 1;
+ line(x1, y1, cx, cy);
+ line(cx, cy, x2, y2);
+ }
+
+ int dy = y2 - y1;
+ int ex1 = x1 >> poly_subpixel_shift;
+ int ex2 = x2 >> poly_subpixel_shift;
+ int ey1 = y1 >> poly_subpixel_shift;
+ int ey2 = y2 >> poly_subpixel_shift;
+ int fy1 = y1 & poly_subpixel_mask;
+ int fy2 = y2 & poly_subpixel_mask;
+
+ int x_from, x_to;
+ int p, rem, mod, lift, delta, first, incr;
+
+ if(ex1 < m_min_x) m_min_x = ex1;
+ if(ex1 > m_max_x) m_max_x = ex1;
+ if(ey1 < m_min_y) m_min_y = ey1;
+ if(ey1 > m_max_y) m_max_y = ey1;
+ if(ex2 < m_min_x) m_min_x = ex2;
+ if(ex2 > m_max_x) m_max_x = ex2;
+ if(ey2 < m_min_y) m_min_y = ey2;
+ if(ey2 > m_max_y) m_max_y = ey2;
+
+ set_curr_cell(ex1, ey1);
+
+ //everything is on a single hline
+ if(ey1 == ey2)
+ {
+ render_hline(ey1, x1, fy1, x2, fy2);
+ return;
+ }
+
+ //Vertical line - we have to calculate start and end cells,
+ //and then - the common values of the area and coverage for
+ //all cells of the line. We know exactly there's only one
+ //cell, so, we don't have to call render_hline().
+ incr = 1;
+ if(dx == 0)
+ {
+ int ex = x1 >> poly_subpixel_shift;
+ int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1;
+ int area;
+
+ first = poly_subpixel_scale;
+ if(dy < 0)
+ {
+ first = 0;
+ incr = -1;
+ }
+
+ x_from = x1;
+
+ //render_hline(ey1, x_from, fy1, x_from, first);
+ delta = first - fy1;
+ m_curr_cell.cover += delta;
+ m_curr_cell.area += two_fx * delta;
+
+ ey1 += incr;
+ set_curr_cell(ex, ey1);
+
+ delta = first + first - poly_subpixel_scale;
+ area = two_fx * delta;
+ while(ey1 != ey2)
+ {
+ //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first);
+ m_curr_cell.cover = delta;
+ m_curr_cell.area = area;
+ ey1 += incr;
+ set_curr_cell(ex, ey1);
+ }
+ //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2);
+ delta = fy2 - poly_subpixel_scale + first;
+ m_curr_cell.cover += delta;
+ m_curr_cell.area += two_fx * delta;
+ return;
+ }
+
+ //ok, we have to render several hlines
+ p = (poly_subpixel_scale - fy1) * dx;
+ first = poly_subpixel_scale;
+
+ if(dy < 0)
+ {
+ p = fy1 * dx;
+ first = 0;
+ incr = -1;
+ dy = -dy;
+ }
+
+ delta = p / dy;
+ mod = p % dy;
+
+ if(mod < 0)
+ {
+ delta--;
+ mod += dy;
+ }
+
+ x_from = x1 + delta;
+ render_hline(ey1, x1, fy1, x_from, first);
+
+ ey1 += incr;
+ set_curr_cell(x_from >> poly_subpixel_shift, ey1);
+
+ if(ey1 != ey2)
+ {
+ p = poly_subpixel_scale * dx;
+ lift = p / dy;
+ rem = p % dy;
+
+ if(rem < 0)
+ {
+ lift--;
+ rem += dy;
+ }
+ mod -= dy;
+
+ while(ey1 != ey2)
+ {
+ delta = lift;
+ mod += rem;
+ if (mod >= 0)
+ {
+ mod -= dy;
+ delta++;
+ }
+
+ x_to = x_from + delta;
+ render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first);
+ x_from = x_to;
+
+ ey1 += incr;
+ set_curr_cell(x_from >> poly_subpixel_shift, ey1);
+ }
+ }
+ render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2);
+ }
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ void rasterizer_cells_aa<Cell>::allocate_block()
+ {
+ if(m_curr_block >= m_num_blocks)
+ {
+ if(m_num_blocks >= m_max_blocks)
+ {
+ cell_type** new_cells =
+ pod_allocator<cell_type*>::allocate(m_max_blocks +
+ cell_block_pool);
+
+ if(m_cells)
+ {
+ memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*));
+ pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
+ }
+ m_cells = new_cells;
+ m_max_blocks += cell_block_pool;
+ }
+
+ m_cells[m_num_blocks++] =
+ pod_allocator<cell_type>::allocate(cell_block_size);
+
+ }
+ m_curr_cell_ptr = m_cells[m_curr_block++];
+ }
+
+
+
+ //------------------------------------------------------------------------
+ template <class T> static AGG_INLINE void swap_cells(T* a, T* b)
+ {
+ T temp = *a;
+ *a = *b;
+ *b = temp;
+ }
+
+
+ //------------------------------------------------------------------------
+ enum
+ {
+ qsort_threshold = 9
+ };
+
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ void qsort_cells(Cell** start, unsigned num)
+ {
+ Cell** stack[80];
+ Cell*** top;
+ Cell** limit;
+ Cell** base;
+
+ limit = start + num;
+ base = start;
+ top = stack;
+
+ for (;;)
+ {
+ int len = int(limit - base);
+
+ Cell** i;
+ Cell** j;
+ Cell** pivot;
+
+ if(len > qsort_threshold)
+ {
+ // we use base + len/2 as the pivot
+ pivot = base + len / 2;
+ swap_cells(base, pivot);
+
+ i = base + 1;
+ j = limit - 1;
+
+ // now ensure that *i <= *base <= *j
+ if((*j)->x < (*i)->x)
+ {
+ swap_cells(i, j);
+ }
+
+ if((*base)->x < (*i)->x)
+ {
+ swap_cells(base, i);
+ }
+
+ if((*j)->x < (*base)->x)
+ {
+ swap_cells(base, j);
+ }
+
+ for(;;)
+ {
+ int x = (*base)->x;
+ do i++; while( (*i)->x < x );
+ do j--; while( x < (*j)->x );
+
+ if(i > j)
+ {
+ break;
+ }
+
+ swap_cells(i, j);
+ }
+
+ swap_cells(base, j);
+
+ // now, push the largest sub-array
+ if(j - base > limit - i)
+ {
+ top[0] = base;
+ top[1] = j;
+ base = i;
+ }
+ else
+ {
+ top[0] = i;
+ top[1] = limit;
+ limit = j;
+ }
+ top += 2;
+ }
+ else
+ {
+ // the sub-array is small, perform insertion sort
+ j = base;
+ i = j + 1;
+
+ for(; i < limit; j = i, i++)
+ {
+ for(; j[1]->x < (*j)->x; j--)
+ {
+ swap_cells(j + 1, j);
+ if (j == base)
+ {
+ break;
+ }
+ }
+ }
+
+ if(top > stack)
+ {
+ top -= 2;
+ base = top[0];
+ limit = top[1];
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class Cell>
+ void rasterizer_cells_aa<Cell>::sort_cells()
+ {
+ if(m_sorted) return; //Perform sort only the first time.
+
+ add_curr_cell();
+ m_curr_cell.x = 0x7FFFFFFF;
+ m_curr_cell.y = 0x7FFFFFFF;
+ m_curr_cell.cover = 0;
+ m_curr_cell.area = 0;
+
+ if(m_num_cells == 0) return;
+
+// DBG: Check to see if min/max works well.
+//for(unsigned nc = 0; nc < m_num_cells; nc++)
+//{
+// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask);
+// if(cell->x < m_min_x ||
+// cell->y < m_min_y ||
+// cell->x > m_max_x ||
+// cell->y > m_max_y)
+// {
+// cell = cell; // Breakpoint here
+// }
+//}
+ // Allocate the array of cell pointers
+ m_sorted_cells.allocate(m_num_cells, 16);
+
+ // Allocate and zero the Y array
+ m_sorted_y.allocate(m_max_y - m_min_y + 1, 16);
+ m_sorted_y.zero();
+
+ // Create the Y-histogram (count the numbers of cells for each Y)
+ cell_type** block_ptr = m_cells;
+ cell_type* cell_ptr;
+ unsigned nb = m_num_cells >> cell_block_shift;
+ unsigned i;
+ while(nb--)
+ {
+ cell_ptr = *block_ptr++;
+ i = cell_block_size;
+ while(i--)
+ {
+ m_sorted_y[cell_ptr->y - m_min_y].start++;
+ ++cell_ptr;
+ }
+ }
+
+ cell_ptr = *block_ptr++;
+ i = m_num_cells & cell_block_mask;
+ while(i--)
+ {
+ m_sorted_y[cell_ptr->y - m_min_y].start++;
+ ++cell_ptr;
+ }
+
+ // Convert the Y-histogram into the array of starting indexes
+ unsigned start = 0;
+ for(i = 0; i < m_sorted_y.size(); i++)
+ {
+ unsigned v = m_sorted_y[i].start;
+ m_sorted_y[i].start = start;
+ start += v;
+ }
+
+ // Fill the cell pointer array sorted by Y
+ block_ptr = m_cells;
+ nb = m_num_cells >> cell_block_shift;
+ while(nb--)
+ {
+ cell_ptr = *block_ptr++;
+ i = cell_block_size;
+ while(i--)
+ {
+ sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
+ m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
+ ++curr_y.num;
+ ++cell_ptr;
+ }
+ }
+
+ cell_ptr = *block_ptr++;
+ i = m_num_cells & cell_block_mask;
+ while(i--)
+ {
+ sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
+ m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
+ ++curr_y.num;
+ ++cell_ptr;
+ }
+
+ // Finally arrange the X-arrays
+ for(i = 0; i < m_sorted_y.size(); i++)
+ {
+ const sorted_y& curr_y = m_sorted_y[i];
+ if(curr_y.num)
+ {
+ qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num);
+ }
+ }
+ m_sorted = true;
+ }
+
+
+
+ //------------------------------------------------------scanline_hit_test
+ class scanline_hit_test
+ {
+ public:
+ scanline_hit_test(int x) : m_x(x), m_hit(false) {}
+
+ void reset_spans() {}
+ void finalize(int) {}
+ void add_cell(int x, int)
+ {
+ if(m_x == x) m_hit = true;
+ }
+ void add_span(int x, int len, int)
+ {
+ if(m_x >= x && m_x < x+len) m_hit = true;
+ }
+ unsigned num_spans() const { return 1; }
+ bool hit() const { return m_hit; }
+
+ private:
+ int m_x;
+ bool m_hit;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_rasterizer_compound_aa.h b/plugins/Clist_ng/AGG/include/agg_rasterizer_compound_aa.h new file mode 100644 index 0000000000..c37b031c5b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rasterizer_compound_aa.h @@ -0,0 +1,698 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.3
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+//
+// The author gratefully acknowleges the support of David Turner,
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
+// libray - in producing this work. See http://www.freetype.org for details.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+#ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED
+#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED
+
+#include "agg_rasterizer_cells_aa.h"
+#include "agg_rasterizer_sl_clip.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------------------cell_style_aa
+ // A pixel cell. There're no constructors defined and it was done
+ // intentionally in order to avoid extra overhead when allocating an
+ // array of cells.
+ struct cell_style_aa
+ {
+ int x;
+ int y;
+ int cover;
+ int area;
+ int16 left, right;
+
+ void initial()
+ {
+ x = 0x7FFFFFFF;
+ y = 0x7FFFFFFF;
+ cover = 0;
+ area = 0;
+ left = -1;
+ right = -1;
+ }
+
+ void style(const cell_style_aa& c)
+ {
+ left = c.left;
+ right = c.right;
+ }
+
+ int not_equal(int ex, int ey, const cell_style_aa& c) const
+ {
+ return (ex - x) | (ey - y) | (left - c.left) | (right - c.right);
+ }
+ };
+
+
+ //===========================================================layer_order_e
+ enum layer_order_e
+ {
+ layer_unsorted, //------layer_unsorted
+ layer_direct, //------layer_direct
+ layer_inverse //------layer_inverse
+ };
+
+
+ //==================================================rasterizer_compound_aa
+ template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa
+ {
+ struct style_info
+ {
+ unsigned start_cell;
+ unsigned num_cells;
+ int last_x;
+ };
+
+ struct cell_info
+ {
+ int x, area, cover;
+ };
+
+ public:
+ typedef Clip clip_type;
+ typedef typename Clip::conv_type conv_type;
+ typedef typename Clip::coord_type coord_type;
+
+ enum aa_scale_e
+ {
+ aa_shift = 8,
+ aa_scale = 1 << aa_shift,
+ aa_mask = aa_scale - 1,
+ aa_scale2 = aa_scale * 2,
+ aa_mask2 = aa_scale2 - 1
+ };
+
+ //--------------------------------------------------------------------
+ rasterizer_compound_aa() :
+ m_outline(),
+ m_clipper(),
+ m_filling_rule(fill_non_zero),
+ m_layer_order(layer_direct),
+ m_styles(), // Active Styles
+ m_ast(), // Active Style Table (unique values)
+ m_asm(), // Active Style Mask
+ m_cells(),
+ m_cover_buf(),
+ m_master_alpha(),
+ m_min_style(0x7FFFFFFF),
+ m_max_style(-0x7FFFFFFF),
+ m_start_x(0),
+ m_start_y(0),
+ m_scan_y(0x7FFFFFFF),
+ m_sl_start(0),
+ m_sl_len(0)
+ {}
+
+ //--------------------------------------------------------------------
+ void reset();
+ void reset_clipping();
+ void clip_box(double x1, double y1, double x2, double y2);
+ void filling_rule(filling_rule_e filling_rule);
+ void layer_order(layer_order_e order);
+ void master_alpha(int style, double alpha);
+
+ //--------------------------------------------------------------------
+ void styles(int left, int right);
+ void move_to(int x, int y);
+ void line_to(int x, int y);
+ void move_to_d(double x, double y);
+ void line_to_d(double x, double y);
+ void add_vertex(double x, double y, unsigned cmd);
+
+ void edge(int x1, int y1, int x2, int y2);
+ void edge_d(double x1, double y1, double x2, double y2);
+
+ //-------------------------------------------------------------------
+ template<class VertexSource>
+ void add_path(VertexSource& vs, unsigned path_id=0)
+ {
+ double x;
+ double y;
+
+ unsigned cmd;
+ vs.rewind(path_id);
+ if(m_outline.sorted()) reset();
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ add_vertex(x, y, cmd);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ int min_x() const { return m_outline.min_x(); }
+ int min_y() const { return m_outline.min_y(); }
+ int max_x() const { return m_outline.max_x(); }
+ int max_y() const { return m_outline.max_y(); }
+ int min_style() const { return m_min_style; }
+ int max_style() const { return m_max_style; }
+
+ //--------------------------------------------------------------------
+ void sort();
+ bool rewind_scanlines();
+ unsigned sweep_styles();
+ int scanline_start() const { return m_sl_start; }
+ unsigned scanline_length() const { return m_sl_len; }
+ unsigned style(unsigned style_idx) const;
+
+ cover_type* allocate_cover_buffer(unsigned len);
+
+ //--------------------------------------------------------------------
+ bool navigate_scanline(int y);
+ bool hit_test(int tx, int ty);
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned calculate_alpha(int area, unsigned master_alpha) const
+ {
+ int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
+ if(cover < 0) cover = -cover;
+ if(m_filling_rule == fill_even_odd)
+ {
+ cover &= aa_mask2;
+ if(cover > aa_scale)
+ {
+ cover = aa_scale2 - cover;
+ }
+ }
+ if(cover > aa_mask) cover = aa_mask;
+ return (cover * master_alpha + aa_mask) >> aa_shift;
+ }
+
+ //--------------------------------------------------------------------
+ // Sweeps one scanline with one style index. The style ID can be
+ // determined by calling style().
+ template<class Scanline> bool sweep_scanline(Scanline& sl, int style_idx)
+ {
+ int scan_y = m_scan_y - 1;
+ if(scan_y > m_outline.max_y()) return false;
+
+ sl.reset_spans();
+
+ unsigned master_alpha = aa_mask;
+
+ if(style_idx < 0)
+ {
+ style_idx = 0;
+ }
+ else
+ {
+ style_idx++;
+ master_alpha = m_master_alpha[m_ast[style_idx] + m_min_style - 1];
+ }
+
+ const style_info& st = m_styles[m_ast[style_idx]];
+
+ unsigned num_cells = st.num_cells;
+ cell_info* cell = &m_cells[st.start_cell];
+
+ int cover = 0;
+ while(num_cells--)
+ {
+ unsigned alpha;
+ int x = cell->x;
+ int area = cell->area;
+
+ cover += cell->cover;
+
+ ++cell;
+
+ if(area)
+ {
+ alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area,
+ master_alpha);
+ sl.add_cell(x, alpha);
+ x++;
+ }
+
+ if(num_cells && cell->x > x)
+ {
+ alpha = calculate_alpha(cover << (poly_subpixel_shift + 1),
+ master_alpha);
+ if(alpha)
+ {
+ sl.add_span(x, cell->x - x, alpha);
+ }
+ }
+ }
+
+ if(sl.num_spans() == 0) return false;
+ sl.finalize(scan_y);
+ return true;
+ }
+
+ private:
+ void add_style(int style_id);
+ void allocate_master_alpha();
+
+ //--------------------------------------------------------------------
+ // Disable copying
+ rasterizer_compound_aa(const rasterizer_compound_aa<Clip>&);
+ const rasterizer_compound_aa<Clip>&
+ operator = (const rasterizer_compound_aa<Clip>&);
+
+ private:
+ rasterizer_cells_aa<cell_style_aa> m_outline;
+ clip_type m_clipper;
+ filling_rule_e m_filling_rule;
+ layer_order_e m_layer_order;
+ pod_vector<style_info> m_styles; // Active Styles
+ pod_vector<unsigned> m_ast; // Active Style Table (unique values)
+ pod_vector<int8u> m_asm; // Active Style Mask
+ pod_vector<cell_info> m_cells;
+ pod_vector<cover_type> m_cover_buf;
+ pod_bvector<unsigned> m_master_alpha;
+
+ int m_min_style;
+ int m_max_style;
+ coord_type m_start_x;
+ coord_type m_start_y;
+ int m_scan_y;
+ int m_sl_start;
+ unsigned m_sl_len;
+ };
+
+
+
+
+
+
+
+
+
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::reset()
+ {
+ m_outline.reset();
+ m_min_style = 0x7FFFFFFF;
+ m_max_style = -0x7FFFFFFF;
+ m_scan_y = 0x7FFFFFFF;
+ m_sl_start = 0;
+ m_sl_len = 0;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::filling_rule(filling_rule_e filling_rule)
+ {
+ m_filling_rule = filling_rule;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order)
+ {
+ m_layer_order = order;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1,
+ double x2, double y2)
+ {
+ reset();
+ m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
+ conv_type::upscale(x2), conv_type::upscale(y2));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::reset_clipping()
+ {
+ reset();
+ m_clipper.reset_clipping();
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::styles(int left, int right)
+ {
+ cell_style_aa cell;
+ cell.initial();
+ cell.left = (int16)left;
+ cell.right = (int16)right;
+ m_outline.style(cell);
+ if(left >= 0 && left < m_min_style) m_min_style = left;
+ if(left >= 0 && left > m_max_style) m_max_style = left;
+ if(right >= 0 && right < m_min_style) m_min_style = right;
+ if(right >= 0 && right > m_max_style) m_max_style = right;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::move_to(int x, int y)
+ {
+ if(m_outline.sorted()) reset();
+ m_clipper.move_to(m_start_x = conv_type::downscale(x),
+ m_start_y = conv_type::downscale(y));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::line_to(int x, int y)
+ {
+ m_clipper.line_to(m_outline,
+ conv_type::downscale(x),
+ conv_type::downscale(y));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::move_to_d(double x, double y)
+ {
+ if(m_outline.sorted()) reset();
+ m_clipper.move_to(m_start_x = conv_type::upscale(x),
+ m_start_y = conv_type::upscale(y));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::line_to_d(double x, double y)
+ {
+ m_clipper.line_to(m_outline,
+ conv_type::upscale(x),
+ conv_type::upscale(y));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
+ {
+ if(is_move_to(cmd))
+ {
+ move_to_d(x, y);
+ }
+ else
+ if(is_vertex(cmd))
+ {
+ line_to_d(x, y);
+ }
+ else
+ if(is_close(cmd))
+ {
+ m_clipper.line_to(m_outline, m_start_x, m_start_y);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::edge(int x1, int y1, int x2, int y2)
+ {
+ if(m_outline.sorted()) reset();
+ m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
+ m_clipper.line_to(m_outline,
+ conv_type::downscale(x2),
+ conv_type::downscale(y2));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::edge_d(double x1, double y1,
+ double x2, double y2)
+ {
+ if(m_outline.sorted()) reset();
+ m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
+ m_clipper.line_to(m_outline,
+ conv_type::upscale(x2),
+ conv_type::upscale(y2));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ AGG_INLINE void rasterizer_compound_aa<Clip>::sort()
+ {
+ m_outline.sort_cells();
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ AGG_INLINE bool rasterizer_compound_aa<Clip>::rewind_scanlines()
+ {
+ m_outline.sort_cells();
+ if(m_outline.total_cells() == 0)
+ {
+ return false;
+ }
+ if(m_max_style < m_min_style)
+ {
+ return false;
+ }
+ m_scan_y = m_outline.min_y();
+ m_styles.allocate(m_max_style - m_min_style + 2, 128);
+ allocate_master_alpha();
+ return true;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ AGG_INLINE void rasterizer_compound_aa<Clip>::add_style(int style_id)
+ {
+ if(style_id < 0) style_id = 0;
+ else style_id -= m_min_style - 1;
+
+ unsigned nbyte = style_id >> 3;
+ unsigned mask = 1 << (style_id & 7);
+
+ style_info* style = &m_styles[style_id];
+ if((m_asm[nbyte] & mask) == 0)
+ {
+ m_ast.add(style_id);
+ m_asm[nbyte] |= mask;
+ style->start_cell = 0;
+ style->num_cells = 0;
+ style->last_x = -0x7FFFFFFF;
+ }
+ ++style->start_cell;
+ }
+
+ //------------------------------------------------------------------------
+ // Returns the number of styles
+ template<class Clip>
+ unsigned rasterizer_compound_aa<Clip>::sweep_styles()
+ {
+ for(;;)
+ {
+ if(m_scan_y > m_outline.max_y()) return 0;
+ unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
+ const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y);
+ unsigned num_styles = m_max_style - m_min_style + 2;
+ const cell_style_aa* curr_cell;
+ unsigned style_id;
+ style_info* style;
+ cell_info* cell;
+
+ m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles
+ m_ast.capacity(num_styles, 64);
+ m_asm.allocate((num_styles + 7) >> 3, 8);
+ m_asm.zero();
+
+ if(num_cells)
+ {
+ // Pre-add zero (for no-fill style, that is, -1).
+ // We need that to ensure that the "-1 style" would go first.
+ m_asm[0] |= 1;
+ m_ast.add(0);
+ style = &m_styles[0];
+ style->start_cell = 0;
+ style->num_cells = 0;
+ style->last_x = -0x7FFFFFFF;
+
+ m_sl_start = cells[0]->x;
+ m_sl_len = cells[num_cells-1]->x - m_sl_start + 1;
+ while(num_cells--)
+ {
+ curr_cell = *cells++;
+ add_style(curr_cell->left);
+ add_style(curr_cell->right);
+ }
+
+ // Convert the Y-histogram into the array of starting indexes
+ unsigned i;
+ unsigned start_cell = 0;
+ for(i = 0; i < m_ast.size(); i++)
+ {
+ style_info& st = m_styles[m_ast[i]];
+ unsigned v = st.start_cell;
+ st.start_cell = start_cell;
+ start_cell += v;
+ }
+
+ cells = m_outline.scanline_cells(m_scan_y);
+ num_cells = m_outline.scanline_num_cells(m_scan_y);
+
+ while(num_cells--)
+ {
+ curr_cell = *cells++;
+ style_id = (curr_cell->left < 0) ? 0 :
+ curr_cell->left - m_min_style + 1;
+
+ style = &m_styles[style_id];
+ if(curr_cell->x == style->last_x)
+ {
+ cell = &m_cells[style->start_cell + style->num_cells - 1];
+ cell->area += curr_cell->area;
+ cell->cover += curr_cell->cover;
+ }
+ else
+ {
+ cell = &m_cells[style->start_cell + style->num_cells];
+ cell->x = curr_cell->x;
+ cell->area = curr_cell->area;
+ cell->cover = curr_cell->cover;
+ style->last_x = curr_cell->x;
+ style->num_cells++;
+ }
+
+ style_id = (curr_cell->right < 0) ? 0 :
+ curr_cell->right - m_min_style + 1;
+
+ style = &m_styles[style_id];
+ if(curr_cell->x == style->last_x)
+ {
+ cell = &m_cells[style->start_cell + style->num_cells - 1];
+ cell->area -= curr_cell->area;
+ cell->cover -= curr_cell->cover;
+ }
+ else
+ {
+ cell = &m_cells[style->start_cell + style->num_cells];
+ cell->x = curr_cell->x;
+ cell->area = -curr_cell->area;
+ cell->cover = -curr_cell->cover;
+ style->last_x = curr_cell->x;
+ style->num_cells++;
+ }
+ }
+ }
+ if(m_ast.size() > 1) break;
+ ++m_scan_y;
+ }
+ ++m_scan_y;
+
+ if(m_layer_order != layer_unsorted)
+ {
+ range_adaptor<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1);
+ if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater);
+ else quick_sort(ra, unsigned_less);
+ }
+
+ return m_ast.size() - 1;
+ }
+
+ //------------------------------------------------------------------------
+ // Returns style ID depending of the existing style index
+ template<class Clip>
+ AGG_INLINE
+ unsigned rasterizer_compound_aa<Clip>::style(unsigned style_idx) const
+ {
+ return m_ast[style_idx + 1] + m_min_style - 1;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y)
+ {
+ m_outline.sort_cells();
+ if(m_outline.total_cells() == 0)
+ {
+ return false;
+ }
+ if(m_max_style < m_min_style)
+ {
+ return false;
+ }
+ if(y < m_outline.min_y() || y > m_outline.max_y())
+ {
+ return false;
+ }
+ m_scan_y = y;
+ m_styles.allocate(m_max_style - m_min_style + 2, 128);
+ allocate_master_alpha();
+ return true;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty)
+ {
+ if(!navigate_scanline(ty))
+ {
+ return false;
+ }
+
+ unsigned num_styles = sweep_styles();
+ if(num_styles <= 0)
+ {
+ return false;
+ }
+
+ scanline_hit_test sl(tx);
+ sweep_scanline(sl, -1);
+ return sl.hit();
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len)
+ {
+ m_cover_buf.allocate(len, 256);
+ return &m_cover_buf[0];
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::allocate_master_alpha()
+ {
+ while((int)m_master_alpha.size() <= m_max_style)
+ {
+ m_master_alpha.add(aa_mask);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_compound_aa<Clip>::master_alpha(int style, double alpha)
+ {
+ if(style >= 0)
+ {
+ while((int)m_master_alpha.size() <= style)
+ {
+ m_master_alpha.add(aa_mask);
+ }
+ m_master_alpha[style] = uround(alpha * aa_mask);
+ }
+ }
+
+}
+
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_rasterizer_outline.h b/plugins/Clist_ng/AGG/include/agg_rasterizer_outline.h new file mode 100644 index 0000000000..57cb3e0a7a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rasterizer_outline.h @@ -0,0 +1,157 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RASTERIZER_OUTLINE_INCLUDED
+#define AGG_RASTERIZER_OUTLINE_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //======================================================rasterizer_outline
+ template<class Renderer> class rasterizer_outline
+ {
+ public:
+ explicit rasterizer_outline(Renderer& ren) :
+ m_ren(&ren),
+ m_start_x(0),
+ m_start_y(0),
+ m_vertices(0)
+ {}
+ void attach(Renderer& ren) { m_ren = &ren; }
+
+
+ //--------------------------------------------------------------------
+ void move_to(int x, int y)
+ {
+ m_vertices = 1;
+ m_ren->move_to(m_start_x = x, m_start_y = y);
+ }
+
+ //--------------------------------------------------------------------
+ void line_to(int x, int y)
+ {
+ ++m_vertices;
+ m_ren->line_to(x, y);
+ }
+
+ //--------------------------------------------------------------------
+ void move_to_d(double x, double y)
+ {
+ move_to(m_ren->coord(x), m_ren->coord(y));
+ }
+
+ //--------------------------------------------------------------------
+ void line_to_d(double x, double y)
+ {
+ line_to(m_ren->coord(x), m_ren->coord(y));
+ }
+
+ //--------------------------------------------------------------------
+ void close()
+ {
+ if(m_vertices > 2)
+ {
+ line_to(m_start_x, m_start_y);
+ }
+ m_vertices = 0;
+ }
+
+ //--------------------------------------------------------------------
+ void add_vertex(double x, double y, unsigned cmd)
+ {
+ if(is_move_to(cmd))
+ {
+ move_to_d(x, y);
+ }
+ else
+ {
+ if(is_end_poly(cmd))
+ {
+ if(is_closed(cmd)) close();
+ }
+ else
+ {
+ line_to_d(x, y);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ template<class VertexSource>
+ void add_path(VertexSource& vs, unsigned path_id=0)
+ {
+ double x;
+ double y;
+
+ unsigned cmd;
+ vs.rewind(path_id);
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ add_vertex(x, y, cmd);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ template<class VertexSource, class ColorStorage, class PathId>
+ void render_all_paths(VertexSource& vs,
+ const ColorStorage& colors,
+ const PathId& path_id,
+ unsigned num_paths)
+ {
+ for(unsigned i = 0; i < num_paths; i++)
+ {
+ m_ren->line_color(colors[i]);
+ add_path(vs, path_id[i]);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ template<class Ctrl> void render_ctrl(Ctrl& c)
+ {
+ unsigned i;
+ for(i = 0; i < c.num_paths(); i++)
+ {
+ m_ren->line_color(c.color(i));
+ add_path(c, i);
+ }
+ }
+
+
+ private:
+ Renderer* m_ren;
+ int m_start_x;
+ int m_start_y;
+ unsigned m_vertices;
+ };
+
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_rasterizer_outline_aa.h b/plugins/Clist_ng/AGG/include/agg_rasterizer_outline_aa.h new file mode 100644 index 0000000000..6347cdfe8a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rasterizer_outline_aa.h @@ -0,0 +1,609 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED
+#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_line_aa_basics.h"
+#include "agg_vertex_sequence.h"
+
+namespace agg
+{
+
+ //-------------------------------------------------------------------------
+ inline bool cmp_dist_start(int d) { return d > 0; }
+ inline bool cmp_dist_end(int d) { return d <= 0; }
+
+
+
+ //-----------------------------------------------------------line_aa_vertex
+ // Vertex (x, y) with the distance to the next one. The last vertex has
+ // the distance between the last and the first points
+ struct line_aa_vertex
+ {
+ int x;
+ int y;
+ int len;
+
+ line_aa_vertex() {}
+ line_aa_vertex(int x_, int y_) :
+ x(x_),
+ y(y_),
+ len(0)
+ {
+ }
+
+ bool operator () (const line_aa_vertex& val)
+ {
+ double dx = val.x - x;
+ double dy = val.y - y;
+ return (len = uround(sqrt(dx * dx + dy * dy))) >
+ (line_subpixel_scale + line_subpixel_scale / 2);
+ }
+ };
+
+
+ //----------------------------------------------------------outline_aa_join_e
+ enum outline_aa_join_e
+ {
+ outline_no_join, //-----outline_no_join
+ outline_miter_join, //-----outline_miter_join
+ outline_round_join, //-----outline_round_join
+ outline_miter_accurate_join //-----outline_accurate_join
+ };
+
+ //=======================================================rasterizer_outline_aa
+ template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa
+ {
+ private:
+ //------------------------------------------------------------------------
+ struct draw_vars
+ {
+ unsigned idx;
+ int x1, y1, x2, y2;
+ line_parameters curr, next;
+ int lcurr, lnext;
+ int xb1, yb1, xb2, yb2;
+ unsigned flags;
+ };
+
+ void draw(draw_vars& dv, unsigned start, unsigned end);
+
+ public:
+ typedef line_aa_vertex vertex_type;
+ typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
+
+ explicit rasterizer_outline_aa(Renderer& ren) :
+ m_ren(&ren),
+ m_line_join(ren.accurate_join_only() ?
+ outline_miter_accurate_join :
+ outline_round_join),
+ m_round_cap(false),
+ m_start_x(0),
+ m_start_y(0)
+ {}
+ void attach(Renderer& ren) { m_ren = &ren; }
+
+ //------------------------------------------------------------------------
+ void line_join(outline_aa_join_e join)
+ {
+ m_line_join = m_ren->accurate_join_only() ?
+ outline_miter_accurate_join :
+ join;
+ }
+ bool line_join() const { return m_line_join; }
+
+ //------------------------------------------------------------------------
+ void round_cap(bool v) { m_round_cap = v; }
+ bool round_cap() const { return m_round_cap; }
+
+ //------------------------------------------------------------------------
+ void move_to(int x, int y)
+ {
+ m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
+ }
+
+ //------------------------------------------------------------------------
+ void line_to(int x, int y)
+ {
+ m_src_vertices.add(vertex_type(x, y));
+ }
+
+ //------------------------------------------------------------------------
+ void move_to_d(double x, double y)
+ {
+ move_to(Coord::conv(x), Coord::conv(y));
+ }
+
+ //------------------------------------------------------------------------
+ void line_to_d(double x, double y)
+ {
+ line_to(Coord::conv(x), Coord::conv(y));
+ }
+
+ //------------------------------------------------------------------------
+ void render(bool close_polygon);
+
+ //------------------------------------------------------------------------
+ void add_vertex(double x, double y, unsigned cmd)
+ {
+ if(is_move_to(cmd))
+ {
+ render(false);
+ move_to_d(x, y);
+ }
+ else
+ {
+ if(is_end_poly(cmd))
+ {
+ render(is_closed(cmd));
+ if(is_closed(cmd))
+ {
+ move_to(m_start_x, m_start_y);
+ }
+ }
+ else
+ {
+ line_to_d(x, y);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VertexSource>
+ void add_path(VertexSource& vs, unsigned path_id=0)
+ {
+ double x;
+ double y;
+
+ unsigned cmd;
+ vs.rewind(path_id);
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ add_vertex(x, y, cmd);
+ }
+ render(false);
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VertexSource, class ColorStorage, class PathId>
+ void render_all_paths(VertexSource& vs,
+ const ColorStorage& colors,
+ const PathId& path_id,
+ unsigned num_paths)
+ {
+ for(unsigned i = 0; i < num_paths; i++)
+ {
+ m_ren->color(colors[i]);
+ add_path(vs, path_id[i]);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class Ctrl> void render_ctrl(Ctrl& c)
+ {
+ unsigned i;
+ for(i = 0; i < c.num_paths(); i++)
+ {
+ m_ren->color(c.color(i));
+ add_path(c, i);
+ }
+ }
+
+ private:
+ rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&);
+ const rasterizer_outline_aa<Renderer, Coord>& operator =
+ (const rasterizer_outline_aa<Renderer, Coord>&);
+
+ Renderer* m_ren;
+ vertex_storage_type m_src_vertices;
+ outline_aa_join_e m_line_join;
+ bool m_round_cap;
+ int m_start_x;
+ int m_start_y;
+ };
+
+
+
+
+
+
+
+
+ //----------------------------------------------------------------------------
+ template<class Renderer, class Coord>
+ void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv,
+ unsigned start,
+ unsigned end)
+ {
+ unsigned i;
+ const vertex_storage_type::value_type* v;
+
+ for(i = start; i < end; i++)
+ {
+ if(m_line_join == outline_round_join)
+ {
+ dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1);
+ dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1);
+ dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
+ dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
+ }
+
+ switch(dv.flags)
+ {
+ case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
+ case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
+ case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
+ case 3: m_ren->line0(dv.curr); break;
+ }
+
+ if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
+ {
+ m_ren->pie(dv.curr.x2, dv.curr.y2,
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
+ dv.curr.x2 + (dv.next.y2 - dv.next.y1),
+ dv.curr.y2 - (dv.next.x2 - dv.next.x1));
+ }
+
+ dv.x1 = dv.x2;
+ dv.y1 = dv.y2;
+ dv.lcurr = dv.lnext;
+ dv.lnext = m_src_vertices[dv.idx].len;
+
+ ++dv.idx;
+ if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
+
+ v = &m_src_vertices[dv.idx];
+ dv.x2 = v->x;
+ dv.y2 = v->y;
+
+ dv.curr = dv.next;
+ dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
+ dv.xb1 = dv.xb2;
+ dv.yb1 = dv.yb2;
+
+ switch(m_line_join)
+ {
+ case outline_no_join:
+ dv.flags = 3;
+ break;
+
+ case outline_miter_join:
+ dv.flags >>= 1;
+ dv.flags |= ((dv.curr.diagonal_quadrant() ==
+ dv.next.diagonal_quadrant()) << 1);
+ if((dv.flags & 2) == 0)
+ {
+ bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
+ }
+ break;
+
+ case outline_round_join:
+ dv.flags >>= 1;
+ dv.flags |= ((dv.curr.diagonal_quadrant() ==
+ dv.next.diagonal_quadrant()) << 1);
+ break;
+
+ case outline_miter_accurate_join:
+ dv.flags = 0;
+ bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
+ break;
+ }
+ }
+ }
+
+
+
+
+ //----------------------------------------------------------------------------
+ template<class Renderer, class Coord>
+ void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon)
+ {
+ m_src_vertices.close(close_polygon);
+ draw_vars dv;
+ const vertex_storage_type::value_type* v;
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ int lprev;
+
+ if(close_polygon)
+ {
+ if(m_src_vertices.size() >= 3)
+ {
+ dv.idx = 2;
+
+ v = &m_src_vertices[m_src_vertices.size() - 1];
+ x1 = v->x;
+ y1 = v->y;
+ lprev = v->len;
+
+ v = &m_src_vertices[0];
+ x2 = v->x;
+ y2 = v->y;
+ dv.lcurr = v->len;
+ line_parameters prev(x1, y1, x2, y2, lprev);
+
+ v = &m_src_vertices[1];
+ dv.x1 = v->x;
+ dv.y1 = v->y;
+ dv.lnext = v->len;
+ dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
+
+ v = &m_src_vertices[dv.idx];
+ dv.x2 = v->x;
+ dv.y2 = v->y;
+ dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
+
+ dv.xb1 = 0;
+ dv.yb1 = 0;
+ dv.xb2 = 0;
+ dv.yb2 = 0;
+
+ switch(m_line_join)
+ {
+ case outline_no_join:
+ dv.flags = 3;
+ break;
+
+ case outline_miter_join:
+ case outline_round_join:
+ dv.flags =
+ (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
+ ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
+ break;
+
+ case outline_miter_accurate_join:
+ dv.flags = 0;
+ break;
+ }
+
+ if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
+ {
+ bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
+ }
+
+ if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
+ {
+ bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
+ }
+ draw(dv, 0, m_src_vertices.size());
+ }
+ }
+ else
+ {
+ switch(m_src_vertices.size())
+ {
+ case 0:
+ case 1:
+ break;
+
+ case 2:
+ {
+ v = &m_src_vertices[0];
+ x1 = v->x;
+ y1 = v->y;
+ lprev = v->len;
+ v = &m_src_vertices[1];
+ x2 = v->x;
+ y2 = v->y;
+ line_parameters lp(x1, y1, x2, y2, lprev);
+ if(m_round_cap)
+ {
+ m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
+ }
+ m_ren->line3(lp,
+ x1 + (y2 - y1),
+ y1 - (x2 - x1),
+ x2 + (y2 - y1),
+ y2 - (x2 - x1));
+ if(m_round_cap)
+ {
+ m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
+ }
+ }
+ break;
+
+ case 3:
+ {
+ int x3, y3;
+ int lnext;
+ v = &m_src_vertices[0];
+ x1 = v->x;
+ y1 = v->y;
+ lprev = v->len;
+ v = &m_src_vertices[1];
+ x2 = v->x;
+ y2 = v->y;
+ lnext = v->len;
+ v = &m_src_vertices[2];
+ x3 = v->x;
+ y3 = v->y;
+ line_parameters lp1(x1, y1, x2, y2, lprev);
+ line_parameters lp2(x2, y2, x3, y3, lnext);
+
+ if(m_round_cap)
+ {
+ m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
+ }
+
+ if(m_line_join == outline_round_join)
+ {
+ m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
+ x2 + (y2 - y1), y2 - (x2 - x1));
+
+ m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
+ x2 + (y3 - y2), y2 - (x3 - x2));
+
+ m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
+ x3 + (y3 - y2), y3 - (x3 - x2));
+ }
+ else
+ {
+ bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
+ m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
+ dv.xb1, dv.yb1);
+
+ m_ren->line3(lp2, dv.xb1, dv.yb1,
+ x3 + (y3 - y2), y3 - (x3 - x2));
+ }
+ if(m_round_cap)
+ {
+ m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
+ }
+ }
+ break;
+
+ default:
+ {
+ dv.idx = 3;
+
+ v = &m_src_vertices[0];
+ x1 = v->x;
+ y1 = v->y;
+ lprev = v->len;
+
+ v = &m_src_vertices[1];
+ x2 = v->x;
+ y2 = v->y;
+ dv.lcurr = v->len;
+ line_parameters prev(x1, y1, x2, y2, lprev);
+
+ v = &m_src_vertices[2];
+ dv.x1 = v->x;
+ dv.y1 = v->y;
+ dv.lnext = v->len;
+ dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
+
+ v = &m_src_vertices[dv.idx];
+ dv.x2 = v->x;
+ dv.y2 = v->y;
+ dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
+
+ dv.xb1 = 0;
+ dv.yb1 = 0;
+ dv.xb2 = 0;
+ dv.yb2 = 0;
+
+ switch(m_line_join)
+ {
+ case outline_no_join:
+ dv.flags = 3;
+ break;
+
+ case outline_miter_join:
+ case outline_round_join:
+ dv.flags =
+ (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
+ ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
+ break;
+
+ case outline_miter_accurate_join:
+ dv.flags = 0;
+ break;
+ }
+
+ if(m_round_cap)
+ {
+ m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
+ }
+ if((dv.flags & 1) == 0)
+ {
+ if(m_line_join == outline_round_join)
+ {
+ m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
+ x2 + (y2 - y1), y2 - (x2 - x1));
+ m_ren->pie(prev.x2, prev.y2,
+ x2 + (y2 - y1), y2 - (x2 - x1),
+ dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
+ dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
+ }
+ else
+ {
+ bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
+ m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
+ dv.xb1, dv.yb1);
+ }
+ }
+ else
+ {
+ m_ren->line1(prev,
+ x1 + (y2 - y1),
+ y1 - (x2 - x1));
+ }
+ if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
+ {
+ bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
+ }
+
+ draw(dv, 1, m_src_vertices.size() - 2);
+
+ if((dv.flags & 1) == 0)
+ {
+ if(m_line_join == outline_round_join)
+ {
+ m_ren->line3(dv.curr,
+ dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
+ dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
+ }
+ else
+ {
+ m_ren->line3(dv.curr, dv.xb1, dv.yb1,
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
+ }
+ }
+ else
+ {
+ m_ren->line2(dv.curr,
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
+ }
+ if(m_round_cap)
+ {
+ m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
+ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
+ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
+ }
+
+ }
+ break;
+ }
+ }
+ m_src_vertices.remove_all();
+ }
+
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_rasterizer_scanline_aa.h b/plugins/Clist_ng/AGG/include/agg_rasterizer_scanline_aa.h new file mode 100644 index 0000000000..b5d363adda --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rasterizer_scanline_aa.h @@ -0,0 +1,520 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// The author gratefully acknowleges the support of David Turner,
+// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
+// libray - in producing this work. See http://www.freetype.org for details.
+//
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED
+#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED
+
+#include "agg_rasterizer_cells_aa.h"
+#include "agg_rasterizer_sl_clip.h"
+#include "agg_gamma_functions.h"
+
+
+namespace agg
+{
+
+
+ //-----------------------------------------------------------------cell_aa
+ // A pixel cell. There're no constructors defined and it was done
+ // intentionally in order to avoid extra overhead when allocating an
+ // array of cells.
+ struct cell_aa
+ {
+ int x;
+ int y;
+ int cover;
+ int area;
+
+ void initial()
+ {
+ x = 0x7FFFFFFF;
+ y = 0x7FFFFFFF;
+ cover = 0;
+ area = 0;
+ }
+
+ void style(const cell_aa&) {}
+
+ int not_equal(int ex, int ey, const cell_aa&) const
+ {
+ return (ex - x) | (ey - y);
+ }
+ };
+
+
+ //==================================================rasterizer_scanline_aa
+ // Polygon rasterizer that is used to render filled polygons with
+ // high-quality Anti-Aliasing. Internally, by default, the class uses
+ // integer coordinates in format 24.8, i.e. 24 bits for integer part
+ // and 8 bits for fractional - see poly_subpixel_shift. This class can be
+ // used in the following way:
+ //
+ // 1. filling_rule(filling_rule_e ft) - optional.
+ //
+ // 2. gamma() - optional.
+ //
+ // 3. reset()
+ //
+ // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
+ // more than one contour, but each contour must consist of at least 3
+ // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
+ // is the absolute minimum of vertices that define a triangle.
+ // The algorithm does not check either the number of vertices nor
+ // coincidence of their coordinates, but in the worst case it just
+ // won't draw anything.
+ // The orger of the vertices (clockwise or counterclockwise)
+ // is important when using the non-zero filling rule (fill_non_zero).
+ // In this case the vertex order of all the contours must be the same
+ // if you want your intersecting polygons to be without "holes".
+ // You actually can use different vertices order. If the contours do not
+ // intersect each other the order is not important anyway. If they do,
+ // contours with the same vertex order will be rendered without "holes"
+ // while the intersecting contours with different orders will have "holes".
+ //
+ // filling_rule() and gamma() can be called anytime before "sweeping".
+ //------------------------------------------------------------------------
+ template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa
+ {
+ enum status
+ {
+ status_initial,
+ status_move_to,
+ status_line_to,
+ status_closed
+ };
+
+ public:
+ typedef Clip clip_type;
+ typedef typename Clip::conv_type conv_type;
+ typedef typename Clip::coord_type coord_type;
+
+ enum aa_scale_e
+ {
+ aa_shift = 8,
+ aa_scale = 1 << aa_shift,
+ aa_mask = aa_scale - 1,
+ aa_scale2 = aa_scale * 2,
+ aa_mask2 = aa_scale2 - 1
+ };
+
+ //--------------------------------------------------------------------
+ rasterizer_scanline_aa() :
+ m_outline(),
+ m_clipper(),
+ m_filling_rule(fill_non_zero),
+ m_auto_close(true),
+ m_start_x(0),
+ m_start_y(0),
+ m_status(status_initial)
+ {
+ int i;
+ for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaF>
+ rasterizer_scanline_aa(const GammaF& gamma_function) :
+ m_outline(),
+ m_clipper(m_outline),
+ m_filling_rule(fill_non_zero),
+ m_auto_close(true),
+ m_start_x(0),
+ m_start_y(0),
+ m_status(status_initial)
+ {
+ gamma(gamma_function);
+ }
+
+ //--------------------------------------------------------------------
+ void reset();
+ void reset_clipping();
+ void clip_box(double x1, double y1, double x2, double y2);
+ void filling_rule(filling_rule_e filling_rule);
+ void auto_close(bool flag) { m_auto_close = flag; }
+
+ //--------------------------------------------------------------------
+ template<class GammaF> void gamma(const GammaF& gamma_function)
+ {
+ int i;
+ for(i = 0; i < aa_scale; i++)
+ {
+ m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ unsigned apply_gamma(unsigned cover) const
+ {
+ return m_gamma[cover];
+ }
+
+ //--------------------------------------------------------------------
+ void move_to(int x, int y);
+ void line_to(int x, int y);
+ void move_to_d(double x, double y);
+ void line_to_d(double x, double y);
+ void close_polygon();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ void edge(int x1, int y1, int x2, int y2);
+ void edge_d(double x1, double y1, double x2, double y2);
+
+ //-------------------------------------------------------------------
+ template<class VertexSource>
+ void add_path(VertexSource& vs, unsigned path_id=0)
+ {
+ double x;
+ double y;
+
+ unsigned cmd;
+ vs.rewind(path_id);
+ if(m_outline.sorted()) reset();
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ add_vertex(x, y, cmd);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ int min_x() const { return m_outline.min_x(); }
+ int min_y() const { return m_outline.min_y(); }
+ int max_x() const { return m_outline.max_x(); }
+ int max_y() const { return m_outline.max_y(); }
+
+ //--------------------------------------------------------------------
+ void sort();
+ bool rewind_scanlines();
+ bool navigate_scanline(int y);
+
+ //--------------------------------------------------------------------
+ AGG_INLINE unsigned calculate_alpha(int area) const
+ {
+ int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
+
+ if(cover < 0) cover = -cover;
+ if(m_filling_rule == fill_even_odd)
+ {
+ cover &= aa_mask2;
+ if(cover > aa_scale)
+ {
+ cover = aa_scale2 - cover;
+ }
+ }
+ if(cover > aa_mask) cover = aa_mask;
+ return m_gamma[cover];
+ }
+
+ //--------------------------------------------------------------------
+ template<class Scanline> bool sweep_scanline(Scanline& sl)
+ {
+ for(;;)
+ {
+ if(m_scan_y > m_outline.max_y()) return false;
+ sl.reset_spans();
+ unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
+ const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
+ int cover = 0;
+
+ while(num_cells)
+ {
+ const cell_aa* cur_cell = *cells;
+ int x = cur_cell->x;
+ int area = cur_cell->area;
+ unsigned alpha;
+
+ cover += cur_cell->cover;
+
+ //accumulate all cells with the same X
+ while(--num_cells)
+ {
+ cur_cell = *++cells;
+ if(cur_cell->x != x) break;
+ area += cur_cell->area;
+ cover += cur_cell->cover;
+ }
+
+ if(area)
+ {
+ alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
+ if(alpha)
+ {
+ sl.add_cell(x, alpha);
+ }
+ x++;
+ }
+
+ if(num_cells && cur_cell->x > x)
+ {
+ alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
+ if(alpha)
+ {
+ sl.add_span(x, cur_cell->x - x, alpha);
+ }
+ }
+ }
+
+ if(sl.num_spans()) break;
+ ++m_scan_y;
+ }
+
+ sl.finalize(m_scan_y);
+ ++m_scan_y;
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ bool hit_test(int tx, int ty);
+
+
+ private:
+ //--------------------------------------------------------------------
+ // Disable copying
+ rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&);
+ const rasterizer_scanline_aa<Clip>&
+ operator = (const rasterizer_scanline_aa<Clip>&);
+
+ private:
+ rasterizer_cells_aa<cell_aa> m_outline;
+ clip_type m_clipper;
+ int m_gamma[aa_scale];
+ filling_rule_e m_filling_rule;
+ bool m_auto_close;
+ coord_type m_start_x;
+ coord_type m_start_y;
+ unsigned m_status;
+ int m_scan_y;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::reset()
+ {
+ m_outline.reset();
+ m_status = status_initial;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule)
+ {
+ m_filling_rule = filling_rule;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1,
+ double x2, double y2)
+ {
+ reset();
+ m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
+ conv_type::upscale(x2), conv_type::upscale(y2));
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::reset_clipping()
+ {
+ reset();
+ m_clipper.reset_clipping();
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::close_polygon()
+ {
+ if(m_status == status_line_to)
+ {
+ m_clipper.line_to(m_outline, m_start_x, m_start_y);
+ m_status = status_closed;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
+ {
+ if(m_outline.sorted()) reset();
+ if(m_auto_close) close_polygon();
+ m_clipper.move_to(m_start_x = conv_type::downscale(x),
+ m_start_y = conv_type::downscale(y));
+ m_status = status_move_to;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::line_to(int x, int y)
+ {
+ m_clipper.line_to(m_outline,
+ conv_type::downscale(x),
+ conv_type::downscale(y));
+ m_status = status_line_to;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
+ {
+ if(m_outline.sorted()) reset();
+ if(m_auto_close) close_polygon();
+ m_clipper.move_to(m_start_x = conv_type::upscale(x),
+ m_start_y = conv_type::upscale(y));
+ m_status = status_move_to;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y)
+ {
+ m_clipper.line_to(m_outline,
+ conv_type::upscale(x),
+ conv_type::upscale(y));
+ m_status = status_line_to;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
+ {
+ if(is_move_to(cmd))
+ {
+ move_to_d(x, y);
+ }
+ else
+ if(is_vertex(cmd))
+ {
+ line_to_d(x, y);
+ }
+ else
+ if(is_close(cmd))
+ {
+ close_polygon();
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2)
+ {
+ if(m_outline.sorted()) reset();
+ m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
+ m_clipper.line_to(m_outline,
+ conv_type::downscale(x2),
+ conv_type::downscale(y2));
+ m_status = status_move_to;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1,
+ double x2, double y2)
+ {
+ if(m_outline.sorted()) reset();
+ m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
+ m_clipper.line_to(m_outline,
+ conv_type::upscale(x2),
+ conv_type::upscale(y2));
+ m_status = status_move_to;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ void rasterizer_scanline_aa<Clip>::sort()
+ {
+ if(m_auto_close) close_polygon();
+ m_outline.sort_cells();
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
+ {
+ if(m_auto_close) close_polygon();
+ m_outline.sort_cells();
+ if(m_outline.total_cells() == 0)
+ {
+ return false;
+ }
+ m_scan_y = m_outline.min_y();
+ return true;
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
+ {
+ if(m_auto_close) close_polygon();
+ m_outline.sort_cells();
+ if(m_outline.total_cells() == 0 ||
+ y < m_outline.min_y() ||
+ y > m_outline.max_y())
+ {
+ return false;
+ }
+ m_scan_y = y;
+ return true;
+ }
+
+ //------------------------------------------------------------------------
+ template<class Clip>
+ bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
+ {
+ if(!navigate_scanline(ty)) return false;
+ scanline_hit_test sl(tx);
+ sweep_scanline(sl);
+ return sl.hit();
+ }
+
+
+
+}
+
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_rasterizer_sl_clip.h b/plugins/Clist_ng/AGG/include/agg_rasterizer_sl_clip.h new file mode 100644 index 0000000000..c11e6da767 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rasterizer_sl_clip.h @@ -0,0 +1,361 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED
+#define AGG_RASTERIZER_SL_CLIP_INCLUDED
+
+#include "agg_clip_liang_barsky.h"
+
+namespace agg
+{
+ //--------------------------------------------------------poly_max_coord_e
+ enum poly_max_coord_e
+ {
+ poly_max_coord = (1 << 30) - 1 //----poly_max_coord
+ };
+
+ //------------------------------------------------------------ras_conv_int
+ struct ras_conv_int
+ {
+ typedef int coord_type;
+ static AGG_INLINE int mul_div(double a, double b, double c)
+ {
+ return iround(a * b / c);
+ }
+ static int xi(int v) { return v; }
+ static int yi(int v) { return v; }
+ static int upscale(double v) { return iround(v * poly_subpixel_scale); }
+ static int downscale(int v) { return v; }
+ };
+
+ //--------------------------------------------------------ras_conv_int_sat
+ struct ras_conv_int_sat
+ {
+ typedef int coord_type;
+ static AGG_INLINE int mul_div(double a, double b, double c)
+ {
+ return saturation<poly_max_coord>::iround(a * b / c);
+ }
+ static int xi(int v) { return v; }
+ static int yi(int v) { return v; }
+ static int upscale(double v)
+ {
+ return saturation<poly_max_coord>::iround(v * poly_subpixel_scale);
+ }
+ static int downscale(int v) { return v; }
+ };
+
+ //---------------------------------------------------------ras_conv_int_3x
+ struct ras_conv_int_3x
+ {
+ typedef int coord_type;
+ static AGG_INLINE int mul_div(double a, double b, double c)
+ {
+ return iround(a * b / c);
+ }
+ static int xi(int v) { return v * 3; }
+ static int yi(int v) { return v; }
+ static int upscale(double v) { return iround(v * poly_subpixel_scale); }
+ static int downscale(int v) { return v; }
+ };
+
+ //-----------------------------------------------------------ras_conv_dbl
+ struct ras_conv_dbl
+ {
+ typedef double coord_type;
+ static AGG_INLINE double mul_div(double a, double b, double c)
+ {
+ return a * b / c;
+ }
+ static int xi(double v) { return iround(v * poly_subpixel_scale); }
+ static int yi(double v) { return iround(v * poly_subpixel_scale); }
+ static double upscale(double v) { return v; }
+ static double downscale(int v) { return v / double(poly_subpixel_scale); }
+ };
+
+ //--------------------------------------------------------ras_conv_dbl_3x
+ struct ras_conv_dbl_3x
+ {
+ typedef double coord_type;
+ static AGG_INLINE double mul_div(double a, double b, double c)
+ {
+ return a * b / c;
+ }
+ static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
+ static int yi(double v) { return iround(v * poly_subpixel_scale); }
+ static double upscale(double v) { return v; }
+ static double downscale(int v) { return v / double(poly_subpixel_scale); }
+ };
+
+
+
+
+
+ //------------------------------------------------------rasterizer_sl_clip
+ template<class Conv> class rasterizer_sl_clip
+ {
+ public:
+ typedef Conv conv_type;
+ typedef typename Conv::coord_type coord_type;
+ typedef rect_base<coord_type> rect_type;
+
+ //--------------------------------------------------------------------
+ rasterizer_sl_clip() :
+ m_clip_box(0,0,0,0),
+ m_x1(0),
+ m_y1(0),
+ m_f1(0),
+ m_clipping(false)
+ {}
+
+ //--------------------------------------------------------------------
+ void reset_clipping()
+ {
+ m_clipping = false;
+ }
+
+ //--------------------------------------------------------------------
+ void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
+ {
+ m_clip_box = rect_type(x1, y1, x2, y2);
+ m_clip_box.normalize();
+ m_clipping = true;
+ }
+
+ //--------------------------------------------------------------------
+ void move_to(coord_type x1, coord_type y1)
+ {
+ m_x1 = x1;
+ m_y1 = y1;
+ if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box);
+ }
+
+ private:
+ //------------------------------------------------------------------------
+ template<class Rasterizer>
+ AGG_INLINE void line_clip_y(Rasterizer& ras,
+ coord_type x1, coord_type y1,
+ coord_type x2, coord_type y2,
+ unsigned f1, unsigned f2) const
+ {
+ f1 &= 10;
+ f2 &= 10;
+ if((f1 | f2) == 0)
+ {
+ // Fully visible
+ ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
+ }
+ else
+ {
+ if(f1 == f2)
+ {
+ // Invisible by Y
+ return;
+ }
+
+ coord_type tx1 = x1;
+ coord_type ty1 = y1;
+ coord_type tx2 = x2;
+ coord_type ty2 = y2;
+
+ if(f1 & 8) // y1 < clip.y1
+ {
+ tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
+ ty1 = m_clip_box.y1;
+ }
+
+ if(f1 & 2) // y1 > clip.y2
+ {
+ tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
+ ty1 = m_clip_box.y2;
+ }
+
+ if(f2 & 8) // y2 < clip.y1
+ {
+ tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
+ ty2 = m_clip_box.y1;
+ }
+
+ if(f2 & 2) // y2 > clip.y2
+ {
+ tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
+ ty2 = m_clip_box.y2;
+ }
+ ras.line(Conv::xi(tx1), Conv::yi(ty1),
+ Conv::xi(tx2), Conv::yi(ty2));
+ }
+ }
+
+
+ public:
+ //--------------------------------------------------------------------
+ template<class Rasterizer>
+ void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
+ {
+ if(m_clipping)
+ {
+ unsigned f2 = clipping_flags(x2, y2, m_clip_box);
+
+ if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
+ {
+ // Invisible by Y
+ m_x1 = x2;
+ m_y1 = y2;
+ m_f1 = f2;
+ return;
+ }
+
+ coord_type x1 = m_x1;
+ coord_type y1 = m_y1;
+ unsigned f1 = m_f1;
+ coord_type y3, y4;
+ unsigned f3, f4;
+
+ switch(((f1 & 5) << 1) | (f2 & 5))
+ {
+ case 0: // Visible by X
+ line_clip_y(ras, x1, y1, x2, y2, f1, f2);
+ break;
+
+ case 1: // x2 > clip.x2
+ y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
+ f3 = clipping_flags_y(y3, m_clip_box);
+ line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3);
+ line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2);
+ break;
+
+ case 2: // x1 > clip.x2
+ y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
+ f3 = clipping_flags_y(y3, m_clip_box);
+ line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
+ line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2);
+ break;
+
+ case 3: // x1 > clip.x2 && x2 > clip.x2
+ line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2);
+ break;
+
+ case 4: // x2 < clip.x1
+ y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
+ f3 = clipping_flags_y(y3, m_clip_box);
+ line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3);
+ line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2);
+ break;
+
+ case 6: // x1 > clip.x2 && x2 < clip.x1
+ y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
+ y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
+ f3 = clipping_flags_y(y3, m_clip_box);
+ f4 = clipping_flags_y(y4, m_clip_box);
+ line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
+ line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4);
+ line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2);
+ break;
+
+ case 8: // x1 < clip.x1
+ y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
+ f3 = clipping_flags_y(y3, m_clip_box);
+ line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
+ line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2);
+ break;
+
+ case 9: // x1 < clip.x1 && x2 > clip.x2
+ y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
+ y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
+ f3 = clipping_flags_y(y3, m_clip_box);
+ f4 = clipping_flags_y(y4, m_clip_box);
+ line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
+ line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4);
+ line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2);
+ break;
+
+ case 12: // x1 < clip.x1 && x2 < clip.x1
+ line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2);
+ break;
+ }
+ m_f1 = f2;
+ }
+ else
+ {
+ ras.line(Conv::xi(m_x1), Conv::yi(m_y1),
+ Conv::xi(x2), Conv::yi(y2));
+ }
+ m_x1 = x2;
+ m_y1 = y2;
+ }
+
+
+ private:
+ rect_type m_clip_box;
+ coord_type m_x1;
+ coord_type m_y1;
+ unsigned m_f1;
+ bool m_clipping;
+ };
+
+
+
+
+ //---------------------------------------------------rasterizer_sl_no_clip
+ class rasterizer_sl_no_clip
+ {
+ public:
+ typedef ras_conv_int conv_type;
+ typedef int coord_type;
+
+ rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
+
+ void reset_clipping() {}
+ void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {}
+ void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
+
+ template<class Rasterizer>
+ void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
+ {
+ ras.line(m_x1, m_y1, x2, y2);
+ m_x1 = x2;
+ m_y1 = y2;
+ }
+
+ private:
+ int m_x1, m_y1;
+ };
+
+
+ // -----rasterizer_sl_clip_int
+ // -----rasterizer_sl_clip_int_sat
+ // -----rasterizer_sl_clip_int_3x
+ // -----rasterizer_sl_clip_dbl
+ // -----rasterizer_sl_clip_dbl_3x
+ //------------------------------------------------------------------------
+ typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int;
+ typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat;
+ typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x;
+ typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl;
+ typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x;
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_base.h b/plugins/Clist_ng/AGG/include/agg_renderer_base.h new file mode 100644 index 0000000000..9d9c1be966 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_base.h @@ -0,0 +1,723 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_BASE_INCLUDED
+#define AGG_RENDERER_BASE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_rendering_buffer.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------------------renderer_base
+ template<class PixelFormat> class renderer_base
+ {
+ public:
+ typedef PixelFormat pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::row_data row_data;
+
+ //--------------------------------------------------------------------
+ renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {}
+ explicit renderer_base(pixfmt_type& ren) :
+ m_ren(&ren),
+ m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
+ {}
+ void attach(pixfmt_type& ren)
+ {
+ m_ren = &ren;
+ m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1);
+ }
+
+ //--------------------------------------------------------------------
+ const pixfmt_type& ren() const { return *m_ren; }
+ pixfmt_type& ren() { return *m_ren; }
+
+ //--------------------------------------------------------------------
+ unsigned width() const { return m_ren->width(); }
+ unsigned height() const { return m_ren->height(); }
+
+ //--------------------------------------------------------------------
+ bool clip_box(int x1, int y1, int x2, int y2)
+ {
+ rect_i cb(x1, y1, x2, y2);
+ cb.normalize();
+ if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
+ {
+ m_clip_box = cb;
+ return true;
+ }
+ m_clip_box.x1 = 1;
+ m_clip_box.y1 = 1;
+ m_clip_box.x2 = 0;
+ m_clip_box.y2 = 0;
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_clipping(bool visibility)
+ {
+ if(visibility)
+ {
+ m_clip_box.x1 = 0;
+ m_clip_box.y1 = 0;
+ m_clip_box.x2 = width() - 1;
+ m_clip_box.y2 = height() - 1;
+ }
+ else
+ {
+ m_clip_box.x1 = 1;
+ m_clip_box.y1 = 1;
+ m_clip_box.x2 = 0;
+ m_clip_box.y2 = 0;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void clip_box_naked(int x1, int y1, int x2, int y2)
+ {
+ m_clip_box.x1 = x1;
+ m_clip_box.y1 = y1;
+ m_clip_box.x2 = x2;
+ m_clip_box.y2 = y2;
+ }
+
+ //--------------------------------------------------------------------
+ bool inbox(int x, int y) const
+ {
+ return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
+ x <= m_clip_box.x2 && y <= m_clip_box.y2;
+ }
+
+ //--------------------------------------------------------------------
+ const rect_i& clip_box() const { return m_clip_box; }
+ int xmin() const { return m_clip_box.x1; }
+ int ymin() const { return m_clip_box.y1; }
+ int xmax() const { return m_clip_box.x2; }
+ int ymax() const { return m_clip_box.y2; }
+
+ //--------------------------------------------------------------------
+ const rect_i& bounding_clip_box() const { return m_clip_box; }
+ int bounding_xmin() const { return m_clip_box.x1; }
+ int bounding_ymin() const { return m_clip_box.y1; }
+ int bounding_xmax() const { return m_clip_box.x2; }
+ int bounding_ymax() const { return m_clip_box.y2; }
+
+ //--------------------------------------------------------------------
+ void clear(const color_type& c)
+ {
+ unsigned y;
+ if(width())
+ {
+ for(y = 0; y < height(); y++)
+ {
+ m_ren->copy_hline(0, y, width(), c);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_pixel(int x, int y, const color_type& c)
+ {
+ if(inbox(x, y))
+ {
+ m_ren->copy_pixel(x, y, c);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void blend_pixel(int x, int y, const color_type& c, cover_type cover)
+ {
+ if(inbox(x, y))
+ {
+ m_ren->blend_pixel(x, y, c, cover);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ color_type pixel(int x, int y) const
+ {
+ return inbox(x, y) ?
+ m_ren->pixel(x, y) :
+ color_type::no_color();
+ }
+
+ //--------------------------------------------------------------------
+ void copy_hline(int x1, int y, int x2, const color_type& c)
+ {
+ if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
+ if(y > ymax()) return;
+ if(y < ymin()) return;
+ if(x1 > xmax()) return;
+ if(x2 < xmin()) return;
+
+ if(x1 < xmin()) x1 = xmin();
+ if(x2 > xmax()) x2 = xmax();
+
+ m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_vline(int x, int y1, int y2, const color_type& c)
+ {
+ if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
+ if(x > xmax()) return;
+ if(x < xmin()) return;
+ if(y1 > ymax()) return;
+ if(y2 < ymin()) return;
+
+ if(y1 < ymin()) y1 = ymin();
+ if(y2 > ymax()) y2 = ymax();
+
+ m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x1, int y, int x2,
+ const color_type& c, cover_type cover)
+ {
+ if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
+ if(y > ymax()) return;
+ if(y < ymin()) return;
+ if(x1 > xmax()) return;
+ if(x2 < xmin()) return;
+
+ if(x1 < xmin()) x1 = xmin();
+ if(x2 > xmax()) x2 = xmax();
+
+ m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y1, int y2,
+ const color_type& c, cover_type cover)
+ {
+ if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
+ if(x > xmax()) return;
+ if(x < xmin()) return;
+ if(y1 > ymax()) return;
+ if(y2 < ymin()) return;
+
+ if(y1 < ymin()) y1 = ymin();
+ if(y2 > ymax()) y2 = ymax();
+
+ m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
+ {
+ rect_i rc(x1, y1, x2, y2);
+ rc.normalize();
+ if(rc.clip(clip_box()))
+ {
+ int y;
+ for(y = rc.y1; y <= rc.y2; y++)
+ {
+ m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void blend_bar(int x1, int y1, int x2, int y2,
+ const color_type& c, cover_type cover)
+ {
+ rect_i rc(x1, y1, x2, y2);
+ rc.normalize();
+ if(rc.clip(clip_box()))
+ {
+ int y;
+ for(y = rc.y1; y <= rc.y2; y++)
+ {
+ m_ren->blend_hline(rc.x1,
+ y,
+ unsigned(rc.x2 - rc.x1 + 1),
+ c,
+ cover);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y, int len,
+ const color_type& c,
+ const cover_type* covers)
+ {
+ if(y > ymax()) return;
+ if(y < ymin()) return;
+
+ if(x < xmin())
+ {
+ len -= xmin() - x;
+ if(len <= 0) return;
+ covers += xmin() - x;
+ x = xmin();
+ }
+ if(x + len > xmax())
+ {
+ len = xmax() - x + 1;
+ if(len <= 0) return;
+ }
+ m_ren->blend_solid_hspan(x, y, len, c, covers);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y, int len,
+ const color_type& c,
+ const cover_type* covers)
+ {
+ if(x > xmax()) return;
+ if(x < xmin()) return;
+
+ if(y < ymin())
+ {
+ len -= ymin() - y;
+ if(len <= 0) return;
+ covers += ymin() - y;
+ y = ymin();
+ }
+ if(y + len > ymax())
+ {
+ len = ymax() - y + 1;
+ if(len <= 0) return;
+ }
+ m_ren->blend_solid_vspan(x, y, len, c, covers);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y, int len, const color_type* colors)
+ {
+ if(y > ymax()) return;
+ if(y < ymin()) return;
+
+ if(x < xmin())
+ {
+ int d = xmin() - x;
+ len -= d;
+ if(len <= 0) return;
+ colors += d;
+ x = xmin();
+ }
+ if(x + len > xmax())
+ {
+ len = xmax() - x + 1;
+ if(len <= 0) return;
+ }
+ m_ren->copy_color_hspan(x, y, len, colors);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y, int len, const color_type* colors)
+ {
+ if(x > xmax()) return;
+ if(x < xmin()) return;
+
+ if(y < ymin())
+ {
+ int d = ymin() - y;
+ len -= d;
+ if(len <= 0) return;
+ colors += d;
+ y = ymin();
+ }
+ if(y + len > ymax())
+ {
+ len = ymax() - y + 1;
+ if(len <= 0) return;
+ }
+ m_ren->copy_color_vspan(x, y, len, colors);
+ }
+
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y, int len,
+ const color_type* colors,
+ const cover_type* covers,
+ cover_type cover = agg::cover_full)
+ {
+ if(y > ymax()) return;
+ if(y < ymin()) return;
+
+ if(x < xmin())
+ {
+ int d = xmin() - x;
+ len -= d;
+ if(len <= 0) return;
+ if(covers) covers += d;
+ colors += d;
+ x = xmin();
+ }
+ if(x + len > xmax())
+ {
+ len = xmax() - x + 1;
+ if(len <= 0) return;
+ }
+ m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y, int len,
+ const color_type* colors,
+ const cover_type* covers,
+ cover_type cover = agg::cover_full)
+ {
+ if(x > xmax()) return;
+ if(x < xmin()) return;
+
+ if(y < ymin())
+ {
+ int d = ymin() - y;
+ len -= d;
+ if(len <= 0) return;
+ if(covers) covers += d;
+ colors += d;
+ y = ymin();
+ }
+ if(y + len > ymax())
+ {
+ len = ymax() - y + 1;
+ if(len <= 0) return;
+ }
+ m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
+ }
+
+ //--------------------------------------------------------------------
+ rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const
+ {
+ rect_i rc(0,0,0,0);
+ rect_i cb = clip_box();
+ ++cb.x2;
+ ++cb.y2;
+
+ if(src.x1 < 0)
+ {
+ dst.x1 -= src.x1;
+ src.x1 = 0;
+ }
+ if(src.y1 < 0)
+ {
+ dst.y1 -= src.y1;
+ src.y1 = 0;
+ }
+
+ if(src.x2 > wsrc) src.x2 = wsrc;
+ if(src.y2 > hsrc) src.y2 = hsrc;
+
+ if(dst.x1 < cb.x1)
+ {
+ src.x1 += cb.x1 - dst.x1;
+ dst.x1 = cb.x1;
+ }
+ if(dst.y1 < cb.y1)
+ {
+ src.y1 += cb.y1 - dst.y1;
+ dst.y1 = cb.y1;
+ }
+
+ if(dst.x2 > cb.x2) dst.x2 = cb.x2;
+ if(dst.y2 > cb.y2) dst.y2 = cb.y2;
+
+ rc.x2 = dst.x2 - dst.x1;
+ rc.y2 = dst.y2 - dst.y1;
+
+ if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1;
+ if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1;
+ return rc;
+ }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf>
+ void copy_from(const RenBuf& src,
+ const rect_i* rect_src_ptr = 0,
+ int dx = 0,
+ int dy = 0)
+ {
+ rect_i rsrc(0, 0, src.width(), src.height());
+ if(rect_src_ptr)
+ {
+ rsrc.x1 = rect_src_ptr->x1;
+ rsrc.y1 = rect_src_ptr->y1;
+ rsrc.x2 = rect_src_ptr->x2 + 1;
+ rsrc.y2 = rect_src_ptr->y2 + 1;
+ }
+
+ // Version with xdst, ydst (absolute positioning)
+ //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
+
+ // Version with dx, dy (relative positioning)
+ rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
+
+ rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
+
+ if(rc.x2 > 0)
+ {
+ int incy = 1;
+ if(rdst.y1 > rsrc.y1)
+ {
+ rsrc.y1 += rc.y2 - 1;
+ rdst.y1 += rc.y2 - 1;
+ incy = -1;
+ }
+ while(rc.y2 > 0)
+ {
+ m_ren->copy_from(src,
+ rdst.x1, rdst.y1,
+ rsrc.x1, rsrc.y1,
+ rc.x2);
+ rdst.y1 += incy;
+ rsrc.y1 += incy;
+ --rc.y2;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from(const SrcPixelFormatRenderer& src,
+ const rect_i* rect_src_ptr = 0,
+ int dx = 0,
+ int dy = 0,
+ cover_type cover = agg::cover_full)
+ {
+ rect_i rsrc(0, 0, src.width(), src.height());
+ if(rect_src_ptr)
+ {
+ rsrc.x1 = rect_src_ptr->x1;
+ rsrc.y1 = rect_src_ptr->y1;
+ rsrc.x2 = rect_src_ptr->x2 + 1;
+ rsrc.y2 = rect_src_ptr->y2 + 1;
+ }
+
+ // Version with xdst, ydst (absolute positioning)
+ //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
+
+ // Version with dx, dy (relative positioning)
+ rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
+ rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
+
+ if(rc.x2 > 0)
+ {
+ int incy = 1;
+ if(rdst.y1 > rsrc.y1)
+ {
+ rsrc.y1 += rc.y2 - 1;
+ rdst.y1 += rc.y2 - 1;
+ incy = -1;
+ }
+ while(rc.y2 > 0)
+ {
+ typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
+ if(rw.ptr)
+ {
+ int x1src = rsrc.x1;
+ int x1dst = rdst.x1;
+ int len = rc.x2;
+ if(rw.x1 > x1src)
+ {
+ x1dst += rw.x1 - x1src;
+ len -= rw.x1 - x1src;
+ x1src = rw.x1;
+ }
+ if(len > 0)
+ {
+ if(x1src + len-1 > rw.x2)
+ {
+ len -= x1src + len - rw.x2 - 1;
+ }
+ if(len > 0)
+ {
+ m_ren->blend_from(src,
+ x1dst, rdst.y1,
+ x1src, rsrc.y1,
+ len,
+ cover);
+ }
+ }
+ }
+ rdst.y1 += incy;
+ rsrc.y1 += incy;
+ --rc.y2;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_color(const SrcPixelFormatRenderer& src,
+ const color_type& color,
+ const rect_i* rect_src_ptr = 0,
+ int dx = 0,
+ int dy = 0,
+ cover_type cover = agg::cover_full)
+ {
+ rect_i rsrc(0, 0, src.width(), src.height());
+ if(rect_src_ptr)
+ {
+ rsrc.x1 = rect_src_ptr->x1;
+ rsrc.y1 = rect_src_ptr->y1;
+ rsrc.x2 = rect_src_ptr->x2 + 1;
+ rsrc.y2 = rect_src_ptr->y2 + 1;
+ }
+
+ // Version with xdst, ydst (absolute positioning)
+ //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
+
+ // Version with dx, dy (relative positioning)
+ rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
+ rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
+
+ if(rc.x2 > 0)
+ {
+ int incy = 1;
+ if(rdst.y1 > rsrc.y1)
+ {
+ rsrc.y1 += rc.y2 - 1;
+ rdst.y1 += rc.y2 - 1;
+ incy = -1;
+ }
+ while(rc.y2 > 0)
+ {
+ typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
+ if(rw.ptr)
+ {
+ int x1src = rsrc.x1;
+ int x1dst = rdst.x1;
+ int len = rc.x2;
+ if(rw.x1 > x1src)
+ {
+ x1dst += rw.x1 - x1src;
+ len -= rw.x1 - x1src;
+ x1src = rw.x1;
+ }
+ if(len > 0)
+ {
+ if(x1src + len-1 > rw.x2)
+ {
+ len -= x1src + len - rw.x2 - 1;
+ }
+ if(len > 0)
+ {
+ m_ren->blend_from_color(src,
+ color,
+ x1dst, rdst.y1,
+ x1src, rsrc.y1,
+ len,
+ cover);
+ }
+ }
+ }
+ rdst.y1 += incy;
+ rsrc.y1 += incy;
+ --rc.y2;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from_lut(const SrcPixelFormatRenderer& src,
+ const color_type* color_lut,
+ const rect_i* rect_src_ptr = 0,
+ int dx = 0,
+ int dy = 0,
+ cover_type cover = agg::cover_full)
+ {
+ rect_i rsrc(0, 0, src.width(), src.height());
+ if(rect_src_ptr)
+ {
+ rsrc.x1 = rect_src_ptr->x1;
+ rsrc.y1 = rect_src_ptr->y1;
+ rsrc.x2 = rect_src_ptr->x2 + 1;
+ rsrc.y2 = rect_src_ptr->y2 + 1;
+ }
+
+ // Version with xdst, ydst (absolute positioning)
+ //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
+
+ // Version with dx, dy (relative positioning)
+ rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
+ rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
+
+ if(rc.x2 > 0)
+ {
+ int incy = 1;
+ if(rdst.y1 > rsrc.y1)
+ {
+ rsrc.y1 += rc.y2 - 1;
+ rdst.y1 += rc.y2 - 1;
+ incy = -1;
+ }
+ while(rc.y2 > 0)
+ {
+ typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
+ if(rw.ptr)
+ {
+ int x1src = rsrc.x1;
+ int x1dst = rdst.x1;
+ int len = rc.x2;
+ if(rw.x1 > x1src)
+ {
+ x1dst += rw.x1 - x1src;
+ len -= rw.x1 - x1src;
+ x1src = rw.x1;
+ }
+ if(len > 0)
+ {
+ if(x1src + len-1 > rw.x2)
+ {
+ len -= x1src + len - rw.x2 - 1;
+ }
+ if(len > 0)
+ {
+ m_ren->blend_from_lut(src,
+ color_lut,
+ x1dst, rdst.y1,
+ x1src, rsrc.y1,
+ len,
+ cover);
+ }
+ }
+ }
+ rdst.y1 += incy;
+ rsrc.y1 += incy;
+ --rc.y2;
+ }
+ }
+ }
+
+ private:
+ pixfmt_type* m_ren;
+ rect_i m_clip_box;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_markers.h b/plugins/Clist_ng/AGG/include/agg_renderer_markers.h new file mode 100644 index 0000000000..40d34da4f0 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_markers.h @@ -0,0 +1,711 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_MARKERS_INCLUDED
+#define AGG_RENDERER_MARKERS_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_renderer_primitives.h"
+
+namespace agg
+{
+
+ //---------------------------------------------------------------marker_e
+ enum marker_e
+ {
+ marker_square,
+ marker_diamond,
+ marker_circle,
+ marker_crossed_circle,
+ marker_semiellipse_left,
+ marker_semiellipse_right,
+ marker_semiellipse_up,
+ marker_semiellipse_down,
+ marker_triangle_left,
+ marker_triangle_right,
+ marker_triangle_up,
+ marker_triangle_down,
+ marker_four_rays,
+ marker_cross,
+ marker_x,
+ marker_dash,
+ marker_dot,
+ marker_pixel,
+
+ end_of_markers
+ };
+
+
+
+ //--------------------------------------------------------renderer_markers
+ template<class BaseRenderer> class renderer_markers :
+ public renderer_primitives<BaseRenderer>
+ {
+ public:
+ typedef renderer_primitives<BaseRenderer> base_type;
+ typedef BaseRenderer base_ren_type;
+ typedef typename base_ren_type::color_type color_type;
+
+ //--------------------------------------------------------------------
+ renderer_markers(base_ren_type& rbuf) :
+ base_type(rbuf)
+ {}
+
+ //--------------------------------------------------------------------
+ bool visible(int x, int y, int r) const
+ {
+ rect_i rc(x-r, y-r, x+y, y+r);
+ return rc.clip(base_type::ren().bounding_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void square(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r);
+ else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void diamond(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int dy = -r;
+ int dx = 0;
+ do
+ {
+ base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
+
+ if(dx)
+ {
+ base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
+ base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++dy;
+ ++dx;
+ }
+ while(dy <= 0);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void circle(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r) base_type::outlined_ellipse(x, y, r, r);
+ else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+
+
+
+ //--------------------------------------------------------------------
+ void crossed_circle(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ base_type::outlined_ellipse(x, y, r, r);
+ int r6 = r + (r >> 1);
+ if(r <= 2) r6++;
+ r >>= 1;
+ base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full);
+ base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full);
+ base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full);
+ base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void semiellipse_left(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int r8 = r * 4 / 5;
+ int dy = -r;
+ int dx = 0;
+ ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
+
+ if(ei.dy() && dx)
+ {
+ base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++ei;
+ }
+ while(dy < r8);
+ base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void semiellipse_right(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int r8 = r * 4 / 5;
+ int dy = -r;
+ int dx = 0;
+ ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
+
+ if(ei.dy() && dx)
+ {
+ base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++ei;
+ }
+ while(dy < r8);
+ base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void semiellipse_up(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int r8 = r * 4 / 5;
+ int dy = -r;
+ int dx = 0;
+ ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
+
+ if(ei.dy() && dx)
+ {
+ base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++ei;
+ }
+ while(dy < r8);
+ base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void semiellipse_down(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int r8 = r * 4 / 5;
+ int dy = -r;
+ int dx = 0;
+ ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
+
+ if(ei.dy() && dx)
+ {
+ base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++ei;
+ }
+ while(dy < r8);
+ base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void triangle_left(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int dy = -r;
+ int dx = 0;
+ int flip = 0;
+ int r6 = r * 3 / 5;
+ do
+ {
+ base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
+
+ if(dx)
+ {
+ base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++dy;
+ dx += flip;
+ flip ^= 1;
+ }
+ while(dy < r6);
+ base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void triangle_right(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int dy = -r;
+ int dx = 0;
+ int flip = 0;
+ int r6 = r * 3 / 5;
+ do
+ {
+ base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
+
+ if(dx)
+ {
+ base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++dy;
+ dx += flip;
+ flip ^= 1;
+ }
+ while(dy < r6);
+ base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void triangle_up(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int dy = -r;
+ int dx = 0;
+ int flip = 0;
+ int r6 = r * 3 / 5;
+ do
+ {
+ base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
+
+ if(dx)
+ {
+ base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++dy;
+ dx += flip;
+ flip ^= 1;
+ }
+ while(dy < r6);
+ base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void triangle_down(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int dy = -r;
+ int dx = 0;
+ int flip = 0;
+ int r6 = r * 3 / 5;
+ do
+ {
+ base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
+
+ if(dx)
+ {
+ base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++dy;
+ dx += flip;
+ flip ^= 1;
+ }
+ while(dy < r6);
+ base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void four_rays(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int dy = -r;
+ int dx = 0;
+ int flip = 0;
+ int r3 = -(r / 3);
+ do
+ {
+ base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
+
+ if(dx)
+ {
+ base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
+ base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
+ base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
+ base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
+ }
+ ++dy;
+ dx += flip;
+ flip ^= 1;
+ }
+ while(dy <= r3);
+ base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void cross(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full);
+ base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
+ }
+ else
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void xing(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r)
+ {
+ int dy = -r * 7 / 10;
+ do
+ {
+ base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full);
+ base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full);
+ ++dy;
+ }
+ while(dy < 0);
+ }
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void dash(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
+ else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ void dot(int x, int y, int r)
+ {
+ if(visible(x, y, r))
+ {
+ if(r) base_type::solid_ellipse(x, y, r, r);
+ else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void pixel(int x, int y, int)
+ {
+ base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
+ }
+
+ //--------------------------------------------------------------------
+ void marker(int x, int y, int r, marker_e type)
+ {
+ switch(type)
+ {
+ case marker_square: square(x, y, r); break;
+ case marker_diamond: diamond(x, y, r); break;
+ case marker_circle: circle(x, y, r); break;
+ case marker_crossed_circle: crossed_circle(x, y, r); break;
+ case marker_semiellipse_left: semiellipse_left(x, y, r); break;
+ case marker_semiellipse_right: semiellipse_right(x, y, r); break;
+ case marker_semiellipse_up: semiellipse_up(x, y, r); break;
+ case marker_semiellipse_down: semiellipse_down(x, y, r); break;
+ case marker_triangle_left: triangle_left(x, y, r); break;
+ case marker_triangle_right: triangle_right(x, y, r); break;
+ case marker_triangle_up: triangle_up(x, y, r); break;
+ case marker_triangle_down: triangle_down(x, y, r); break;
+ case marker_four_rays: four_rays(x, y, r); break;
+ case marker_cross: cross(x, y, r); break;
+ case marker_x: xing(x, y, r); break;
+ case marker_dash: dash(x, y, r); break;
+ case marker_dot: dot(x, y, r); break;
+ case marker_pixel: pixel(x, y, r); break;
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ template<class T>
+ void markers(int n, const T* x, const T* y, T r, marker_e type)
+ {
+ if(n <= 0) return;
+ if(r == 0)
+ {
+ do
+ {
+ base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full);
+ ++x;
+ ++y;
+ }
+ while(--n);
+ return;
+ }
+
+ switch(type)
+ {
+ case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class T>
+ void markers(int n, const T* x, const T* y, const T* r, marker_e type)
+ {
+ if(n <= 0) return;
+ switch(type)
+ {
+ case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class T>
+ void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type)
+ {
+ if(n <= 0) return;
+ switch(type)
+ {
+ case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class T>
+ void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type)
+ {
+ if(n <= 0) return;
+ switch(type)
+ {
+ case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
+ }
+ }
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_mclip.h b/plugins/Clist_ng/AGG/include/agg_renderer_mclip.h new file mode 100644 index 0000000000..a2a5b65695 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_mclip.h @@ -0,0 +1,349 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_MCLIP_INCLUDED
+#define AGG_RENDERER_MCLIP_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_array.h"
+#include "agg_renderer_base.h"
+
+namespace agg
+{
+
+ //----------------------------------------------------------renderer_mclip
+ template<class PixelFormat> class renderer_mclip
+ {
+ public:
+ typedef PixelFormat pixfmt_type;
+ typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::row_data row_data;
+ typedef renderer_base<pixfmt_type> base_ren_type;
+
+ //--------------------------------------------------------------------
+ explicit renderer_mclip(pixfmt_type& pixf) :
+ m_ren(pixf),
+ m_curr_cb(0),
+ m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
+ {}
+ void attach(pixfmt_type& pixf)
+ {
+ m_ren.attach(pixf);
+ reset_clipping(true);
+ }
+
+ //--------------------------------------------------------------------
+ const pixfmt_type& ren() const { return m_ren.ren(); }
+ pixfmt_type& ren() { return m_ren.ren(); }
+
+ //--------------------------------------------------------------------
+ unsigned width() const { return m_ren.width(); }
+ unsigned height() const { return m_ren.height(); }
+
+ //--------------------------------------------------------------------
+ const rect_i& clip_box() const { return m_ren.clip_box(); }
+ int xmin() const { return m_ren.xmin(); }
+ int ymin() const { return m_ren.ymin(); }
+ int xmax() const { return m_ren.xmax(); }
+ int ymax() const { return m_ren.ymax(); }
+
+ //--------------------------------------------------------------------
+ const rect_i& bounding_clip_box() const { return m_bounds; }
+ int bounding_xmin() const { return m_bounds.x1; }
+ int bounding_ymin() const { return m_bounds.y1; }
+ int bounding_xmax() const { return m_bounds.x2; }
+ int bounding_ymax() const { return m_bounds.y2; }
+
+ //--------------------------------------------------------------------
+ void first_clip_box()
+ {
+ m_curr_cb = 0;
+ if(m_clip.size())
+ {
+ const rect_i& cb = m_clip[0];
+ m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ bool next_clip_box()
+ {
+ if(++m_curr_cb < m_clip.size())
+ {
+ const rect_i& cb = m_clip[m_curr_cb];
+ m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
+ return true;
+ }
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_clipping(bool visibility)
+ {
+ m_ren.reset_clipping(visibility);
+ m_clip.remove_all();
+ m_curr_cb = 0;
+ m_bounds = m_ren.clip_box();
+ }
+
+ //--------------------------------------------------------------------
+ void add_clip_box(int x1, int y1, int x2, int y2)
+ {
+ rect_i cb(x1, y1, x2, y2);
+ cb.normalize();
+ if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
+ {
+ m_clip.add(cb);
+ if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1;
+ if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1;
+ if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2;
+ if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void clear(const color_type& c)
+ {
+ m_ren.clear(c);
+ }
+
+ //--------------------------------------------------------------------
+ void copy_pixel(int x, int y, const color_type& c)
+ {
+ first_clip_box();
+ do
+ {
+ if(m_ren.inbox(x, y))
+ {
+ m_ren.ren().copy_pixel(x, y, c);
+ break;
+ }
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_pixel(int x, int y, const color_type& c, cover_type cover)
+ {
+ first_clip_box();
+ do
+ {
+ if(m_ren.inbox(x, y))
+ {
+ m_ren.ren().blend_pixel(x, y, c, cover);
+ break;
+ }
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ color_type pixel(int x, int y) const
+ {
+ if(m_ren.inbox(x, y))
+ {
+ return m_ren.ren().pixel(x, y);
+ }
+ return color_type::no_color();
+ }
+
+ //--------------------------------------------------------------------
+ void copy_hline(int x1, int y, int x2, const color_type& c)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.copy_hline(x1, y, x2, c);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void copy_vline(int x, int y1, int y2, const color_type& c)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.copy_vline(x, y1, y2, c);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_hline(int x1, int y, int x2,
+ const color_type& c, cover_type cover)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_hline(x1, y, x2, c, cover);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_vline(int x, int y1, int y2,
+ const color_type& c, cover_type cover)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_vline(x, y1, y2, c, cover);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.copy_bar(x1, y1, x2, y2, c);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_bar(int x1, int y1, int x2, int y2,
+ const color_type& c, cover_type cover)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_bar(x1, y1, x2, y2, c, cover);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y, int len,
+ const color_type& c, const cover_type* covers)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_solid_hspan(x, y, len, c, covers);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y, int len,
+ const color_type& c, const cover_type* covers)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_solid_vspan(x, y, len, c, covers);
+ }
+ while(next_clip_box());
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y, int len, const color_type* colors)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.copy_color_hspan(x, y, len, colors);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_hspan(int x, int y, int len,
+ const color_type* colors,
+ const cover_type* covers,
+ cover_type cover = cover_full)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void blend_color_vspan(int x, int y, int len,
+ const color_type* colors,
+ const cover_type* covers,
+ cover_type cover = cover_full)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ void copy_from(const rendering_buffer& from,
+ const rect_i* rc=0,
+ int x_to=0,
+ int y_to=0)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.copy_from(from, rc, x_to, y_to);
+ }
+ while(next_clip_box());
+ }
+
+ //--------------------------------------------------------------------
+ template<class SrcPixelFormatRenderer>
+ void blend_from(const SrcPixelFormatRenderer& src,
+ const rect_i* rect_src_ptr = 0,
+ int dx = 0,
+ int dy = 0,
+ cover_type cover = cover_full)
+ {
+ first_clip_box();
+ do
+ {
+ m_ren.blend_from(src, rect_src_ptr, dx, dy, cover);
+ }
+ while(next_clip_box());
+ }
+
+
+ private:
+ renderer_mclip(const renderer_mclip<PixelFormat>&);
+ const renderer_mclip<PixelFormat>&
+ operator = (const renderer_mclip<PixelFormat>&);
+
+ base_ren_type m_ren;
+ pod_bvector<rect_i, 4> m_clip;
+ unsigned m_curr_cb;
+ rect_i m_bounds;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_outline_aa.h b/plugins/Clist_ng/AGG/include/agg_renderer_outline_aa.h new file mode 100644 index 0000000000..70b4c9b7e4 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_outline_aa.h @@ -0,0 +1,1847 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
+#define AGG_RENDERER_OUTLINE_AA_INCLUDED
+
+#include "agg_array.h"
+#include "agg_math.h"
+#include "agg_line_aa_basics.h"
+#include "agg_dda_line.h"
+#include "agg_ellipse_bresenham.h"
+#include "agg_renderer_base.h"
+#include "agg_gamma_functions.h"
+#include "agg_clip_liang_barsky.h"
+
+namespace agg
+{
+
+ //===================================================distance_interpolator0
+ class distance_interpolator0
+ {
+ public:
+ //---------------------------------------------------------------------
+ distance_interpolator0() {}
+ distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) :
+ m_dx(line_mr(x2) - line_mr(x1)),
+ m_dy(line_mr(y2) - line_mr(y1)),
+ m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx)
+ {
+ m_dx <<= line_mr_subpixel_shift;
+ m_dy <<= line_mr_subpixel_shift;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_x() { m_dist += m_dy; }
+ int dist() const { return m_dist; }
+
+ private:
+ //---------------------------------------------------------------------
+ int m_dx;
+ int m_dy;
+ int m_dist;
+ };
+
+ //==================================================distance_interpolator00
+ class distance_interpolator00
+ {
+ public:
+ //---------------------------------------------------------------------
+ distance_interpolator00() {}
+ distance_interpolator00(int xc, int yc,
+ int x1, int y1, int x2, int y2,
+ int x, int y) :
+ m_dx1(line_mr(x1) - line_mr(xc)),
+ m_dy1(line_mr(y1) - line_mr(yc)),
+ m_dx2(line_mr(x2) - line_mr(xc)),
+ m_dy2(line_mr(y2) - line_mr(yc)),
+ m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1),
+ m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2)
+ {
+ m_dx1 <<= line_mr_subpixel_shift;
+ m_dy1 <<= line_mr_subpixel_shift;
+ m_dx2 <<= line_mr_subpixel_shift;
+ m_dy2 <<= line_mr_subpixel_shift;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; }
+ int dist1() const { return m_dist1; }
+ int dist2() const { return m_dist2; }
+
+ private:
+ //---------------------------------------------------------------------
+ int m_dx1;
+ int m_dy1;
+ int m_dx2;
+ int m_dy2;
+ int m_dist1;
+ int m_dist2;
+ };
+
+ //===================================================distance_interpolator1
+ class distance_interpolator1
+ {
+ public:
+ //---------------------------------------------------------------------
+ distance_interpolator1() {}
+ distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) :
+ m_dx(x2 - x1),
+ m_dy(y2 - y1),
+ m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
+ double(y + line_subpixel_scale/2 - y2) * double(m_dx)))
+ {
+ m_dx <<= line_subpixel_shift;
+ m_dy <<= line_subpixel_shift;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_x() { m_dist += m_dy; }
+ void dec_x() { m_dist -= m_dy; }
+ void inc_y() { m_dist -= m_dx; }
+ void dec_y() { m_dist += m_dx; }
+
+ //---------------------------------------------------------------------
+ void inc_x(int dy)
+ {
+ m_dist += m_dy;
+ if(dy > 0) m_dist -= m_dx;
+ if(dy < 0) m_dist += m_dx;
+ }
+
+ //---------------------------------------------------------------------
+ void dec_x(int dy)
+ {
+ m_dist -= m_dy;
+ if(dy > 0) m_dist -= m_dx;
+ if(dy < 0) m_dist += m_dx;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_y(int dx)
+ {
+ m_dist -= m_dx;
+ if(dx > 0) m_dist += m_dy;
+ if(dx < 0) m_dist -= m_dy;
+ }
+
+ void dec_y(int dx)
+ //---------------------------------------------------------------------
+ {
+ m_dist += m_dx;
+ if(dx > 0) m_dist += m_dy;
+ if(dx < 0) m_dist -= m_dy;
+ }
+
+ //---------------------------------------------------------------------
+ int dist() const { return m_dist; }
+ int dx() const { return m_dx; }
+ int dy() const { return m_dy; }
+
+ private:
+ //---------------------------------------------------------------------
+ int m_dx;
+ int m_dy;
+ int m_dist;
+ };
+
+
+
+
+
+ //===================================================distance_interpolator2
+ class distance_interpolator2
+ {
+ public:
+ //---------------------------------------------------------------------
+ distance_interpolator2() {}
+ distance_interpolator2(int x1, int y1, int x2, int y2,
+ int sx, int sy, int x, int y) :
+ m_dx(x2 - x1),
+ m_dy(y2 - y1),
+ m_dx_start(line_mr(sx) - line_mr(x1)),
+ m_dy_start(line_mr(sy) - line_mr(y1)),
+
+ m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
+ double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
+
+ m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start)
+ {
+ m_dx <<= line_subpixel_shift;
+ m_dy <<= line_subpixel_shift;
+ m_dx_start <<= line_mr_subpixel_shift;
+ m_dy_start <<= line_mr_subpixel_shift;
+ }
+
+ distance_interpolator2(int x1, int y1, int x2, int y2,
+ int ex, int ey, int x, int y, int) :
+ m_dx(x2 - x1),
+ m_dy(y2 - y1),
+ m_dx_start(line_mr(ex) - line_mr(x2)),
+ m_dy_start(line_mr(ey) - line_mr(y2)),
+
+ m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
+ double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
+
+ m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start)
+ {
+ m_dx <<= line_subpixel_shift;
+ m_dy <<= line_subpixel_shift;
+ m_dx_start <<= line_mr_subpixel_shift;
+ m_dy_start <<= line_mr_subpixel_shift;
+ }
+
+
+ //---------------------------------------------------------------------
+ void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; }
+ void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; }
+ void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; }
+ void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; }
+
+ //---------------------------------------------------------------------
+ void inc_x(int dy)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ if(dy > 0)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ }
+ if(dy < 0)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void dec_x(int dy)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ if(dy > 0)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ }
+ if(dy < 0)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void inc_y(int dx)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ if(dx > 0)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ }
+ if(dx < 0)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void dec_y(int dx)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ if(dx > 0)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ }
+ if(dx < 0)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ int dist() const { return m_dist; }
+ int dist_start() const { return m_dist_start; }
+ int dist_end() const { return m_dist_start; }
+
+ //---------------------------------------------------------------------
+ int dx() const { return m_dx; }
+ int dy() const { return m_dy; }
+ int dx_start() const { return m_dx_start; }
+ int dy_start() const { return m_dy_start; }
+ int dx_end() const { return m_dx_start; }
+ int dy_end() const { return m_dy_start; }
+
+ private:
+ //---------------------------------------------------------------------
+ int m_dx;
+ int m_dy;
+ int m_dx_start;
+ int m_dy_start;
+
+ int m_dist;
+ int m_dist_start;
+ };
+
+
+
+
+
+ //===================================================distance_interpolator3
+ class distance_interpolator3
+ {
+ public:
+ //---------------------------------------------------------------------
+ distance_interpolator3() {}
+ distance_interpolator3(int x1, int y1, int x2, int y2,
+ int sx, int sy, int ex, int ey,
+ int x, int y) :
+ m_dx(x2 - x1),
+ m_dy(y2 - y1),
+ m_dx_start(line_mr(sx) - line_mr(x1)),
+ m_dy_start(line_mr(sy) - line_mr(y1)),
+ m_dx_end(line_mr(ex) - line_mr(x2)),
+ m_dy_end(line_mr(ey) - line_mr(y2)),
+
+ m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
+ double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
+
+ m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
+
+ m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end)
+ {
+ m_dx <<= line_subpixel_shift;
+ m_dy <<= line_subpixel_shift;
+ m_dx_start <<= line_mr_subpixel_shift;
+ m_dy_start <<= line_mr_subpixel_shift;
+ m_dx_end <<= line_mr_subpixel_shift;
+ m_dy_end <<= line_mr_subpixel_shift;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; }
+ void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; }
+ void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; }
+ void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; }
+
+ //---------------------------------------------------------------------
+ void inc_x(int dy)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ m_dist_end += m_dy_end;
+ if(dy > 0)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ m_dist_end -= m_dx_end;
+ }
+ if(dy < 0)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ m_dist_end += m_dx_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void dec_x(int dy)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ m_dist_end -= m_dy_end;
+ if(dy > 0)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ m_dist_end -= m_dx_end;
+ }
+ if(dy < 0)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ m_dist_end += m_dx_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void inc_y(int dx)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ m_dist_end -= m_dx_end;
+ if(dx > 0)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ m_dist_end += m_dy_end;
+ }
+ if(dx < 0)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ m_dist_end -= m_dy_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void dec_y(int dx)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ m_dist_end += m_dx_end;
+ if(dx > 0)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ m_dist_end += m_dy_end;
+ }
+ if(dx < 0)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ m_dist_end -= m_dy_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ int dist() const { return m_dist; }
+ int dist_start() const { return m_dist_start; }
+ int dist_end() const { return m_dist_end; }
+
+ //---------------------------------------------------------------------
+ int dx() const { return m_dx; }
+ int dy() const { return m_dy; }
+ int dx_start() const { return m_dx_start; }
+ int dy_start() const { return m_dy_start; }
+ int dx_end() const { return m_dx_end; }
+ int dy_end() const { return m_dy_end; }
+
+ private:
+ //---------------------------------------------------------------------
+ int m_dx;
+ int m_dy;
+ int m_dx_start;
+ int m_dy_start;
+ int m_dx_end;
+ int m_dy_end;
+
+ int m_dist;
+ int m_dist_start;
+ int m_dist_end;
+ };
+
+
+
+
+
+ //================================================line_interpolator_aa_base
+ template<class Renderer> class line_interpolator_aa_base
+ {
+ public:
+ typedef Renderer renderer_type;
+ typedef typename Renderer::color_type color_type;
+
+ //---------------------------------------------------------------------
+ enum max_half_width_e
+ {
+ max_half_width = 64
+ };
+
+ //---------------------------------------------------------------------
+ line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) :
+ m_lp(&lp),
+ m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
+ line_dbl_hr(lp.y2 - lp.y1),
+ lp.vertical ? abs(lp.y2 - lp.y1) :
+ abs(lp.x2 - lp.x1) + 1),
+ m_ren(ren),
+ m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len),
+ m_x(lp.x1 >> line_subpixel_shift),
+ m_y(lp.y1 >> line_subpixel_shift),
+ m_old_x(m_x),
+ m_old_y(m_y),
+ m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
+ abs((lp.x2 >> line_subpixel_shift) - m_x))),
+ m_width(ren.subpixel_width()),
+ //m_max_extent(m_width >> (line_subpixel_shift - 2)),
+ m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift),
+ m_step(0)
+ {
+ agg::dda2_line_interpolator li(0, lp.vertical ?
+ (lp.dy << agg::line_subpixel_shift) :
+ (lp.dx << agg::line_subpixel_shift),
+ lp.len);
+
+ unsigned i;
+ int stop = m_width + line_subpixel_scale * 2;
+ for(i = 0; i < max_half_width; ++i)
+ {
+ m_dist[i] = li.y();
+ if(m_dist[i] >= stop) break;
+ ++li;
+ }
+ m_dist[i++] = 0x7FFF0000;
+ }
+
+ //---------------------------------------------------------------------
+ template<class DI> int step_hor_base(DI& di)
+ {
+ ++m_li;
+ m_x += m_lp->inc;
+ m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift;
+
+ if(m_lp->inc > 0) di.inc_x(m_y - m_old_y);
+ else di.dec_x(m_y - m_old_y);
+
+ m_old_y = m_y;
+
+ return di.dist() / m_len;
+ }
+
+ //---------------------------------------------------------------------
+ template<class DI> int step_ver_base(DI& di)
+ {
+ ++m_li;
+ m_y += m_lp->inc;
+ m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift;
+
+ if(m_lp->inc > 0) di.inc_y(m_x - m_old_x);
+ else di.dec_y(m_x - m_old_x);
+
+ m_old_x = m_x;
+
+ return di.dist() / m_len;
+ }
+
+ //---------------------------------------------------------------------
+ bool vertical() const { return m_lp->vertical; }
+ int width() const { return m_width; }
+ int count() const { return m_count; }
+
+ private:
+ line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&);
+ const line_interpolator_aa_base<Renderer>&
+ operator = (const line_interpolator_aa_base<Renderer>&);
+
+ protected:
+ const line_parameters* m_lp;
+ dda2_line_interpolator m_li;
+ renderer_type& m_ren;
+ int m_len;
+ int m_x;
+ int m_y;
+ int m_old_x;
+ int m_old_y;
+ int m_count;
+ int m_width;
+ int m_max_extent;
+ int m_step;
+ int m_dist[max_half_width + 1];
+ cover_type m_covers[max_half_width * 2 + 4];
+ };
+
+
+
+
+
+
+
+ //====================================================line_interpolator_aa0
+ template<class Renderer> class line_interpolator_aa0 :
+ public line_interpolator_aa_base<Renderer>
+ {
+ public:
+ typedef Renderer renderer_type;
+ typedef typename Renderer::color_type color_type;
+ typedef line_interpolator_aa_base<Renderer> base_type;
+
+ //---------------------------------------------------------------------
+ line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) :
+ line_interpolator_aa_base<Renderer>(ren, lp),
+ m_di(lp.x1, lp.y1, lp.x2, lp.y2,
+ lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
+ {
+ base_type::m_li.adjust_forward();
+ }
+
+ //---------------------------------------------------------------------
+ bool step_hor()
+ {
+ int dist;
+ int dy;
+ int s1 = base_type::step_hor_base(m_di);
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ *p1++ = (cover_type)base_type::m_ren.cover(s1);
+
+ dy = 1;
+ while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
+ {
+ *p1++ = (cover_type)base_type::m_ren.cover(dist);
+ ++dy;
+ }
+
+ dy = 1;
+ while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
+ {
+ *--p0 = (cover_type)base_type::m_ren.cover(dist);
+ ++dy;
+ }
+ base_type::m_ren.blend_solid_vspan(base_type::m_x,
+ base_type::m_y - dy + 1,
+ unsigned(p1 - p0),
+ p0);
+ return ++base_type::m_step < base_type::m_count;
+ }
+
+ //---------------------------------------------------------------------
+ bool step_ver()
+ {
+ int dist;
+ int dx;
+ int s1 = base_type::step_ver_base(m_di);
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ *p1++ = (cover_type)base_type::m_ren.cover(s1);
+
+ dx = 1;
+ while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
+ {
+ *p1++ = (cover_type)base_type::m_ren.cover(dist);
+ ++dx;
+ }
+
+ dx = 1;
+ while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
+ {
+ *--p0 = (cover_type)base_type::m_ren.cover(dist);
+ ++dx;
+ }
+ base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
+ base_type::m_y,
+ unsigned(p1 - p0),
+ p0);
+ return ++base_type::m_step < base_type::m_count;
+ }
+
+ private:
+ line_interpolator_aa0(const line_interpolator_aa0<Renderer>&);
+ const line_interpolator_aa0<Renderer>&
+ operator = (const line_interpolator_aa0<Renderer>&);
+
+ //---------------------------------------------------------------------
+ distance_interpolator1 m_di;
+ };
+
+
+
+
+
+
+ //====================================================line_interpolator_aa1
+ template<class Renderer> class line_interpolator_aa1 :
+ public line_interpolator_aa_base<Renderer>
+ {
+ public:
+ typedef Renderer renderer_type;
+ typedef typename Renderer::color_type color_type;
+ typedef line_interpolator_aa_base<Renderer> base_type;
+
+ //---------------------------------------------------------------------
+ line_interpolator_aa1(renderer_type& ren, const line_parameters& lp,
+ int sx, int sy) :
+ line_interpolator_aa_base<Renderer>(ren, lp),
+ m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy,
+ lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
+ {
+ int dist1_start;
+ int dist2_start;
+
+ int npix = 1;
+
+ if(lp.vertical)
+ {
+ do
+ {
+ --base_type::m_li;
+ base_type::m_y -= lp.inc;
+ base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
+
+ if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
+ else m_di.inc_y(base_type::m_x - base_type::m_old_x);
+
+ base_type::m_old_x = base_type::m_x;
+
+ dist1_start = dist2_start = m_di.dist_start();
+
+ int dx = 0;
+ if(dist1_start < 0) ++npix;
+ do
+ {
+ dist1_start += m_di.dy_start();
+ dist2_start -= m_di.dy_start();
+ if(dist1_start < 0) ++npix;
+ if(dist2_start < 0) ++npix;
+ ++dx;
+ }
+ while(base_type::m_dist[dx] <= base_type::m_width);
+ --base_type::m_step;
+ if(npix == 0) break;
+ npix = 0;
+ }
+ while(base_type::m_step >= -base_type::m_max_extent);
+ }
+ else
+ {
+ do
+ {
+ --base_type::m_li;
+ base_type::m_x -= lp.inc;
+ base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
+
+ if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
+ else m_di.inc_x(base_type::m_y - base_type::m_old_y);
+
+ base_type::m_old_y = base_type::m_y;
+
+ dist1_start = dist2_start = m_di.dist_start();
+
+ int dy = 0;
+ if(dist1_start < 0) ++npix;
+ do
+ {
+ dist1_start -= m_di.dx_start();
+ dist2_start += m_di.dx_start();
+ if(dist1_start < 0) ++npix;
+ if(dist2_start < 0) ++npix;
+ ++dy;
+ }
+ while(base_type::m_dist[dy] <= base_type::m_width);
+ --base_type::m_step;
+ if(npix == 0) break;
+ npix = 0;
+ }
+ while(base_type::m_step >= -base_type::m_max_extent);
+ }
+ base_type::m_li.adjust_forward();
+ }
+
+ //---------------------------------------------------------------------
+ bool step_hor()
+ {
+ int dist_start;
+ int dist;
+ int dy;
+ int s1 = base_type::step_hor_base(m_di);
+
+ dist_start = m_di.dist_start();
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ *p1 = 0;
+ if(dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(s1);
+ }
+ ++p1;
+
+ dy = 1;
+ while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
+ {
+ dist_start -= m_di.dx_start();
+ *p1 = 0;
+ if(dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(dist);
+ }
+ ++p1;
+ ++dy;
+ }
+
+ dy = 1;
+ dist_start = m_di.dist_start();
+ while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
+ {
+ dist_start += m_di.dx_start();
+ *--p0 = 0;
+ if(dist_start <= 0)
+ {
+ *p0 = (cover_type)base_type::m_ren.cover(dist);
+ }
+ ++dy;
+ }
+
+ base_type::m_ren.blend_solid_vspan(base_type::m_x,
+ base_type::m_y - dy + 1,
+ unsigned(p1 - p0),
+ p0);
+ return ++base_type::m_step < base_type::m_count;
+ }
+
+ //---------------------------------------------------------------------
+ bool step_ver()
+ {
+ int dist_start;
+ int dist;
+ int dx;
+ int s1 = base_type::step_ver_base(m_di);
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ dist_start = m_di.dist_start();
+
+ *p1 = 0;
+ if(dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(s1);
+ }
+ ++p1;
+
+ dx = 1;
+ while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
+ {
+ dist_start += m_di.dy_start();
+ *p1 = 0;
+ if(dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(dist);
+ }
+ ++p1;
+ ++dx;
+ }
+
+ dx = 1;
+ dist_start = m_di.dist_start();
+ while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
+ {
+ dist_start -= m_di.dy_start();
+ *--p0 = 0;
+ if(dist_start <= 0)
+ {
+ *p0 = (cover_type)base_type::m_ren.cover(dist);
+ }
+ ++dx;
+ }
+ base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
+ base_type::m_y,
+ unsigned(p1 - p0),
+ p0);
+ return ++base_type::m_step < base_type::m_count;
+ }
+
+ private:
+ line_interpolator_aa1(const line_interpolator_aa1<Renderer>&);
+ const line_interpolator_aa1<Renderer>&
+ operator = (const line_interpolator_aa1<Renderer>&);
+
+ //---------------------------------------------------------------------
+ distance_interpolator2 m_di;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+ //====================================================line_interpolator_aa2
+ template<class Renderer> class line_interpolator_aa2 :
+ public line_interpolator_aa_base<Renderer>
+ {
+ public:
+ typedef Renderer renderer_type;
+ typedef typename Renderer::color_type color_type;
+ typedef line_interpolator_aa_base<Renderer> base_type;
+
+ //---------------------------------------------------------------------
+ line_interpolator_aa2(renderer_type& ren, const line_parameters& lp,
+ int ex, int ey) :
+ line_interpolator_aa_base<Renderer>(ren, lp),
+ m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey,
+ lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask,
+ 0)
+ {
+ base_type::m_li.adjust_forward();
+ base_type::m_step -= base_type::m_max_extent;
+ }
+
+ //---------------------------------------------------------------------
+ bool step_hor()
+ {
+ int dist_end;
+ int dist;
+ int dy;
+ int s1 = base_type::step_hor_base(m_di);
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ dist_end = m_di.dist_end();
+
+ int npix = 0;
+ *p1 = 0;
+ if(dist_end > 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(s1);
+ ++npix;
+ }
+ ++p1;
+
+ dy = 1;
+ while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
+ {
+ dist_end -= m_di.dx_end();
+ *p1 = 0;
+ if(dist_end > 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++p1;
+ ++dy;
+ }
+
+ dy = 1;
+ dist_end = m_di.dist_end();
+ while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
+ {
+ dist_end += m_di.dx_end();
+ *--p0 = 0;
+ if(dist_end > 0)
+ {
+ *p0 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++dy;
+ }
+ base_type::m_ren.blend_solid_vspan(base_type::m_x,
+ base_type::m_y - dy + 1,
+ unsigned(p1 - p0),
+ p0);
+ return npix && ++base_type::m_step < base_type::m_count;
+ }
+
+ //---------------------------------------------------------------------
+ bool step_ver()
+ {
+ int dist_end;
+ int dist;
+ int dx;
+ int s1 = base_type::step_ver_base(m_di);
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ dist_end = m_di.dist_end();
+
+ int npix = 0;
+ *p1 = 0;
+ if(dist_end > 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(s1);
+ ++npix;
+ }
+ ++p1;
+
+ dx = 1;
+ while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
+ {
+ dist_end += m_di.dy_end();
+ *p1 = 0;
+ if(dist_end > 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++p1;
+ ++dx;
+ }
+
+ dx = 1;
+ dist_end = m_di.dist_end();
+ while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
+ {
+ dist_end -= m_di.dy_end();
+ *--p0 = 0;
+ if(dist_end > 0)
+ {
+ *p0 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++dx;
+ }
+ base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
+ base_type::m_y,
+ unsigned(p1 - p0),
+ p0);
+ return npix && ++base_type::m_step < base_type::m_count;
+ }
+
+ private:
+ line_interpolator_aa2(const line_interpolator_aa2<Renderer>&);
+ const line_interpolator_aa2<Renderer>&
+ operator = (const line_interpolator_aa2<Renderer>&);
+
+ //---------------------------------------------------------------------
+ distance_interpolator2 m_di;
+ };
+
+
+
+
+
+
+
+
+
+
+ //====================================================line_interpolator_aa3
+ template<class Renderer> class line_interpolator_aa3 :
+ public line_interpolator_aa_base<Renderer>
+ {
+ public:
+ typedef Renderer renderer_type;
+ typedef typename Renderer::color_type color_type;
+ typedef line_interpolator_aa_base<Renderer> base_type;
+
+ //---------------------------------------------------------------------
+ line_interpolator_aa3(renderer_type& ren, const line_parameters& lp,
+ int sx, int sy, int ex, int ey) :
+ line_interpolator_aa_base<Renderer>(ren, lp),
+ m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey,
+ lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
+ {
+ int dist1_start;
+ int dist2_start;
+ int npix = 1;
+ if(lp.vertical)
+ {
+ do
+ {
+ --base_type::m_li;
+ base_type::m_y -= lp.inc;
+ base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
+
+ if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
+ else m_di.inc_y(base_type::m_x - base_type::m_old_x);
+
+ base_type::m_old_x = base_type::m_x;
+
+ dist1_start = dist2_start = m_di.dist_start();
+
+ int dx = 0;
+ if(dist1_start < 0) ++npix;
+ do
+ {
+ dist1_start += m_di.dy_start();
+ dist2_start -= m_di.dy_start();
+ if(dist1_start < 0) ++npix;
+ if(dist2_start < 0) ++npix;
+ ++dx;
+ }
+ while(base_type::m_dist[dx] <= base_type::m_width);
+ if(npix == 0) break;
+ npix = 0;
+ }
+ while(--base_type::m_step >= -base_type::m_max_extent);
+ }
+ else
+ {
+ do
+ {
+ --base_type::m_li;
+ base_type::m_x -= lp.inc;
+ base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
+
+ if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
+ else m_di.inc_x(base_type::m_y - base_type::m_old_y);
+
+ base_type::m_old_y = base_type::m_y;
+
+ dist1_start = dist2_start = m_di.dist_start();
+
+ int dy = 0;
+ if(dist1_start < 0) ++npix;
+ do
+ {
+ dist1_start -= m_di.dx_start();
+ dist2_start += m_di.dx_start();
+ if(dist1_start < 0) ++npix;
+ if(dist2_start < 0) ++npix;
+ ++dy;
+ }
+ while(base_type::m_dist[dy] <= base_type::m_width);
+ if(npix == 0) break;
+ npix = 0;
+ }
+ while(--base_type::m_step >= -base_type::m_max_extent);
+ }
+ base_type::m_li.adjust_forward();
+ base_type::m_step -= base_type::m_max_extent;
+ }
+
+
+ //---------------------------------------------------------------------
+ bool step_hor()
+ {
+ int dist_start;
+ int dist_end;
+ int dist;
+ int dy;
+ int s1 = base_type::step_hor_base(m_di);
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ dist_start = m_di.dist_start();
+ dist_end = m_di.dist_end();
+
+ int npix = 0;
+ *p1 = 0;
+ if(dist_end > 0)
+ {
+ if(dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(s1);
+ }
+ ++npix;
+ }
+ ++p1;
+
+ dy = 1;
+ while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
+ {
+ dist_start -= m_di.dx_start();
+ dist_end -= m_di.dx_end();
+ *p1 = 0;
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++p1;
+ ++dy;
+ }
+
+ dy = 1;
+ dist_start = m_di.dist_start();
+ dist_end = m_di.dist_end();
+ while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
+ {
+ dist_start += m_di.dx_start();
+ dist_end += m_di.dx_end();
+ *--p0 = 0;
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ *p0 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++dy;
+ }
+ base_type::m_ren.blend_solid_vspan(base_type::m_x,
+ base_type::m_y - dy + 1,
+ unsigned(p1 - p0),
+ p0);
+ return npix && ++base_type::m_step < base_type::m_count;
+ }
+
+ //---------------------------------------------------------------------
+ bool step_ver()
+ {
+ int dist_start;
+ int dist_end;
+ int dist;
+ int dx;
+ int s1 = base_type::step_ver_base(m_di);
+ cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
+ cover_type* p1 = p0;
+
+ dist_start = m_di.dist_start();
+ dist_end = m_di.dist_end();
+
+ int npix = 0;
+ *p1 = 0;
+ if(dist_end > 0)
+ {
+ if(dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(s1);
+ }
+ ++npix;
+ }
+ ++p1;
+
+ dx = 1;
+ while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
+ {
+ dist_start += m_di.dy_start();
+ dist_end += m_di.dy_end();
+ *p1 = 0;
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ *p1 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++p1;
+ ++dx;
+ }
+
+ dx = 1;
+ dist_start = m_di.dist_start();
+ dist_end = m_di.dist_end();
+ while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
+ {
+ dist_start -= m_di.dy_start();
+ dist_end -= m_di.dy_end();
+ *--p0 = 0;
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ *p0 = (cover_type)base_type::m_ren.cover(dist);
+ ++npix;
+ }
+ ++dx;
+ }
+ base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
+ base_type::m_y,
+ unsigned(p1 - p0),
+ p0);
+ return npix && ++base_type::m_step < base_type::m_count;
+ }
+
+ private:
+ line_interpolator_aa3(const line_interpolator_aa3<Renderer>&);
+ const line_interpolator_aa3<Renderer>&
+ operator = (const line_interpolator_aa3<Renderer>&);
+
+ //---------------------------------------------------------------------
+ distance_interpolator3 m_di;
+ };
+
+
+
+
+ //==========================================================line_profile_aa
+ //
+ // See Implementation agg_line_profile_aa.cpp
+ //
+ class line_profile_aa
+ {
+ public:
+ //---------------------------------------------------------------------
+ typedef int8u value_type;
+ enum subpixel_scale_e
+ {
+ subpixel_shift = line_subpixel_shift,
+ subpixel_scale = 1 << subpixel_shift,
+ subpixel_mask = subpixel_scale - 1
+ };
+
+ enum aa_scale_e
+ {
+ aa_shift = 8,
+ aa_scale = 1 << aa_shift,
+ aa_mask = aa_scale - 1
+ };
+
+ //---------------------------------------------------------------------
+ line_profile_aa() :
+ m_subpixel_width(0),
+ m_min_width(1.0),
+ m_smoother_width(1.0)
+ {
+ int i;
+ for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i;
+ }
+
+ //---------------------------------------------------------------------
+ template<class GammaF>
+ line_profile_aa(double w, const GammaF& gamma_function) :
+ m_subpixel_width(0),
+ m_min_width(1.0),
+ m_smoother_width(1.0)
+ {
+ gamma(gamma_function);
+ width(w);
+ }
+
+ //---------------------------------------------------------------------
+ void min_width(double w) { m_min_width = w; }
+ void smoother_width(double w) { m_smoother_width = w; }
+
+ //---------------------------------------------------------------------
+ template<class GammaF> void gamma(const GammaF& gamma_function)
+ {
+ int i;
+ for(i = 0; i < aa_scale; i++)
+ {
+ m_gamma[i] = value_type(
+ uround(gamma_function(double(i) / aa_mask) * aa_mask));
+ }
+ }
+
+ void width(double w);
+
+ unsigned profile_size() const { return m_profile.size(); }
+ int subpixel_width() const { return m_subpixel_width; }
+
+ //---------------------------------------------------------------------
+ double min_width() const { return m_min_width; }
+ double smoother_width() const { return m_smoother_width; }
+
+ //---------------------------------------------------------------------
+ value_type value(int dist) const
+ {
+ return m_profile[dist + subpixel_scale*2];
+ }
+
+ private:
+ line_profile_aa(const line_profile_aa&);
+ const line_profile_aa& operator = (const line_profile_aa&);
+
+ value_type* profile(double w);
+ void set(double center_width, double smoother_width);
+
+ //---------------------------------------------------------------------
+ pod_array<value_type> m_profile;
+ value_type m_gamma[aa_scale];
+ int m_subpixel_width;
+ double m_min_width;
+ double m_smoother_width;
+ };
+
+
+ //======================================================renderer_outline_aa
+ template<class BaseRenderer> class renderer_outline_aa
+ {
+ public:
+ //---------------------------------------------------------------------
+ typedef BaseRenderer base_ren_type;
+ typedef renderer_outline_aa<base_ren_type> self_type;
+ typedef typename base_ren_type::color_type color_type;
+
+ //---------------------------------------------------------------------
+ renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) :
+ m_ren(&ren),
+ m_profile(&prof),
+ m_clip_box(0,0,0,0),
+ m_clipping(false)
+ {}
+ void attach(base_ren_type& ren) { m_ren = &ren; }
+
+ //---------------------------------------------------------------------
+ void color(const color_type& c) { m_color = c; }
+ const color_type& color() const { return m_color; }
+
+ //---------------------------------------------------------------------
+ void profile(const line_profile_aa& prof) { m_profile = &prof; }
+ const line_profile_aa& profile() const { return *m_profile; }
+ line_profile_aa& profile() { return *m_profile; }
+
+ //---------------------------------------------------------------------
+ int subpixel_width() const { return m_profile->subpixel_width(); }
+
+ //---------------------------------------------------------------------
+ void reset_clipping() { m_clipping = false; }
+ void clip_box(double x1, double y1, double x2, double y2)
+ {
+ m_clip_box.x1 = line_coord_sat::conv(x1);
+ m_clip_box.y1 = line_coord_sat::conv(y1);
+ m_clip_box.x2 = line_coord_sat::conv(x2);
+ m_clip_box.y2 = line_coord_sat::conv(y2);
+ m_clipping = true;
+ }
+
+ //---------------------------------------------------------------------
+ int cover(int d) const
+ {
+ return m_profile->value(d);
+ }
+
+ //-------------------------------------------------------------------------
+ void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers)
+ {
+ m_ren->blend_solid_hspan(x, y, len, m_color, covers);
+ }
+
+ //-------------------------------------------------------------------------
+ void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers)
+ {
+ m_ren->blend_solid_vspan(x, y, len, m_color, covers);
+ }
+
+ //-------------------------------------------------------------------------
+ static bool accurate_join_only() { return false; }
+
+ //-------------------------------------------------------------------------
+ template<class Cmp>
+ void semidot_hline(Cmp cmp,
+ int xc1, int yc1, int xc2, int yc2,
+ int x1, int y1, int x2)
+ {
+ cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
+ cover_type* p0 = covers;
+ cover_type* p1 = covers;
+ int x = x1 << line_subpixel_shift;
+ int y = y1 << line_subpixel_shift;
+ int w = subpixel_width();
+ distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y);
+ x += line_subpixel_scale/2;
+ y += line_subpixel_scale/2;
+
+ int x0 = x1;
+ int dx = x - xc1;
+ int dy = y - yc1;
+ do
+ {
+ int d = int(fast_sqrt(dx*dx + dy*dy));
+ *p1 = 0;
+ if(cmp(di.dist()) && d <= w)
+ {
+ *p1 = (cover_type)cover(d);
+ }
+ ++p1;
+ dx += line_subpixel_scale;
+ di.inc_x();
+ }
+ while(++x1 <= x2);
+ m_ren->blend_solid_hspan(x0, y1,
+ unsigned(p1 - p0),
+ color(),
+ p0);
+ }
+
+ //-------------------------------------------------------------------------
+ template<class Cmp>
+ void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2)
+ {
+ if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return;
+
+ int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
+ if(r < 1) r = 1;
+ ellipse_bresenham_interpolator ei(r, r);
+ int dx = 0;
+ int dy = -r;
+ int dy0 = dy;
+ int dx0 = dx;
+ int x = xc1 >> line_subpixel_shift;
+ int y = yc1 >> line_subpixel_shift;
+
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ if(dy != dy0)
+ {
+ semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
+ semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0);
+ }
+ dx0 = dx;
+ dy0 = dy;
+ ++ei;
+ }
+ while(dy < 0);
+ semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
+ }
+
+ //-------------------------------------------------------------------------
+ void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2,
+ int xh1, int yh1, int xh2)
+ {
+ if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return;
+
+ cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
+ cover_type* p0 = covers;
+ cover_type* p1 = covers;
+ int x = xh1 << line_subpixel_shift;
+ int y = yh1 << line_subpixel_shift;
+ int w = subpixel_width();
+
+ distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y);
+ x += line_subpixel_scale/2;
+ y += line_subpixel_scale/2;
+
+ int xh0 = xh1;
+ int dx = x - xc;
+ int dy = y - yc;
+ do
+ {
+ int d = int(fast_sqrt(dx*dx + dy*dy));
+ *p1 = 0;
+ if(di.dist1() <= 0 && di.dist2() > 0 && d <= w)
+ {
+ *p1 = (cover_type)cover(d);
+ }
+ ++p1;
+ dx += line_subpixel_scale;
+ di.inc_x();
+ }
+ while(++xh1 <= xh2);
+ m_ren->blend_solid_hspan(xh0, yh1,
+ unsigned(p1 - p0),
+ color(),
+ p0);
+ }
+
+
+ //-------------------------------------------------------------------------
+ void pie(int xc, int yc, int x1, int y1, int x2, int y2)
+ {
+ int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
+ if(r < 1) r = 1;
+ ellipse_bresenham_interpolator ei(r, r);
+ int dx = 0;
+ int dy = -r;
+ int dy0 = dy;
+ int dx0 = dx;
+ int x = xc >> line_subpixel_shift;
+ int y = yc >> line_subpixel_shift;
+
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ if(dy != dy0)
+ {
+ pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
+ pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0);
+ }
+ dx0 = dx;
+ dy0 = dy;
+ ++ei;
+ }
+ while(dy < 0);
+ pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
+ }
+
+ //-------------------------------------------------------------------------
+ void line0_no_clip(const line_parameters& lp)
+ {
+ if(lp.len > line_max_length)
+ {
+ line_parameters lp1, lp2;
+ lp.divide(lp1, lp2);
+ line0_no_clip(lp1);
+ line0_no_clip(lp2);
+ return;
+ }
+
+ line_interpolator_aa0<self_type> li(*this, lp);
+ if(li.count())
+ {
+ if(li.vertical())
+ {
+ while(li.step_ver());
+ }
+ else
+ {
+ while(li.step_hor());
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void line0(const line_parameters& lp)
+ {
+ if(m_clipping)
+ {
+ int x1 = lp.x1;
+ int y1 = lp.y1;
+ int x2 = lp.x2;
+ int y2 = lp.y2;
+ unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
+ if((flags & 4) == 0)
+ {
+ if(flags)
+ {
+ line_parameters lp2(x1, y1, x2, y2,
+ uround(calc_distance(x1, y1, x2, y2)));
+ line0_no_clip(lp2);
+ }
+ else
+ {
+ line0_no_clip(lp);
+ }
+ }
+ }
+ else
+ {
+ line0_no_clip(lp);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void line1_no_clip(const line_parameters& lp, int sx, int sy)
+ {
+ if(lp.len > line_max_length)
+ {
+ line_parameters lp1, lp2;
+ lp.divide(lp1, lp2);
+ line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1);
+ line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
+ return;
+ }
+
+ fix_degenerate_bisectrix_start(lp, &sx, &sy);
+ line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
+ if(li.vertical())
+ {
+ while(li.step_ver());
+ }
+ else
+ {
+ while(li.step_hor());
+ }
+ }
+
+
+ //-------------------------------------------------------------------------
+ void line1(const line_parameters& lp, int sx, int sy)
+ {
+ if(m_clipping)
+ {
+ int x1 = lp.x1;
+ int y1 = lp.y1;
+ int x2 = lp.x2;
+ int y2 = lp.y2;
+ unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
+ if((flags & 4) == 0)
+ {
+ if(flags)
+ {
+ line_parameters lp2(x1, y1, x2, y2,
+ uround(calc_distance(x1, y1, x2, y2)));
+ if(flags & 1)
+ {
+ sx = x1 + (y2 - y1);
+ sy = y1 - (x2 - x1);
+ }
+ else
+ {
+ while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
+ {
+ sx = (lp.x1 + sx) >> 1;
+ sy = (lp.y1 + sy) >> 1;
+ }
+ }
+ line1_no_clip(lp2, sx, sy);
+ }
+ else
+ {
+ line1_no_clip(lp, sx, sy);
+ }
+ }
+ }
+ else
+ {
+ line1_no_clip(lp, sx, sy);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void line2_no_clip(const line_parameters& lp, int ex, int ey)
+ {
+ if(lp.len > line_max_length)
+ {
+ line_parameters lp1, lp2;
+ lp.divide(lp1, lp2);
+ line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
+ line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
+ return;
+ }
+
+ fix_degenerate_bisectrix_end(lp, &ex, &ey);
+ line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
+ if(li.vertical())
+ {
+ while(li.step_ver());
+ }
+ else
+ {
+ while(li.step_hor());
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void line2(const line_parameters& lp, int ex, int ey)
+ {
+ if(m_clipping)
+ {
+ int x1 = lp.x1;
+ int y1 = lp.y1;
+ int x2 = lp.x2;
+ int y2 = lp.y2;
+ unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
+ if((flags & 4) == 0)
+ {
+ if(flags)
+ {
+ line_parameters lp2(x1, y1, x2, y2,
+ uround(calc_distance(x1, y1, x2, y2)));
+ if(flags & 2)
+ {
+ ex = x2 + (y2 - y1);
+ ey = y2 - (x2 - x1);
+ }
+ else
+ {
+ while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
+ {
+ ex = (lp.x2 + ex) >> 1;
+ ey = (lp.y2 + ey) >> 1;
+ }
+ }
+ line2_no_clip(lp2, ex, ey);
+ }
+ else
+ {
+ line2_no_clip(lp, ex, ey);
+ }
+ }
+ }
+ else
+ {
+ line2_no_clip(lp, ex, ey);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void line3_no_clip(const line_parameters& lp,
+ int sx, int sy, int ex, int ey)
+ {
+ if(lp.len > line_max_length)
+ {
+ line_parameters lp1, lp2;
+ lp.divide(lp1, lp2);
+ int mx = lp1.x2 + (lp1.y2 - lp1.y1);
+ int my = lp1.y2 - (lp1.x2 - lp1.x1);
+ line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
+ line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
+ return;
+ }
+
+ fix_degenerate_bisectrix_start(lp, &sx, &sy);
+ fix_degenerate_bisectrix_end(lp, &ex, &ey);
+ line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey);
+ if(li.vertical())
+ {
+ while(li.step_ver());
+ }
+ else
+ {
+ while(li.step_hor());
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void line3(const line_parameters& lp,
+ int sx, int sy, int ex, int ey)
+ {
+ if(m_clipping)
+ {
+ int x1 = lp.x1;
+ int y1 = lp.y1;
+ int x2 = lp.x2;
+ int y2 = lp.y2;
+ unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
+ if((flags & 4) == 0)
+ {
+ if(flags)
+ {
+ line_parameters lp2(x1, y1, x2, y2,
+ uround(calc_distance(x1, y1, x2, y2)));
+ if(flags & 1)
+ {
+ sx = x1 + (y2 - y1);
+ sy = y1 - (x2 - x1);
+ }
+ else
+ {
+ while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
+ {
+ sx = (lp.x1 + sx) >> 1;
+ sy = (lp.y1 + sy) >> 1;
+ }
+ }
+ if(flags & 2)
+ {
+ ex = x2 + (y2 - y1);
+ ey = y2 - (x2 - x1);
+ }
+ else
+ {
+ while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
+ {
+ ex = (lp.x2 + ex) >> 1;
+ ey = (lp.y2 + ey) >> 1;
+ }
+ }
+ line3_no_clip(lp2, sx, sy, ex, ey);
+ }
+ else
+ {
+ line3_no_clip(lp, sx, sy, ex, ey);
+ }
+ }
+ }
+ else
+ {
+ line3_no_clip(lp, sx, sy, ex, ey);
+ }
+ }
+
+
+ private:
+ base_ren_type* m_ren;
+ const line_profile_aa* m_profile;
+ color_type m_color;
+ rect_i m_clip_box;
+ bool m_clipping;
+ };
+
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_outline_image.h b/plugins/Clist_ng/AGG/include/agg_renderer_outline_image.h new file mode 100644 index 0000000000..cedf6e83f6 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_outline_image.h @@ -0,0 +1,1023 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
+#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
+
+#include "agg_array.h"
+#include "agg_math.h"
+#include "agg_line_aa_basics.h"
+#include "agg_dda_line.h"
+#include "agg_rendering_buffer.h"
+#include "agg_clip_liang_barsky.h"
+
+
+namespace agg
+{
+ //========================================================line_image_scale
+ template<class Source> class line_image_scale
+ {
+ public:
+ typedef typename Source::color_type color_type;
+
+ line_image_scale(const Source& src, double height) :
+ m_source(src),
+ m_height(height),
+ m_scale(src.height() / height)
+ {
+ }
+
+ double width() const { return m_source.width(); }
+ double height() const { return m_height; }
+
+ color_type pixel(int x, int y) const
+ {
+ double src_y = (y + 0.5) * m_scale - 0.5;
+ int h = m_source.height() - 1;
+ int y1 = ufloor(src_y);
+ int y2 = y1 + 1;
+ color_type pix1 = (y1 < 0) ? color_type::no_color() : m_source.pixel(x, y1);
+ color_type pix2 = (y2 > h) ? color_type::no_color() : m_source.pixel(x, y2);
+ return pix1.gradient(pix2, src_y - y1);
+ }
+
+ private:
+ line_image_scale(const line_image_scale<Source>&);
+ const line_image_scale<Source>& operator = (const line_image_scale<Source>&);
+
+ const Source& m_source;
+ double m_height;
+ double m_scale;
+ };
+
+
+
+ //======================================================line_image_pattern
+ template<class Filter> class line_image_pattern
+ {
+ public:
+ typedef Filter filter_type;
+ typedef typename filter_type::color_type color_type;
+
+ //--------------------------------------------------------------------
+ line_image_pattern(const Filter& filter) :
+ m_filter(&filter),
+ m_dilation(filter.dilation() + 1),
+ m_dilation_hr(m_dilation << line_subpixel_shift),
+ m_data(),
+ m_width(0),
+ m_height(0),
+ m_width_hr(0),
+ m_half_height_hr(0),
+ m_offset_y_hr(0)
+ {
+ }
+
+ // Create
+ //--------------------------------------------------------------------
+ template<class Source>
+ line_image_pattern(const Filter& filter, const Source& src) :
+ m_filter(&filter),
+ m_dilation(filter.dilation() + 1),
+ m_dilation_hr(m_dilation << line_subpixel_shift),
+ m_data(),
+ m_width(0),
+ m_height(0),
+ m_width_hr(0),
+ m_half_height_hr(0),
+ m_offset_y_hr(0)
+ {
+ create(src);
+ }
+
+ // Create
+ //--------------------------------------------------------------------
+ template<class Source> void create(const Source& src)
+ {
+ m_height = uceil(src.height());
+ m_width = uceil(src.width());
+ m_width_hr = uround(src.width() * line_subpixel_scale);
+ m_half_height_hr = uround(src.height() * line_subpixel_scale/2);
+ m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2;
+ m_half_height_hr += line_subpixel_scale/2;
+
+ m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2));
+
+ m_buf.attach(&m_data[0], m_width + m_dilation * 2,
+ m_height + m_dilation * 2,
+ m_width + m_dilation * 2);
+ unsigned x, y;
+ color_type* d1;
+ color_type* d2;
+ for(y = 0; y < m_height; y++)
+ {
+ d1 = m_buf.row_ptr(y + m_dilation) + m_dilation;
+ for(x = 0; x < m_width; x++)
+ {
+ *d1++ = src.pixel(x, y);
+ }
+ }
+
+ const color_type* s1;
+ const color_type* s2;
+ for(y = 0; y < m_dilation; y++)
+ {
+ //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation;
+ //s2 = m_buf.row_ptr(m_dilation) + m_dilation;
+ d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation;
+ d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation;
+ for(x = 0; x < m_width; x++)
+ {
+ //*d1++ = color_type(*s1++, 0);
+ //*d2++ = color_type(*s2++, 0);
+ *d1++ = color_type::no_color();
+ *d2++ = color_type::no_color();
+ }
+ }
+
+ unsigned h = m_height + m_dilation * 2;
+ for(y = 0; y < h; y++)
+ {
+ s1 = m_buf.row_ptr(y) + m_dilation;
+ s2 = m_buf.row_ptr(y) + m_dilation + m_width;
+ d1 = m_buf.row_ptr(y) + m_dilation + m_width;
+ d2 = m_buf.row_ptr(y) + m_dilation;
+
+ for(x = 0; x < m_dilation; x++)
+ {
+ *d1++ = *s1++;
+ *--d2 = *--s2;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ int pattern_width() const { return m_width_hr; }
+ int line_width() const { return m_half_height_hr; }
+ double width() const { return m_height; }
+
+ //--------------------------------------------------------------------
+ void pixel(color_type* p, int x, int y) const
+ {
+ m_filter->pixel_high_res(m_buf.rows(),
+ p,
+ x % m_width_hr + m_dilation_hr,
+ y + m_offset_y_hr);
+ }
+
+ //--------------------------------------------------------------------
+ const filter_type& filter() const { return *m_filter; }
+
+ private:
+ line_image_pattern(const line_image_pattern<filter_type>&);
+ const line_image_pattern<filter_type>&
+ operator = (const line_image_pattern<filter_type>&);
+
+ protected:
+ row_ptr_cache<color_type> m_buf;
+ const filter_type* m_filter;
+ unsigned m_dilation;
+ int m_dilation_hr;
+ pod_array<color_type> m_data;
+ unsigned m_width;
+ unsigned m_height;
+ int m_width_hr;
+ int m_half_height_hr;
+ int m_offset_y_hr;
+ };
+
+
+
+
+
+
+ //=================================================line_image_pattern_pow2
+ template<class Filter> class line_image_pattern_pow2 :
+ public line_image_pattern<Filter>
+ {
+ public:
+ typedef Filter filter_type;
+ typedef typename filter_type::color_type color_type;
+ typedef line_image_pattern<Filter> base_type;
+
+ //--------------------------------------------------------------------
+ line_image_pattern_pow2(const Filter& filter) :
+ line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {}
+
+ //--------------------------------------------------------------------
+ template<class Source>
+ line_image_pattern_pow2(const Filter& filter, const Source& src) :
+ line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask)
+ {
+ create(src);
+ }
+
+ //--------------------------------------------------------------------
+ template<class Source> void create(const Source& src)
+ {
+ line_image_pattern<Filter>::create(src);
+ m_mask = 1;
+ while(m_mask < base_type::m_width)
+ {
+ m_mask <<= 1;
+ m_mask |= 1;
+ }
+ m_mask <<= line_subpixel_shift - 1;
+ m_mask |= line_subpixel_mask;
+ base_type::m_width_hr = m_mask + 1;
+ }
+
+ //--------------------------------------------------------------------
+ void pixel(color_type* p, int x, int y) const
+ {
+ base_type::m_filter->pixel_high_res(
+ base_type::m_buf.rows(),
+ p,
+ (x & m_mask) + base_type::m_dilation_hr,
+ y + base_type::m_offset_y_hr);
+ }
+ private:
+ unsigned m_mask;
+ };
+
+
+
+
+
+
+
+ //===================================================distance_interpolator4
+ class distance_interpolator4
+ {
+ public:
+ //---------------------------------------------------------------------
+ distance_interpolator4() {}
+ distance_interpolator4(int x1, int y1, int x2, int y2,
+ int sx, int sy, int ex, int ey,
+ int len, double scale, int x, int y) :
+ m_dx(x2 - x1),
+ m_dy(y2 - y1),
+ m_dx_start(line_mr(sx) - line_mr(x1)),
+ m_dy_start(line_mr(sy) - line_mr(y1)),
+ m_dx_end(line_mr(ex) - line_mr(x2)),
+ m_dy_end(line_mr(ey) - line_mr(y2)),
+
+ m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
+ double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
+
+ m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
+
+ m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end -
+ (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end),
+ m_len(uround(len / scale))
+ {
+ double d = len * scale;
+ int dx = iround(((x2 - x1) << line_subpixel_shift) / d);
+ int dy = iround(((y2 - y1) << line_subpixel_shift) / d);
+ m_dx_pict = -dy;
+ m_dy_pict = dx;
+ m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict -
+ (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >>
+ line_subpixel_shift;
+
+ m_dx <<= line_subpixel_shift;
+ m_dy <<= line_subpixel_shift;
+ m_dx_start <<= line_mr_subpixel_shift;
+ m_dy_start <<= line_mr_subpixel_shift;
+ m_dx_end <<= line_mr_subpixel_shift;
+ m_dy_end <<= line_mr_subpixel_shift;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_x()
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ m_dist_pict += m_dy_pict;
+ m_dist_end += m_dy_end;
+ }
+
+ //---------------------------------------------------------------------
+ void dec_x()
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ m_dist_pict -= m_dy_pict;
+ m_dist_end -= m_dy_end;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_y()
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ m_dist_pict -= m_dx_pict;
+ m_dist_end -= m_dx_end;
+ }
+
+ //---------------------------------------------------------------------
+ void dec_y()
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ m_dist_pict += m_dx_pict;
+ m_dist_end += m_dx_end;
+ }
+
+ //---------------------------------------------------------------------
+ void inc_x(int dy)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ m_dist_pict += m_dy_pict;
+ m_dist_end += m_dy_end;
+ if(dy > 0)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ m_dist_pict -= m_dx_pict;
+ m_dist_end -= m_dx_end;
+ }
+ if(dy < 0)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ m_dist_pict += m_dx_pict;
+ m_dist_end += m_dx_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void dec_x(int dy)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ m_dist_pict -= m_dy_pict;
+ m_dist_end -= m_dy_end;
+ if(dy > 0)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ m_dist_pict -= m_dx_pict;
+ m_dist_end -= m_dx_end;
+ }
+ if(dy < 0)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ m_dist_pict += m_dx_pict;
+ m_dist_end += m_dx_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void inc_y(int dx)
+ {
+ m_dist -= m_dx;
+ m_dist_start -= m_dx_start;
+ m_dist_pict -= m_dx_pict;
+ m_dist_end -= m_dx_end;
+ if(dx > 0)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ m_dist_pict += m_dy_pict;
+ m_dist_end += m_dy_end;
+ }
+ if(dx < 0)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ m_dist_pict -= m_dy_pict;
+ m_dist_end -= m_dy_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void dec_y(int dx)
+ {
+ m_dist += m_dx;
+ m_dist_start += m_dx_start;
+ m_dist_pict += m_dx_pict;
+ m_dist_end += m_dx_end;
+ if(dx > 0)
+ {
+ m_dist += m_dy;
+ m_dist_start += m_dy_start;
+ m_dist_pict += m_dy_pict;
+ m_dist_end += m_dy_end;
+ }
+ if(dx < 0)
+ {
+ m_dist -= m_dy;
+ m_dist_start -= m_dy_start;
+ m_dist_pict -= m_dy_pict;
+ m_dist_end -= m_dy_end;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ int dist() const { return m_dist; }
+ int dist_start() const { return m_dist_start; }
+ int dist_pict() const { return m_dist_pict; }
+ int dist_end() const { return m_dist_end; }
+
+ //---------------------------------------------------------------------
+ int dx() const { return m_dx; }
+ int dy() const { return m_dy; }
+ int dx_start() const { return m_dx_start; }
+ int dy_start() const { return m_dy_start; }
+ int dx_pict() const { return m_dx_pict; }
+ int dy_pict() const { return m_dy_pict; }
+ int dx_end() const { return m_dx_end; }
+ int dy_end() const { return m_dy_end; }
+ int len() const { return m_len; }
+
+ private:
+ //---------------------------------------------------------------------
+ int m_dx;
+ int m_dy;
+ int m_dx_start;
+ int m_dy_start;
+ int m_dx_pict;
+ int m_dy_pict;
+ int m_dx_end;
+ int m_dy_end;
+
+ int m_dist;
+ int m_dist_start;
+ int m_dist_pict;
+ int m_dist_end;
+ int m_len;
+ };
+
+
+
+
+
+ //==================================================line_interpolator_image
+ template<class Renderer> class line_interpolator_image
+ {
+ public:
+ typedef Renderer renderer_type;
+ typedef typename Renderer::color_type color_type;
+
+ //---------------------------------------------------------------------
+ enum max_half_width_e
+ {
+ max_half_width = 64
+ };
+
+ //---------------------------------------------------------------------
+ line_interpolator_image(renderer_type& ren, const line_parameters& lp,
+ int sx, int sy, int ex, int ey,
+ int pattern_start,
+ double scale_x) :
+ m_lp(lp),
+ m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
+ line_dbl_hr(lp.y2 - lp.y1),
+ lp.vertical ? abs(lp.y2 - lp.y1) :
+ abs(lp.x2 - lp.x1) + 1),
+ m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
+ lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask),
+ m_ren(ren),
+ m_x(lp.x1 >> line_subpixel_shift),
+ m_y(lp.y1 >> line_subpixel_shift),
+ m_old_x(m_x),
+ m_old_y(m_y),
+ m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
+ abs((lp.x2 >> line_subpixel_shift) - m_x))),
+ m_width(ren.subpixel_width()),
+ //m_max_extent(m_width >> (line_subpixel_shift - 2)),
+ m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift),
+ m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()),
+ m_step(0)
+ {
+ agg::dda2_line_interpolator li(0, lp.vertical ?
+ (lp.dy << agg::line_subpixel_shift) :
+ (lp.dx << agg::line_subpixel_shift),
+ lp.len);
+
+ unsigned i;
+ int stop = m_width + line_subpixel_scale * 2;
+ for(i = 0; i < max_half_width; ++i)
+ {
+ m_dist_pos[i] = li.y();
+ if(m_dist_pos[i] >= stop) break;
+ ++li;
+ }
+ m_dist_pos[i] = 0x7FFF0000;
+
+ int dist1_start;
+ int dist2_start;
+ int npix = 1;
+
+ if(lp.vertical)
+ {
+ do
+ {
+ --m_li;
+ m_y -= lp.inc;
+ m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
+
+ if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
+ else m_di.inc_y(m_x - m_old_x);
+
+ m_old_x = m_x;
+
+ dist1_start = dist2_start = m_di.dist_start();
+
+ int dx = 0;
+ if(dist1_start < 0) ++npix;
+ do
+ {
+ dist1_start += m_di.dy_start();
+ dist2_start -= m_di.dy_start();
+ if(dist1_start < 0) ++npix;
+ if(dist2_start < 0) ++npix;
+ ++dx;
+ }
+ while(m_dist_pos[dx] <= m_width);
+ if(npix == 0) break;
+
+ npix = 0;
+ }
+ while(--m_step >= -m_max_extent);
+ }
+ else
+ {
+ do
+ {
+ --m_li;
+
+ m_x -= lp.inc;
+ m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
+
+ if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
+ else m_di.inc_x(m_y - m_old_y);
+
+ m_old_y = m_y;
+
+ dist1_start = dist2_start = m_di.dist_start();
+
+ int dy = 0;
+ if(dist1_start < 0) ++npix;
+ do
+ {
+ dist1_start -= m_di.dx_start();
+ dist2_start += m_di.dx_start();
+ if(dist1_start < 0) ++npix;
+ if(dist2_start < 0) ++npix;
+ ++dy;
+ }
+ while(m_dist_pos[dy] <= m_width);
+ if(npix == 0) break;
+
+ npix = 0;
+ }
+ while(--m_step >= -m_max_extent);
+ }
+ m_li.adjust_forward();
+ m_step -= m_max_extent;
+ }
+
+ //---------------------------------------------------------------------
+ bool step_hor()
+ {
+ ++m_li;
+ m_x += m_lp.inc;
+ m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
+
+ if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y);
+ else m_di.dec_x(m_y - m_old_y);
+
+ m_old_y = m_y;
+
+ int s1 = m_di.dist() / m_lp.len;
+ int s2 = -s1;
+
+ if(m_lp.inc < 0) s1 = -s1;
+
+ int dist_start;
+ int dist_pict;
+ int dist_end;
+ int dy;
+ int dist;
+
+ dist_start = m_di.dist_start();
+ dist_pict = m_di.dist_pict() + m_start;
+ dist_end = m_di.dist_end();
+ color_type* p0 = m_colors + max_half_width + 2;
+ color_type* p1 = p0;
+
+ int npix = 0;
+ p1->clear();
+ if(dist_end > 0)
+ {
+ if(dist_start <= 0)
+ {
+ m_ren.pixel(p1, dist_pict, s2);
+ }
+ ++npix;
+ }
+ ++p1;
+
+ dy = 1;
+ while((dist = m_dist_pos[dy]) - s1 <= m_width)
+ {
+ dist_start -= m_di.dx_start();
+ dist_pict -= m_di.dx_pict();
+ dist_end -= m_di.dx_end();
+ p1->clear();
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ if(m_lp.inc > 0) dist = -dist;
+ m_ren.pixel(p1, dist_pict, s2 - dist);
+ ++npix;
+ }
+ ++p1;
+ ++dy;
+ }
+
+ dy = 1;
+ dist_start = m_di.dist_start();
+ dist_pict = m_di.dist_pict() + m_start;
+ dist_end = m_di.dist_end();
+ while((dist = m_dist_pos[dy]) + s1 <= m_width)
+ {
+ dist_start += m_di.dx_start();
+ dist_pict += m_di.dx_pict();
+ dist_end += m_di.dx_end();
+ --p0;
+ p0->clear();
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ if(m_lp.inc > 0) dist = -dist;
+ m_ren.pixel(p0, dist_pict, s2 + dist);
+ ++npix;
+ }
+ ++dy;
+ }
+ m_ren.blend_color_vspan(m_x,
+ m_y - dy + 1,
+ unsigned(p1 - p0),
+ p0);
+ return npix && ++m_step < m_count;
+ }
+
+
+
+ //---------------------------------------------------------------------
+ bool step_ver()
+ {
+ ++m_li;
+ m_y += m_lp.inc;
+ m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
+
+ if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x);
+ else m_di.dec_y(m_x - m_old_x);
+
+ m_old_x = m_x;
+
+ int s1 = m_di.dist() / m_lp.len;
+ int s2 = -s1;
+
+ if(m_lp.inc > 0) s1 = -s1;
+
+ int dist_start;
+ int dist_pict;
+ int dist_end;
+ int dist;
+ int dx;
+
+ dist_start = m_di.dist_start();
+ dist_pict = m_di.dist_pict() + m_start;
+ dist_end = m_di.dist_end();
+ color_type* p0 = m_colors + max_half_width + 2;
+ color_type* p1 = p0;
+
+ int npix = 0;
+ p1->clear();
+ if(dist_end > 0)
+ {
+ if(dist_start <= 0)
+ {
+ m_ren.pixel(p1, dist_pict, s2);
+ }
+ ++npix;
+ }
+ ++p1;
+
+ dx = 1;
+ while((dist = m_dist_pos[dx]) - s1 <= m_width)
+ {
+ dist_start += m_di.dy_start();
+ dist_pict += m_di.dy_pict();
+ dist_end += m_di.dy_end();
+ p1->clear();
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ if(m_lp.inc > 0) dist = -dist;
+ m_ren.pixel(p1, dist_pict, s2 + dist);
+ ++npix;
+ }
+ ++p1;
+ ++dx;
+ }
+
+ dx = 1;
+ dist_start = m_di.dist_start();
+ dist_pict = m_di.dist_pict() + m_start;
+ dist_end = m_di.dist_end();
+ while((dist = m_dist_pos[dx]) + s1 <= m_width)
+ {
+ dist_start -= m_di.dy_start();
+ dist_pict -= m_di.dy_pict();
+ dist_end -= m_di.dy_end();
+ --p0;
+ p0->clear();
+ if(dist_end > 0 && dist_start <= 0)
+ {
+ if(m_lp.inc > 0) dist = -dist;
+ m_ren.pixel(p0, dist_pict, s2 - dist);
+ ++npix;
+ }
+ ++dx;
+ }
+ m_ren.blend_color_hspan(m_x - dx + 1,
+ m_y,
+ unsigned(p1 - p0),
+ p0);
+ return npix && ++m_step < m_count;
+ }
+
+
+ //---------------------------------------------------------------------
+ int pattern_end() const { return m_start + m_di.len(); }
+
+ //---------------------------------------------------------------------
+ bool vertical() const { return m_lp.vertical; }
+ int width() const { return m_width; }
+ int count() const { return m_count; }
+
+ private:
+ line_interpolator_image(const line_interpolator_image<Renderer>&);
+ const line_interpolator_image<Renderer>&
+ operator = (const line_interpolator_image<Renderer>&);
+
+ protected:
+ const line_parameters& m_lp;
+ dda2_line_interpolator m_li;
+ distance_interpolator4 m_di;
+ renderer_type& m_ren;
+ int m_plen;
+ int m_x;
+ int m_y;
+ int m_old_x;
+ int m_old_y;
+ int m_count;
+ int m_width;
+ int m_max_extent;
+ int m_start;
+ int m_step;
+ int m_dist_pos[max_half_width + 1];
+ color_type m_colors[max_half_width * 2 + 4];
+ };
+
+
+
+
+
+
+
+
+ //===================================================renderer_outline_image
+ template<class BaseRenderer, class ImagePattern>
+ class renderer_outline_image
+ {
+ public:
+ //---------------------------------------------------------------------
+ typedef BaseRenderer base_ren_type;
+ typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type;
+ typedef typename base_ren_type::color_type color_type;
+ typedef ImagePattern pattern_type;
+
+
+ //---------------------------------------------------------------------
+ renderer_outline_image(base_ren_type& ren, const pattern_type& patt) :
+ m_ren(&ren),
+ m_pattern(&patt),
+ m_start(0),
+ m_scale_x(1.0),
+ m_clip_box(0,0,0,0),
+ m_clipping(false)
+ {}
+ void attach(base_ren_type& ren) { m_ren = &ren; }
+
+ //---------------------------------------------------------------------
+ void pattern(const pattern_type& p) { m_pattern = &p; }
+ const pattern_type& pattern() const { return *m_pattern; }
+
+ //---------------------------------------------------------------------
+ void reset_clipping() { m_clipping = false; }
+ void clip_box(double x1, double y1, double x2, double y2)
+ {
+ m_clip_box.x1 = line_coord_sat::conv(x1);
+ m_clip_box.y1 = line_coord_sat::conv(y1);
+ m_clip_box.x2 = line_coord_sat::conv(x2);
+ m_clip_box.y2 = line_coord_sat::conv(y2);
+ m_clipping = true;
+ }
+
+ //---------------------------------------------------------------------
+ void scale_x(double s) { m_scale_x = s; }
+ double scale_x() const { return m_scale_x; }
+
+ //---------------------------------------------------------------------
+ void start_x(double s) { m_start = iround(s * line_subpixel_scale); }
+ double start_x() const { return double(m_start) / line_subpixel_scale; }
+
+ //---------------------------------------------------------------------
+ int subpixel_width() const { return m_pattern->line_width(); }
+ int pattern_width() const { return m_pattern->pattern_width(); }
+ double width() const { return double(subpixel_width()) / line_subpixel_scale; }
+
+ //-------------------------------------------------------------------------
+ void pixel(color_type* p, int x, int y) const
+ {
+ m_pattern->pixel(p, x, y);
+ }
+
+ //-------------------------------------------------------------------------
+ void blend_color_hspan(int x, int y, unsigned len, const color_type* colors)
+ {
+ m_ren->blend_color_hspan(x, y, len, colors, 0);
+ }
+
+ //-------------------------------------------------------------------------
+ void blend_color_vspan(int x, int y, unsigned len, const color_type* colors)
+ {
+ m_ren->blend_color_vspan(x, y, len, colors, 0);
+ }
+
+ //-------------------------------------------------------------------------
+ static bool accurate_join_only() { return true; }
+
+ //-------------------------------------------------------------------------
+ template<class Cmp>
+ void semidot(Cmp, int, int, int, int)
+ {
+ }
+
+ //-------------------------------------------------------------------------
+ void pie(int, int, int, int, int, int)
+ {
+ }
+
+ //-------------------------------------------------------------------------
+ void line0(const line_parameters&)
+ {
+ }
+
+ //-------------------------------------------------------------------------
+ void line1(const line_parameters&, int, int)
+ {
+ }
+
+ //-------------------------------------------------------------------------
+ void line2(const line_parameters&, int, int)
+ {
+ }
+
+ //-------------------------------------------------------------------------
+ void line3_no_clip(const line_parameters& lp,
+ int sx, int sy, int ex, int ey)
+ {
+ if(lp.len > line_max_length)
+ {
+ line_parameters lp1, lp2;
+ lp.divide(lp1, lp2);
+ int mx = lp1.x2 + (lp1.y2 - lp1.y1);
+ int my = lp1.y2 - (lp1.x2 - lp1.x1);
+ line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
+ line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
+ return;
+ }
+
+ fix_degenerate_bisectrix_start(lp, &sx, &sy);
+ fix_degenerate_bisectrix_end(lp, &ex, &ey);
+ line_interpolator_image<self_type> li(*this, lp,
+ sx, sy,
+ ex, ey,
+ m_start, m_scale_x);
+ if(li.vertical())
+ {
+ while(li.step_ver());
+ }
+ else
+ {
+ while(li.step_hor());
+ }
+ m_start += uround(lp.len / m_scale_x);
+ }
+
+ //-------------------------------------------------------------------------
+ void line3(const line_parameters& lp,
+ int sx, int sy, int ex, int ey)
+ {
+ if(m_clipping)
+ {
+ int x1 = lp.x1;
+ int y1 = lp.y1;
+ int x2 = lp.x2;
+ int y2 = lp.y2;
+ unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
+ int start = m_start;
+ if((flags & 4) == 0)
+ {
+ if(flags)
+ {
+ line_parameters lp2(x1, y1, x2, y2,
+ uround(calc_distance(x1, y1, x2, y2)));
+ if(flags & 1)
+ {
+ m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x);
+ sx = x1 + (y2 - y1);
+ sy = y1 - (x2 - x1);
+ }
+ else
+ {
+ while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
+ {
+ sx = (lp.x1 + sx) >> 1;
+ sy = (lp.y1 + sy) >> 1;
+ }
+ }
+ if(flags & 2)
+ {
+ ex = x2 + (y2 - y1);
+ ey = y2 - (x2 - x1);
+ }
+ else
+ {
+ while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
+ {
+ ex = (lp.x2 + ex) >> 1;
+ ey = (lp.y2 + ey) >> 1;
+ }
+ }
+ line3_no_clip(lp2, sx, sy, ex, ey);
+ }
+ else
+ {
+ line3_no_clip(lp, sx, sy, ex, ey);
+ }
+ }
+ m_start = start + uround(lp.len / m_scale_x);
+ }
+ else
+ {
+ line3_no_clip(lp, sx, sy, ex, ey);
+ }
+ }
+
+ private:
+ base_ren_type* m_ren;
+ const pattern_type* m_pattern;
+ int m_start;
+ double m_scale_x;
+ rect_i m_clip_box;
+ bool m_clipping;
+ };
+
+
+
+
+
+}
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_primitives.h b/plugins/Clist_ng/AGG/include/agg_renderer_primitives.h new file mode 100644 index 0000000000..d999f8b56b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_primitives.h @@ -0,0 +1,229 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED
+#define AGG_RENDERER_PRIMITIVES_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_renderer_base.h"
+#include "agg_dda_line.h"
+#include "agg_ellipse_bresenham.h"
+
+namespace agg
+{
+ //-----------------------------------------------------renderer_primitives
+ template<class BaseRenderer> class renderer_primitives
+ {
+ public:
+ typedef BaseRenderer base_ren_type;
+ typedef typename base_ren_type::color_type color_type;
+
+ //--------------------------------------------------------------------
+ explicit renderer_primitives(base_ren_type& ren) :
+ m_ren(&ren),
+ m_fill_color(),
+ m_line_color(),
+ m_curr_x(0),
+ m_curr_y(0)
+ {}
+ void attach(base_ren_type& ren) { m_ren = &ren; }
+
+ //--------------------------------------------------------------------
+ static int coord(double c)
+ {
+ return iround(c * line_bresenham_interpolator::subpixel_scale);
+ }
+
+ //--------------------------------------------------------------------
+ void fill_color(const color_type& c) { m_fill_color = c; }
+ void line_color(const color_type& c) { m_line_color = c; }
+ const color_type& fill_color() const { return m_fill_color; }
+ const color_type& line_color() const { return m_line_color; }
+
+ //--------------------------------------------------------------------
+ void rectangle(int x1, int y1, int x2, int y2)
+ {
+ m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full);
+ m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full);
+ m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full);
+ m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full);
+ }
+
+ //--------------------------------------------------------------------
+ void solid_rectangle(int x1, int y1, int x2, int y2)
+ {
+ m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full);
+ }
+
+ //--------------------------------------------------------------------
+ void outlined_rectangle(int x1, int y1, int x2, int y2)
+ {
+ rectangle(x1, y1, x2, y2);
+ m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full);
+ }
+
+ //--------------------------------------------------------------------
+ void ellipse(int x, int y, int rx, int ry)
+ {
+ ellipse_bresenham_interpolator ei(rx, ry);
+ int dx = 0;
+ int dy = -ry;
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+ m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
+ m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
+ m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
+ m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
+ ++ei;
+ }
+ while(dy < 0);
+ }
+
+ //--------------------------------------------------------------------
+ void solid_ellipse(int x, int y, int rx, int ry)
+ {
+ ellipse_bresenham_interpolator ei(rx, ry);
+ int dx = 0;
+ int dy = -ry;
+ int dy0 = dy;
+ int dx0 = dx;
+
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ if(dy != dy0)
+ {
+ m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
+ m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full);
+ }
+ dx0 = dx;
+ dy0 = dy;
+ ++ei;
+ }
+ while(dy < 0);
+ m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
+ }
+
+ //--------------------------------------------------------------------
+ void outlined_ellipse(int x, int y, int rx, int ry)
+ {
+ ellipse_bresenham_interpolator ei(rx, ry);
+ int dx = 0;
+ int dy = -ry;
+
+ do
+ {
+ dx += ei.dx();
+ dy += ei.dy();
+
+ m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
+ m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
+ m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
+ m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
+
+ if(ei.dy() && dx)
+ {
+ m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full);
+ m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full);
+ }
+ ++ei;
+ }
+ while(dy < 0);
+ }
+
+ //--------------------------------------------------------------------
+ void line(int x1, int y1, int x2, int y2, bool last=false)
+ {
+ line_bresenham_interpolator li(x1, y1, x2, y2);
+
+ unsigned len = li.len();
+ if(len == 0)
+ {
+ if(last)
+ {
+ m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
+ }
+ return;
+ }
+
+ if(last) ++len;
+
+ if(li.is_ver())
+ {
+ do
+ {
+ m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
+ li.vstep();
+ }
+ while(--len);
+ }
+ else
+ {
+ do
+ {
+ m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
+ li.hstep();
+ }
+ while(--len);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void move_to(int x, int y)
+ {
+ m_curr_x = x;
+ m_curr_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ void line_to(int x, int y, bool last=false)
+ {
+ line(m_curr_x, m_curr_y, x, y, last);
+ m_curr_x = x;
+ m_curr_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ const base_ren_type& ren() const { return *m_ren; }
+ base_ren_type& ren() { return *m_ren; }
+
+ //--------------------------------------------------------------------
+ const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
+ rendering_buffer& rbuf() { return m_ren->rbuf(); }
+
+ private:
+ base_ren_type* m_ren;
+ color_type m_fill_color;
+ color_type m_line_color;
+ int m_curr_x;
+ int m_curr_y;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_raster_text.h b/plugins/Clist_ng/AGG/include/agg_renderer_raster_text.h new file mode 100644 index 0000000000..304554250b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_raster_text.h @@ -0,0 +1,273 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_RASTER_TEXT_INCLUDED
+#define AGG_RENDERER_RASTER_TEXT_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //==============================================renderer_raster_htext_solid
+ template<class BaseRenderer, class GlyphGenerator>
+ class renderer_raster_htext_solid
+ {
+ public:
+ typedef BaseRenderer ren_type;
+ typedef GlyphGenerator glyph_gen_type;
+ typedef typename glyph_gen_type::glyph_rect glyph_rect;
+ typedef typename ren_type::color_type color_type;
+
+ renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
+ m_ren(&ren),
+ m_glyph(&glyph)
+ {}
+ void attach(ren_type& ren) { m_ren = &ren; }
+
+ //--------------------------------------------------------------------
+ void color(const color_type& c) { m_color = c; }
+ const color_type& color() const { return m_color; }
+
+ //--------------------------------------------------------------------
+ template<class CharT>
+ void render_text(double x, double y, const CharT* str, bool flip=false)
+ {
+ glyph_rect r;
+ while(*str)
+ {
+ m_glyph->prepare(&r, x, y, *str, flip);
+ if(r.x2 >= r.x1)
+ {
+ int i;
+ if(flip)
+ {
+ for(i = r.y1; i <= r.y2; i++)
+ {
+ m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
+ m_color,
+ m_glyph->span(r.y2 - i));
+ }
+ }
+ else
+ {
+ for(i = r.y1; i <= r.y2; i++)
+ {
+ m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
+ m_color,
+ m_glyph->span(i - r.y1));
+ }
+ }
+ }
+ x += r.dx;
+ y += r.dy;
+ ++str;
+ }
+ }
+
+ private:
+ ren_type* m_ren;
+ glyph_gen_type* m_glyph;
+ color_type m_color;
+ };
+
+
+
+ //=============================================renderer_raster_vtext_solid
+ template<class BaseRenderer, class GlyphGenerator>
+ class renderer_raster_vtext_solid
+ {
+ public:
+ typedef BaseRenderer ren_type;
+ typedef GlyphGenerator glyph_gen_type;
+ typedef typename glyph_gen_type::glyph_rect glyph_rect;
+ typedef typename ren_type::color_type color_type;
+
+ renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) :
+ m_ren(&ren),
+ m_glyph(&glyph)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void color(const color_type& c) { m_color = c; }
+ const color_type& color() const { return m_color; }
+
+ //--------------------------------------------------------------------
+ template<class CharT>
+ void render_text(double x, double y, const CharT* str, bool flip=false)
+ {
+ glyph_rect r;
+ while(*str)
+ {
+ m_glyph->prepare(&r, x, y, *str, !flip);
+ if(r.x2 >= r.x1)
+ {
+ int i;
+ if(flip)
+ {
+ for(i = r.y1; i <= r.y2; i++)
+ {
+ m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
+ m_color,
+ m_glyph->span(i - r.y1));
+ }
+ }
+ else
+ {
+ for(i = r.y1; i <= r.y2; i++)
+ {
+ m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
+ m_color,
+ m_glyph->span(r.y2 - i));
+ }
+ }
+ }
+ x += r.dx;
+ y += r.dy;
+ ++str;
+ }
+ }
+
+ private:
+ ren_type* m_ren;
+ glyph_gen_type* m_glyph;
+ color_type m_color;
+ };
+
+
+
+
+
+
+ //===================================================renderer_raster_htext
+ template<class ScanlineRenderer, class GlyphGenerator>
+ class renderer_raster_htext
+ {
+ public:
+ typedef ScanlineRenderer ren_type;
+ typedef GlyphGenerator glyph_gen_type;
+ typedef typename glyph_gen_type::glyph_rect glyph_rect;
+
+ class scanline_single_span
+ {
+ public:
+ typedef agg::cover_type cover_type;
+
+ //----------------------------------------------------------------
+ struct const_span
+ {
+ int x;
+ unsigned len;
+ const cover_type* covers;
+
+ const_span() {}
+ const_span(int x_, unsigned len_, const cover_type* covers_) :
+ x(x_), len(len_), covers(covers_)
+ {}
+ };
+
+ typedef const const_span* const_iterator;
+
+ //----------------------------------------------------------------
+ scanline_single_span(int x, int y, unsigned len,
+ const cover_type* covers) :
+ m_y(y),
+ m_span(x, len, covers)
+ {}
+
+ //----------------------------------------------------------------
+ int y() const { return m_y; }
+ unsigned num_spans() const { return 1; }
+ const_iterator begin() const { return &m_span; }
+
+ private:
+ //----------------------------------------------------------------
+ int m_y;
+ const_span m_span;
+ };
+
+
+
+ //--------------------------------------------------------------------
+ renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) :
+ m_ren(&ren),
+ m_glyph(&glyph)
+ {
+ }
+
+
+ //--------------------------------------------------------------------
+ template<class CharT>
+ void render_text(double x, double y, const CharT* str, bool flip=false)
+ {
+ glyph_rect r;
+ while(*str)
+ {
+ m_glyph->prepare(&r, x, y, *str, flip);
+ if(r.x2 >= r.x1)
+ {
+ m_ren->prepare();
+ int i;
+ if(flip)
+ {
+ for(i = r.y1; i <= r.y2; i++)
+ {
+ m_ren->render(
+ scanline_single_span(r.x1,
+ i,
+ (r.x2 - r.x1 + 1),
+ m_glyph->span(r.y2 - i)));
+ }
+ }
+ else
+ {
+ for(i = r.y1; i <= r.y2; i++)
+ {
+ m_ren->render(
+ scanline_single_span(r.x1,
+ i,
+ (r.x2 - r.x1 + 1),
+ m_glyph->span(i - r.y1)));
+ }
+ }
+ }
+ x += r.dx;
+ y += r.dy;
+ ++str;
+ }
+ }
+
+ private:
+ ren_type* m_ren;
+ glyph_gen_type* m_glyph;
+ };
+
+
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_renderer_scanline.h b/plugins/Clist_ng/AGG/include/agg_renderer_scanline.h new file mode 100644 index 0000000000..c0b6df6f8c --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_renderer_scanline.h @@ -0,0 +1,861 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERER_SCANLINE_INCLUDED
+#define AGG_RENDERER_SCANLINE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_renderer_base.h"
+
+namespace agg
+{
+
+ //================================================render_scanline_aa_solid
+ template<class Scanline, class BaseRenderer, class ColorT>
+ void render_scanline_aa_solid(const Scanline& sl,
+ BaseRenderer& ren,
+ const ColorT& color)
+ {
+ int y = sl.y();
+ unsigned num_spans = sl.num_spans();
+ typename Scanline::const_iterator span = sl.begin();
+
+ for(;;)
+ {
+ int x = span->x;
+ if(span->len > 0)
+ {
+ ren.blend_solid_hspan(x, y, (unsigned)span->len,
+ color,
+ span->covers);
+ }
+ else
+ {
+ ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
+ color,
+ *(span->covers));
+ }
+ if(--num_spans == 0) break;
+ ++span;
+ }
+ }
+
+ //===============================================render_scanlines_aa_solid
+ template<class Rasterizer, class Scanline,
+ class BaseRenderer, class ColorT>
+ void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl,
+ BaseRenderer& ren, const ColorT& color)
+ {
+ if(ras.rewind_scanlines())
+ {
+ // Explicitly convert "color" to the BaseRenderer color type.
+ // For example, it can be called with color type "rgba", while
+ // "rgba8" is needed. Otherwise it will be implicitly
+ // converted in the loop many times.
+ //----------------------
+ typename BaseRenderer::color_type ren_color(color);
+
+ sl.reset(ras.min_x(), ras.max_x());
+ while(ras.sweep_scanline(sl))
+ {
+ //render_scanline_aa_solid(sl, ren, ren_color);
+
+ // This code is equivalent to the above call (copy/paste).
+ // It's just a "manual" optimization for old compilers,
+ // like Microsoft Visual C++ v6.0
+ //-------------------------------
+ int y = sl.y();
+ unsigned num_spans = sl.num_spans();
+ typename Scanline::const_iterator span = sl.begin();
+
+ for(;;)
+ {
+ int x = span->x;
+ if(span->len > 0)
+ {
+ ren.blend_solid_hspan(x, y, (unsigned)span->len,
+ ren_color,
+ span->covers);
+ }
+ else
+ {
+ ren.blend_hline(x, y, (unsigned)(x - span->len - 1),
+ ren_color,
+ *(span->covers));
+ }
+ if(--num_spans == 0) break;
+ ++span;
+ }
+ }
+ }
+ }
+
+ //==============================================renderer_scanline_aa_solid
+ template<class BaseRenderer> class renderer_scanline_aa_solid
+ {
+ public:
+ typedef BaseRenderer base_ren_type;
+ typedef typename base_ren_type::color_type color_type;
+
+ //--------------------------------------------------------------------
+ renderer_scanline_aa_solid() : m_ren(0) {}
+ explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {}
+ void attach(base_ren_type& ren)
+ {
+ m_ren = &ren;
+ }
+
+ //--------------------------------------------------------------------
+ void color(const color_type& c) { m_color = c; }
+ const color_type& color() const { return m_color; }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+
+ //--------------------------------------------------------------------
+ template<class Scanline> void render(const Scanline& sl)
+ {
+ render_scanline_aa_solid(sl, *m_ren, m_color);
+ }
+
+ private:
+ base_ren_type* m_ren;
+ color_type m_color;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //======================================================render_scanline_aa
+ template<class Scanline, class BaseRenderer,
+ class SpanAllocator, class SpanGenerator>
+ void render_scanline_aa(const Scanline& sl, BaseRenderer& ren,
+ SpanAllocator& alloc, SpanGenerator& span_gen)
+ {
+ int y = sl.y();
+
+ unsigned num_spans = sl.num_spans();
+ typename Scanline::const_iterator span = sl.begin();
+ for(;;)
+ {
+ int x = span->x;
+ int len = span->len;
+ const typename Scanline::cover_type* covers = span->covers;
+
+ if(len < 0) len = -len;
+ typename BaseRenderer::color_type* colors = alloc.allocate(len);
+ span_gen.generate(colors, x, y, len);
+ ren.blend_color_hspan(x, y, len, colors,
+ (span->len < 0) ? 0 : covers, *covers);
+
+ if(--num_spans == 0) break;
+ ++span;
+ }
+ }
+
+ //=====================================================render_scanlines_aa
+ template<class Rasterizer, class Scanline, class BaseRenderer,
+ class SpanAllocator, class SpanGenerator>
+ void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
+ SpanAllocator& alloc, SpanGenerator& span_gen)
+ {
+ if(ras.rewind_scanlines())
+ {
+ sl.reset(ras.min_x(), ras.max_x());
+ span_gen.prepare();
+ while(ras.sweep_scanline(sl))
+ {
+ render_scanline_aa(sl, ren, alloc, span_gen);
+ }
+ }
+ }
+
+ //====================================================renderer_scanline_aa
+ template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
+ class renderer_scanline_aa
+ {
+ public:
+ typedef BaseRenderer base_ren_type;
+ typedef SpanAllocator alloc_type;
+ typedef SpanGenerator span_gen_type;
+
+ //--------------------------------------------------------------------
+ renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {}
+ renderer_scanline_aa(base_ren_type& ren,
+ alloc_type& alloc,
+ span_gen_type& span_gen) :
+ m_ren(&ren),
+ m_alloc(&alloc),
+ m_span_gen(&span_gen)
+ {}
+ void attach(base_ren_type& ren,
+ alloc_type& alloc,
+ span_gen_type& span_gen)
+ {
+ m_ren = &ren;
+ m_alloc = &alloc;
+ m_span_gen = &span_gen;
+ }
+
+ //--------------------------------------------------------------------
+ void prepare() { m_span_gen->prepare(); }
+
+ //--------------------------------------------------------------------
+ template<class Scanline> void render(const Scanline& sl)
+ {
+ render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen);
+ }
+
+ private:
+ base_ren_type* m_ren;
+ alloc_type* m_alloc;
+ span_gen_type* m_span_gen;
+ };
+
+
+
+
+
+
+ //===============================================render_scanline_bin_solid
+ template<class Scanline, class BaseRenderer, class ColorT>
+ void render_scanline_bin_solid(const Scanline& sl,
+ BaseRenderer& ren,
+ const ColorT& color)
+ {
+ unsigned num_spans = sl.num_spans();
+ typename Scanline::const_iterator span = sl.begin();
+ for(;;)
+ {
+ ren.blend_hline(span->x,
+ sl.y(),
+ span->x - 1 + ((span->len < 0) ?
+ -span->len :
+ span->len),
+ color,
+ cover_full);
+ if(--num_spans == 0) break;
+ ++span;
+ }
+ }
+
+ //==============================================render_scanlines_bin_solid
+ template<class Rasterizer, class Scanline,
+ class BaseRenderer, class ColorT>
+ void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl,
+ BaseRenderer& ren, const ColorT& color)
+ {
+ if(ras.rewind_scanlines())
+ {
+ // Explicitly convert "color" to the BaseRenderer color type.
+ // For example, it can be called with color type "rgba", while
+ // "rgba8" is needed. Otherwise it will be implicitly
+ // converted in the loop many times.
+ //----------------------
+ typename BaseRenderer::color_type ren_color(color);
+
+ sl.reset(ras.min_x(), ras.max_x());
+ while(ras.sweep_scanline(sl))
+ {
+ //render_scanline_bin_solid(sl, ren, ren_color);
+
+ // This code is equivalent to the above call (copy/paste).
+ // It's just a "manual" optimization for old compilers,
+ // like Microsoft Visual C++ v6.0
+ //-------------------------------
+ unsigned num_spans = sl.num_spans();
+ typename Scanline::const_iterator span = sl.begin();
+ for(;;)
+ {
+ ren.blend_hline(span->x,
+ sl.y(),
+ span->x - 1 + ((span->len < 0) ?
+ -span->len :
+ span->len),
+ ren_color,
+ cover_full);
+ if(--num_spans == 0) break;
+ ++span;
+ }
+ }
+ }
+ }
+
+ //=============================================renderer_scanline_bin_solid
+ template<class BaseRenderer> class renderer_scanline_bin_solid
+ {
+ public:
+ typedef BaseRenderer base_ren_type;
+ typedef typename base_ren_type::color_type color_type;
+
+ //--------------------------------------------------------------------
+ renderer_scanline_bin_solid() : m_ren(0) {}
+ explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {}
+ void attach(base_ren_type& ren)
+ {
+ m_ren = &ren;
+ }
+
+ //--------------------------------------------------------------------
+ void color(const color_type& c) { m_color = c; }
+ const color_type& color() const { return m_color; }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+
+ //--------------------------------------------------------------------
+ template<class Scanline> void render(const Scanline& sl)
+ {
+ render_scanline_bin_solid(sl, *m_ren, m_color);
+ }
+
+ private:
+ base_ren_type* m_ren;
+ color_type m_color;
+ };
+
+
+
+
+
+
+
+
+ //======================================================render_scanline_bin
+ template<class Scanline, class BaseRenderer,
+ class SpanAllocator, class SpanGenerator>
+ void render_scanline_bin(const Scanline& sl, BaseRenderer& ren,
+ SpanAllocator& alloc, SpanGenerator& span_gen)
+ {
+ int y = sl.y();
+
+ unsigned num_spans = sl.num_spans();
+ typename Scanline::const_iterator span = sl.begin();
+ for(;;)
+ {
+ int x = span->x;
+ int len = span->len;
+ if(len < 0) len = -len;
+ typename BaseRenderer::color_type* colors = alloc.allocate(len);
+ span_gen.generate(colors, x, y, len);
+ ren.blend_color_hspan(x, y, len, colors, 0, cover_full);
+ if(--num_spans == 0) break;
+ ++span;
+ }
+ }
+
+ //=====================================================render_scanlines_bin
+ template<class Rasterizer, class Scanline, class BaseRenderer,
+ class SpanAllocator, class SpanGenerator>
+ void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren,
+ SpanAllocator& alloc, SpanGenerator& span_gen)
+ {
+ if(ras.rewind_scanlines())
+ {
+ sl.reset(ras.min_x(), ras.max_x());
+ span_gen.prepare();
+ while(ras.sweep_scanline(sl))
+ {
+ render_scanline_bin(sl, ren, alloc, span_gen);
+ }
+ }
+ }
+
+ //====================================================renderer_scanline_bin
+ template<class BaseRenderer, class SpanAllocator, class SpanGenerator>
+ class renderer_scanline_bin
+ {
+ public:
+ typedef BaseRenderer base_ren_type;
+ typedef SpanAllocator alloc_type;
+ typedef SpanGenerator span_gen_type;
+
+ //--------------------------------------------------------------------
+ renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {}
+ renderer_scanline_bin(base_ren_type& ren,
+ alloc_type& alloc,
+ span_gen_type& span_gen) :
+ m_ren(&ren),
+ m_alloc(&alloc),
+ m_span_gen(&span_gen)
+ {}
+ void attach(base_ren_type& ren,
+ alloc_type& alloc,
+ span_gen_type& span_gen)
+ {
+ m_ren = &ren;
+ m_alloc = &alloc;
+ m_span_gen = &span_gen;
+ }
+
+ //--------------------------------------------------------------------
+ void prepare() { m_span_gen->prepare(); }
+
+ //--------------------------------------------------------------------
+ template<class Scanline> void render(const Scanline& sl)
+ {
+ render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen);
+ }
+
+ private:
+ base_ren_type* m_ren;
+ alloc_type* m_alloc;
+ span_gen_type* m_span_gen;
+ };
+
+
+
+
+
+
+
+
+
+
+ //========================================================render_scanlines
+ template<class Rasterizer, class Scanline, class Renderer>
+ void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren)
+ {
+ if(ras.rewind_scanlines())
+ {
+ sl.reset(ras.min_x(), ras.max_x());
+ ren.prepare();
+ while(ras.sweep_scanline(sl))
+ {
+ ren.render(sl);
+ }
+ }
+ }
+
+ //========================================================render_all_paths
+ template<class Rasterizer, class Scanline, class Renderer,
+ class VertexSource, class ColorStorage, class PathId>
+ void render_all_paths(Rasterizer& ras,
+ Scanline& sl,
+ Renderer& r,
+ VertexSource& vs,
+ const ColorStorage& as,
+ const PathId& path_id,
+ unsigned num_paths)
+ {
+ for(unsigned i = 0; i < num_paths; i++)
+ {
+ ras.reset();
+ ras.add_path(vs, path_id[i]);
+ r.color(as[i]);
+ render_scanlines(ras, sl, r);
+ }
+ }
+
+
+
+
+
+
+ //=============================================render_scanlines_compound
+ template<class Rasterizer,
+ class ScanlineAA,
+ class ScanlineBin,
+ class BaseRenderer,
+ class SpanAllocator,
+ class StyleHandler>
+ void render_scanlines_compound(Rasterizer& ras,
+ ScanlineAA& sl_aa,
+ ScanlineBin& sl_bin,
+ BaseRenderer& ren,
+ SpanAllocator& alloc,
+ StyleHandler& sh)
+ {
+ if(ras.rewind_scanlines())
+ {
+ int min_x = ras.min_x();
+ int len = ras.max_x() - min_x + 2;
+ sl_aa.reset(min_x, ras.max_x());
+ sl_bin.reset(min_x, ras.max_x());
+
+ typedef typename BaseRenderer::color_type color_type;
+ color_type* color_span = alloc.allocate(len * 2);
+ color_type* mix_buffer = color_span + len;
+ unsigned num_spans;
+
+ unsigned num_styles;
+ unsigned style;
+ bool solid;
+ while((num_styles = ras.sweep_styles()) > 0)
+ {
+ typename ScanlineAA::const_iterator span_aa;
+ if(num_styles == 1)
+ {
+ // Optimization for a single style. Happens often
+ //-------------------------
+ if(ras.sweep_scanline(sl_aa, 0))
+ {
+ style = ras.style(0);
+ if(sh.is_solid(style))
+ {
+ // Just solid fill
+ //-----------------------
+ render_scanline_aa_solid(sl_aa, ren, sh.color(style));
+ }
+ else
+ {
+ // Arbitrary span generator
+ //-----------------------
+ span_aa = sl_aa.begin();
+ num_spans = sl_aa.num_spans();
+ for(;;)
+ {
+ len = span_aa->len;
+ sh.generate_span(color_span,
+ span_aa->x,
+ sl_aa.y(),
+ len,
+ style);
+
+ ren.blend_color_hspan(span_aa->x,
+ sl_aa.y(),
+ span_aa->len,
+ color_span,
+ span_aa->covers);
+ if(--num_spans == 0) break;
+ ++span_aa;
+ }
+ }
+ }
+ }
+ else
+ {
+ if(ras.sweep_scanline(sl_bin, -1))
+ {
+ // Clear the spans of the mix_buffer
+ //--------------------
+ typename ScanlineBin::const_iterator span_bin = sl_bin.begin();
+ num_spans = sl_bin.num_spans();
+ for(;;)
+ {
+ memset(mix_buffer + span_bin->x - min_x,
+ 0,
+ span_bin->len * sizeof(color_type));
+
+ if(--num_spans == 0) break;
+ ++span_bin;
+ }
+
+ unsigned i;
+ for(i = 0; i < num_styles; i++)
+ {
+ style = ras.style(i);
+ solid = sh.is_solid(style);
+
+ if(ras.sweep_scanline(sl_aa, i))
+ {
+ color_type* colors;
+ color_type* cspan;
+ typename ScanlineAA::cover_type* covers;
+ span_aa = sl_aa.begin();
+ num_spans = sl_aa.num_spans();
+ if(solid)
+ {
+ // Just solid fill
+ //-----------------------
+ for(;;)
+ {
+ color_type c = sh.color(style);
+ len = span_aa->len;
+ colors = mix_buffer + span_aa->x - min_x;
+ covers = span_aa->covers;
+ do
+ {
+ if(*covers == cover_full)
+ {
+ *colors = c;
+ }
+ else
+ {
+ colors->add(c, *covers);
+ }
+ ++colors;
+ ++covers;
+ }
+ while(--len);
+ if(--num_spans == 0) break;
+ ++span_aa;
+ }
+ }
+ else
+ {
+ // Arbitrary span generator
+ //-----------------------
+ for(;;)
+ {
+ len = span_aa->len;
+ colors = mix_buffer + span_aa->x - min_x;
+ cspan = color_span;
+ sh.generate_span(cspan,
+ span_aa->x,
+ sl_aa.y(),
+ len,
+ style);
+ covers = span_aa->covers;
+ do
+ {
+ if(*covers == cover_full)
+ {
+ *colors = *cspan;
+ }
+ else
+ {
+ colors->add(*cspan, *covers);
+ }
+ ++cspan;
+ ++colors;
+ ++covers;
+ }
+ while(--len);
+ if(--num_spans == 0) break;
+ ++span_aa;
+ }
+ }
+ }
+ }
+
+ // Emit the blended result as a color hspan
+ //-------------------------
+ span_bin = sl_bin.begin();
+ num_spans = sl_bin.num_spans();
+ for(;;)
+ {
+ ren.blend_color_hspan(span_bin->x,
+ sl_bin.y(),
+ span_bin->len,
+ mix_buffer + span_bin->x - min_x,
+ 0,
+ cover_full);
+ if(--num_spans == 0) break;
+ ++span_bin;
+ }
+ } // if(ras.sweep_scanline(sl_bin, -1))
+ } // if(num_styles == 1) ... else
+ } // while((num_styles = ras.sweep_styles()) > 0)
+ } // if(ras.rewind_scanlines())
+ }
+
+ //=======================================render_scanlines_compound_layered
+ template<class Rasterizer,
+ class ScanlineAA,
+ class BaseRenderer,
+ class SpanAllocator,
+ class StyleHandler>
+ void render_scanlines_compound_layered(Rasterizer& ras,
+ ScanlineAA& sl_aa,
+ BaseRenderer& ren,
+ SpanAllocator& alloc,
+ StyleHandler& sh)
+ {
+ if(ras.rewind_scanlines())
+ {
+ int min_x = ras.min_x();
+ int len = ras.max_x() - min_x + 2;
+ sl_aa.reset(min_x, ras.max_x());
+
+ typedef typename BaseRenderer::color_type color_type;
+ color_type* color_span = alloc.allocate(len * 2);
+ color_type* mix_buffer = color_span + len;
+ cover_type* cover_buffer = ras.allocate_cover_buffer(len);
+ unsigned num_spans;
+
+ unsigned num_styles;
+ unsigned style;
+ bool solid;
+ while((num_styles = ras.sweep_styles()) > 0)
+ {
+ typename ScanlineAA::const_iterator span_aa;
+ if(num_styles == 1)
+ {
+ // Optimization for a single style. Happens often
+ //-------------------------
+ if(ras.sweep_scanline(sl_aa, 0))
+ {
+ style = ras.style(0);
+ if(sh.is_solid(style))
+ {
+ // Just solid fill
+ //-----------------------
+ render_scanline_aa_solid(sl_aa, ren, sh.color(style));
+ }
+ else
+ {
+ // Arbitrary span generator
+ //-----------------------
+ span_aa = sl_aa.begin();
+ num_spans = sl_aa.num_spans();
+ for(;;)
+ {
+ len = span_aa->len;
+ sh.generate_span(color_span,
+ span_aa->x,
+ sl_aa.y(),
+ len,
+ style);
+
+ ren.blend_color_hspan(span_aa->x,
+ sl_aa.y(),
+ span_aa->len,
+ color_span,
+ span_aa->covers);
+ if(--num_spans == 0) break;
+ ++span_aa;
+ }
+ }
+ }
+ }
+ else
+ {
+ int sl_start = ras.scanline_start();
+ unsigned sl_len = ras.scanline_length();
+
+ if(sl_len)
+ {
+ memset(mix_buffer + sl_start - min_x,
+ 0,
+ sl_len * sizeof(color_type));
+
+ memset(cover_buffer + sl_start - min_x,
+ 0,
+ sl_len * sizeof(cover_type));
+
+ int sl_y = 0x7FFFFFFF;
+ unsigned i;
+ for(i = 0; i < num_styles; i++)
+ {
+ style = ras.style(i);
+ solid = sh.is_solid(style);
+
+ if(ras.sweep_scanline(sl_aa, i))
+ {
+ unsigned cover;
+ color_type* colors;
+ color_type* cspan;
+ cover_type* src_covers;
+ cover_type* dst_covers;
+ span_aa = sl_aa.begin();
+ num_spans = sl_aa.num_spans();
+ sl_y = sl_aa.y();
+ if(solid)
+ {
+ // Just solid fill
+ //-----------------------
+ for(;;)
+ {
+ color_type c = sh.color(style);
+ len = span_aa->len;
+ colors = mix_buffer + span_aa->x - min_x;
+ src_covers = span_aa->covers;
+ dst_covers = cover_buffer + span_aa->x - min_x;
+ do
+ {
+ cover = *src_covers;
+ if(*dst_covers + cover > cover_full)
+ {
+ cover = cover_full - *dst_covers;
+ }
+ if(cover)
+ {
+ colors->add(c, cover);
+ *dst_covers += cover;
+ }
+ ++colors;
+ ++src_covers;
+ ++dst_covers;
+ }
+ while(--len);
+ if(--num_spans == 0) break;
+ ++span_aa;
+ }
+ }
+ else
+ {
+ // Arbitrary span generator
+ //-----------------------
+ for(;;)
+ {
+ len = span_aa->len;
+ colors = mix_buffer + span_aa->x - min_x;
+ cspan = color_span;
+ sh.generate_span(cspan,
+ span_aa->x,
+ sl_aa.y(),
+ len,
+ style);
+ src_covers = span_aa->covers;
+ dst_covers = cover_buffer + span_aa->x - min_x;
+ do
+ {
+ cover = *src_covers;
+ if(*dst_covers + cover > cover_full)
+ {
+ cover = cover_full - *dst_covers;
+ }
+ if(cover)
+ {
+ colors->add(*cspan, cover);
+ *dst_covers += cover;
+ }
+ ++cspan;
+ ++colors;
+ ++src_covers;
+ ++dst_covers;
+ }
+ while(--len);
+ if(--num_spans == 0) break;
+ ++span_aa;
+ }
+ }
+ }
+ }
+ ren.blend_color_hspan(sl_start,
+ sl_y,
+ sl_len,
+ mix_buffer + sl_start - min_x,
+ 0,
+ cover_full);
+ } //if(sl_len)
+ } //if(num_styles == 1) ... else
+ } //while((num_styles = ras.sweep_styles()) > 0)
+ } //if(ras.rewind_scanlines())
+ }
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_rendering_buffer.h b/plugins/Clist_ng/AGG/include/agg_rendering_buffer.h new file mode 100644 index 0000000000..5a06c8a00f --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rendering_buffer.h @@ -0,0 +1,305 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERING_BUFFER_INCLUDED
+#define AGG_RENDERING_BUFFER_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+
+ //===========================================================row_accessor
+ template<class T> class row_accessor
+ {
+ public:
+ typedef const_row_info<T> row_data;
+
+ //-------------------------------------------------------------------
+ row_accessor() :
+ m_buf(0),
+ m_start(0),
+ m_width(0),
+ m_height(0),
+ m_stride(0)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ row_accessor(T* buf, unsigned width, unsigned height, int stride) :
+ m_buf(0),
+ m_start(0),
+ m_width(0),
+ m_height(0),
+ m_stride(0)
+ {
+ attach(buf, width, height, stride);
+ }
+
+
+ //--------------------------------------------------------------------
+ void attach(T* buf, unsigned width, unsigned height, int stride)
+ {
+ m_buf = m_start = buf;
+ m_width = width;
+ m_height = height;
+ m_stride = stride;
+ if(stride < 0)
+ {
+ m_start = m_buf - int(height - 1) * stride;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE T* buf() { return m_buf; }
+ AGG_INLINE const T* buf() const { return m_buf; }
+ AGG_INLINE unsigned width() const { return m_width; }
+ AGG_INLINE unsigned height() const { return m_height; }
+ AGG_INLINE int stride() const { return m_stride; }
+ AGG_INLINE unsigned stride_abs() const
+ {
+ return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE T* row_ptr(int, int y, unsigned)
+ {
+ return m_start + y * m_stride;
+ }
+ AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
+ AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
+ AGG_INLINE row_data row (int y) const
+ {
+ return row_data(0, m_width-1, row_ptr(y));
+ }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf>
+ void copy_from(const RenBuf& src)
+ {
+ unsigned h = height();
+ if(src.height() < h) h = src.height();
+
+ unsigned l = stride_abs();
+ if(src.stride_abs() < l) l = src.stride_abs();
+
+ l *= sizeof(T);
+
+ unsigned y;
+ unsigned w = width();
+ for (y = 0; y < h; y++)
+ {
+ memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void clear(T value)
+ {
+ unsigned y;
+ unsigned w = width();
+ unsigned stride = stride_abs();
+ for(y = 0; y < height(); y++)
+ {
+ T* p = row_ptr(0, y, w);
+ unsigned x;
+ for(x = 0; x < stride; x++)
+ {
+ *p++ = value;
+ }
+ }
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ T* m_buf; // Pointer to renrdering buffer
+ T* m_start; // Pointer to first pixel depending on stride
+ unsigned m_width; // Width in pixels
+ unsigned m_height; // Height in pixels
+ int m_stride; // Number of bytes per row. Can be < 0
+ };
+
+
+
+
+ //==========================================================row_ptr_cache
+ template<class T> class row_ptr_cache
+ {
+ public:
+ typedef const_row_info<T> row_data;
+
+ //-------------------------------------------------------------------
+ row_ptr_cache() :
+ m_buf(0),
+ m_rows(),
+ m_width(0),
+ m_height(0),
+ m_stride(0)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
+ m_buf(0),
+ m_rows(),
+ m_width(0),
+ m_height(0),
+ m_stride(0)
+ {
+ attach(buf, width, height, stride);
+ }
+
+ //--------------------------------------------------------------------
+ void attach(T* buf, unsigned width, unsigned height, int stride)
+ {
+ m_buf = buf;
+ m_width = width;
+ m_height = height;
+ m_stride = stride;
+ if(height > m_rows.size())
+ {
+ m_rows.resize(height);
+ }
+
+ T* row_ptr = m_buf;
+
+ if(stride < 0)
+ {
+ row_ptr = m_buf - int(height - 1) * stride;
+ }
+
+ T** rows = &m_rows[0];
+
+ while(height--)
+ {
+ *rows++ = row_ptr;
+ row_ptr += stride;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE T* buf() { return m_buf; }
+ AGG_INLINE const T* buf() const { return m_buf; }
+ AGG_INLINE unsigned width() const { return m_width; }
+ AGG_INLINE unsigned height() const { return m_height; }
+ AGG_INLINE int stride() const { return m_stride; }
+ AGG_INLINE unsigned stride_abs() const
+ {
+ return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE T* row_ptr(int, int y, unsigned)
+ {
+ return m_rows[y];
+ }
+ AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
+ AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
+ AGG_INLINE row_data row (int y) const
+ {
+ return row_data(0, m_width-1, m_rows[y]);
+ }
+
+ //--------------------------------------------------------------------
+ T const* const* rows() const { return &m_rows[0]; }
+
+ //--------------------------------------------------------------------
+ template<class RenBuf>
+ void copy_from(const RenBuf& src)
+ {
+ unsigned h = height();
+ if(src.height() < h) h = src.height();
+
+ unsigned l = stride_abs();
+ if(src.stride_abs() < l) l = src.stride_abs();
+
+ l *= sizeof(T);
+
+ unsigned y;
+ unsigned w = width();
+ for (y = 0; y < h; y++)
+ {
+ memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void clear(T value)
+ {
+ unsigned y;
+ unsigned w = width();
+ unsigned stride = stride_abs();
+ for(y = 0; y < height(); y++)
+ {
+ T* p = row_ptr(0, y, w);
+ unsigned x;
+ for(x = 0; x < stride; x++)
+ {
+ *p++ = value;
+ }
+ }
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ T* m_buf; // Pointer to renrdering buffer
+ pod_array<T*> m_rows; // Pointers to each row of the buffer
+ unsigned m_width; // Width in pixels
+ unsigned m_height; // Height in pixels
+ int m_stride; // Number of bytes per row. Can be < 0
+ };
+
+
+
+
+ //========================================================rendering_buffer
+ //
+ // The definition of the main type for accessing the rows in the frame
+ // buffer. It provides functionality to navigate to the rows in a
+ // rectangular matrix, from top to bottom or from bottom to top depending
+ // on stride.
+ //
+ // row_accessor is cheap to create/destroy, but performs one multiplication
+ // when calling row_ptr().
+ //
+ // row_ptr_cache creates an array of pointers to rows, so, the access
+ // via row_ptr() may be faster. But it requires memory allocation
+ // when creating. For example, on typical Intel Pentium hardware
+ // row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
+ //
+ // It's used only in short hand typedefs like pixfmt_rgba32 and can be
+ // redefined in agg_config.h
+ // In real applications you can use both, depending on your needs
+ //------------------------------------------------------------------------
+#ifdef AGG_RENDERING_BUFFER
+ typedef AGG_RENDERING_BUFFER rendering_buffer;
+#else
+// typedef row_ptr_cache<int8u> rendering_buffer;
+ typedef row_accessor<int8u> rendering_buffer;
+#endif
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_rendering_buffer_dynarow.h b/plugins/Clist_ng/AGG/include/agg_rendering_buffer_dynarow.h new file mode 100644 index 0000000000..bc0ad4d21e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rendering_buffer_dynarow.h @@ -0,0 +1,142 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
+#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+
+ //===============================================rendering_buffer_dynarow
+ // Rendering buffer class with dynamic allocation of the rows.
+ // The rows are allocated as needed when requesting for span_ptr().
+ // The class automatically calculates min_x and max_x for each row.
+ // Generally it's more efficient to use this class as a temporary buffer
+ // for rendering a few lines and then to blend it with another buffer.
+ //
+ class rendering_buffer_dynarow
+ {
+ public:
+ typedef row_info<int8u> row_data;
+
+ //-------------------------------------------------------------------
+ ~rendering_buffer_dynarow()
+ {
+ init(0,0,0);
+ }
+
+ //-------------------------------------------------------------------
+ rendering_buffer_dynarow() :
+ m_rows(),
+ m_width(0),
+ m_height(0),
+ m_byte_width(0)
+ {
+ }
+
+ // Allocate and clear the buffer
+ //--------------------------------------------------------------------
+ rendering_buffer_dynarow(unsigned width, unsigned height,
+ unsigned byte_width) :
+ m_rows(height),
+ m_width(width),
+ m_height(height),
+ m_byte_width(byte_width)
+ {
+ memset(&m_rows[0], 0, sizeof(row_data) * height);
+ }
+
+ // Allocate and clear the buffer
+ //--------------------------------------------------------------------
+ void init(unsigned width, unsigned height, unsigned byte_width)
+ {
+ unsigned i;
+ for(i = 0; i < m_height; ++i)
+ {
+ pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
+ }
+ if(width && height)
+ {
+ m_width = width;
+ m_height = height;
+ m_byte_width = byte_width;
+ m_rows.resize(height);
+ memset(&m_rows[0], 0, sizeof(row_data) * height);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ unsigned width() const { return m_width; }
+ unsigned height() const { return m_height; }
+ unsigned byte_width() const { return m_byte_width; }
+
+ // The main function used for rendering. Returns pointer to the
+ // pre-allocated span. Memory for the row is allocated as needed.
+ //--------------------------------------------------------------------
+ int8u* row_ptr(int x, int y, unsigned len)
+ {
+ row_data* r = &m_rows[y];
+ int x2 = x + len - 1;
+ if(r->ptr)
+ {
+ if(x < r->x1) { r->x1 = x; }
+ if(x2 > r->x2) { r->x2 = x2; }
+ }
+ else
+ {
+ int8u* p = pod_allocator<int8u>::allocate(m_byte_width);
+ r->ptr = p;
+ r->x1 = x;
+ r->x2 = x2;
+ memset(p, 0, m_byte_width);
+ }
+ return (int8u*)r->ptr;
+ }
+
+ //--------------------------------------------------------------------
+ const int8u* row_ptr(int y) const { return m_rows[y].ptr; }
+ int8u* row_ptr(int y) { return row_ptr(0, y, m_width); }
+ row_data row (int y) const { return m_rows[y]; }
+
+ private:
+ //--------------------------------------------------------------------
+ // Prohibit copying
+ rendering_buffer_dynarow(const rendering_buffer_dynarow&);
+ const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&);
+
+ private:
+ //--------------------------------------------------------------------
+ pod_array<row_data> m_rows; // Pointers to each row of the buffer
+ unsigned m_width; // Width in pixels
+ unsigned m_height; // Height in pixels
+ unsigned m_byte_width; // Width in bytes
+ };
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_rounded_rect.h b/plugins/Clist_ng/AGG/include/agg_rounded_rect.h new file mode 100644 index 0000000000..ecaa370eac --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_rounded_rect.h @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_ROUNDED_RECT_INCLUDED
+#define AGG_ROUNDED_RECT_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_arc.h"
+
+namespace agg
+{
+ //------------------------------------------------------------rounded_rect
+ //
+ // See Implemantation agg_rounded_rect.cpp
+ //
+ class rounded_rect
+ {
+ public:
+ rounded_rect() {}
+ rounded_rect(double x1, double y1, double x2, double y2, double r);
+
+ void rect(double x1, double y1, double x2, double y2);
+ void radius(double r);
+ void radius(double rx, double ry);
+ void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top);
+ void radius(double rx1, double ry1, double rx2, double ry2,
+ double rx3, double ry3, double rx4, double ry4);
+ void normalize_radius();
+
+ void approximation_scale(double s) { m_arc.approximation_scale(s); }
+ double approximation_scale() const { return m_arc.approximation_scale(); }
+
+ void rewind(unsigned);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ double m_x1;
+ double m_y1;
+ double m_x2;
+ double m_y2;
+ double m_rx1;
+ double m_ry1;
+ double m_rx2;
+ double m_ry2;
+ double m_rx3;
+ double m_ry3;
+ double m_rx4;
+ double m_ry4;
+ unsigned m_status;
+ arc m_arc;
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_scanline_bin.h b/plugins/Clist_ng/AGG/include/agg_scanline_bin.h new file mode 100644 index 0000000000..dd4cdf694b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_scanline_bin.h @@ -0,0 +1,269 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SCANLINE_BIN_INCLUDED
+#define AGG_SCANLINE_BIN_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+
+ //=============================================================scanline_bin
+ //
+ // This is binary scaline container which supports the interface
+ // used in the rasterizer::render(). See description of agg_scanline_u8
+ // for details.
+ //
+ //------------------------------------------------------------------------
+ class scanline_bin
+ {
+ public:
+ typedef int32 coord_type;
+
+ struct span
+ {
+ int16 x;
+ int16 len;
+ };
+
+ typedef const span* const_iterator;
+
+ //--------------------------------------------------------------------
+ scanline_bin() :
+ m_last_x(0x7FFFFFF0),
+ m_spans(),
+ m_cur_span(0)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void reset(int min_x, int max_x)
+ {
+ unsigned max_len = max_x - min_x + 3;
+ if(max_len > m_spans.size())
+ {
+ m_spans.resize(max_len);
+ }
+ m_last_x = 0x7FFFFFF0;
+ m_cur_span = &m_spans[0];
+ }
+
+ //--------------------------------------------------------------------
+ void add_cell(int x, unsigned)
+ {
+ if(x == m_last_x+1)
+ {
+ m_cur_span->len++;
+ }
+ else
+ {
+ ++m_cur_span;
+ m_cur_span->x = (int16)x;
+ m_cur_span->len = 1;
+ }
+ m_last_x = x;
+ }
+
+ //--------------------------------------------------------------------
+ void add_span(int x, unsigned len, unsigned)
+ {
+ if(x == m_last_x+1)
+ {
+ m_cur_span->len = (int16)(m_cur_span->len + len);
+ }
+ else
+ {
+ ++m_cur_span;
+ m_cur_span->x = (int16)x;
+ m_cur_span->len = (int16)len;
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void add_cells(int x, unsigned len, const void*)
+ {
+ add_span(x, len, 0);
+ }
+
+ //--------------------------------------------------------------------
+ void finalize(int y)
+ {
+ m_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_spans()
+ {
+ m_last_x = 0x7FFFFFF0;
+ m_cur_span = &m_spans[0];
+ }
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y; }
+ unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
+ const_iterator begin() const { return &m_spans[1]; }
+
+ private:
+ scanline_bin(const scanline_bin&);
+ const scanline_bin operator = (const scanline_bin&);
+
+ int m_last_x;
+ int m_y;
+ pod_array<span> m_spans;
+ span* m_cur_span;
+ };
+
+
+
+
+
+
+ //===========================================================scanline32_bin
+ class scanline32_bin
+ {
+ public:
+ typedef int32 coord_type;
+
+ //--------------------------------------------------------------------
+ struct span
+ {
+ span() {}
+ span(coord_type x_, coord_type len_) : x(x_), len(len_) {}
+
+ coord_type x;
+ coord_type len;
+ };
+ typedef pod_bvector<span, 4> span_array_type;
+
+
+ //--------------------------------------------------------------------
+ class const_iterator
+ {
+ public:
+ const_iterator(const span_array_type& spans) :
+ m_spans(spans),
+ m_span_idx(0)
+ {}
+
+ const span& operator*() const { return m_spans[m_span_idx]; }
+ const span* operator->() const { return &m_spans[m_span_idx]; }
+
+ void operator ++ () { ++m_span_idx; }
+
+ private:
+ const span_array_type& m_spans;
+ unsigned m_span_idx;
+ };
+
+
+ //--------------------------------------------------------------------
+ scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {}
+
+ //--------------------------------------------------------------------
+ void reset(int min_x, int max_x)
+ {
+ m_last_x = 0x7FFFFFF0;
+ m_spans.remove_all();
+ }
+
+ //--------------------------------------------------------------------
+ void add_cell(int x, unsigned)
+ {
+ if(x == m_last_x+1)
+ {
+ m_spans.last().len++;
+ }
+ else
+ {
+ m_spans.add(span(coord_type(x), 1));
+ }
+ m_last_x = x;
+ }
+
+ //--------------------------------------------------------------------
+ void add_span(int x, unsigned len, unsigned)
+ {
+ if(x == m_last_x+1)
+ {
+ m_spans.last().len += coord_type(len);
+ }
+ else
+ {
+ m_spans.add(span(coord_type(x), coord_type(len)));
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void add_cells(int x, unsigned len, const void*)
+ {
+ add_span(x, len, 0);
+ }
+
+ //--------------------------------------------------------------------
+ void finalize(int y)
+ {
+ m_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_spans()
+ {
+ m_last_x = 0x7FFFFFF0;
+ m_spans.remove_all();
+ }
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y; }
+ unsigned num_spans() const { return m_spans.size(); }
+ const_iterator begin() const { return const_iterator(m_spans); }
+
+ private:
+ scanline32_bin(const scanline32_bin&);
+ const scanline32_bin operator = (const scanline32_bin&);
+
+ unsigned m_max_len;
+ int m_last_x;
+ int m_y;
+ span_array_type m_spans;
+ };
+
+
+
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_scanline_boolean_algebra.h b/plugins/Clist_ng/AGG/include/agg_scanline_boolean_algebra.h new file mode 100644 index 0000000000..7e0970bc50 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_scanline_boolean_algebra.h @@ -0,0 +1,1576 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED
+#define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED
+
+#include <stdlib.h>
+#include <math.h>
+#include "agg_basics.h"
+
+
+namespace agg
+{
+
+ //-----------------------------------------------sbool_combine_spans_bin
+ // Functor.
+ // Combine two binary encoded spans, i.e., when we don't have any
+ // anti-aliasing information, but only X and Length. The function
+ // is compatible with any type of scanlines.
+ //----------------
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline>
+ struct sbool_combine_spans_bin
+ {
+ void operator () (const typename Scanline1::const_iterator&,
+ const typename Scanline2::const_iterator&,
+ int x, unsigned len,
+ Scanline& sl) const
+ {
+ sl.add_span(x, len, cover_full);
+ }
+ };
+
+
+
+ //---------------------------------------------sbool_combine_spans_empty
+ // Functor.
+ // Combine two spans as empty ones. The functor does nothing
+ // and is used to XOR binary spans.
+ //----------------
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline>
+ struct sbool_combine_spans_empty
+ {
+ void operator () (const typename Scanline1::const_iterator&,
+ const typename Scanline2::const_iterator&,
+ int, unsigned,
+ Scanline&) const
+ {}
+ };
+
+
+
+ //--------------------------------------------------sbool_add_span_empty
+ // Functor.
+ // Add nothing. Used in conbine_shapes_sub
+ //----------------
+ template<class Scanline1,
+ class Scanline>
+ struct sbool_add_span_empty
+ {
+ void operator () (const typename Scanline1::const_iterator&,
+ int, unsigned,
+ Scanline&) const
+ {}
+ };
+
+
+ //----------------------------------------------------sbool_add_span_bin
+ // Functor.
+ // Add a binary span
+ //----------------
+ template<class Scanline1,
+ class Scanline>
+ struct sbool_add_span_bin
+ {
+ void operator () (const typename Scanline1::const_iterator&,
+ int x, unsigned len,
+ Scanline& sl) const
+ {
+ sl.add_span(x, len, cover_full);
+ }
+ };
+
+
+
+
+ //-----------------------------------------------------sbool_add_span_aa
+ // Functor.
+ // Add an anti-aliased span
+ // anti-aliasing information, but only X and Length. The function
+ // is compatible with any type of scanlines.
+ //----------------
+ template<class Scanline1,
+ class Scanline>
+ struct sbool_add_span_aa
+ {
+ void operator () (const typename Scanline1::const_iterator& span,
+ int x, unsigned len,
+ Scanline& sl) const
+ {
+ if(span->len < 0)
+ {
+ sl.add_span(x, len, *span->covers);
+ }
+ else
+ if(span->len > 0)
+ {
+ const typename Scanline1::cover_type* covers = span->covers;
+ if(span->x < x) covers += x - span->x;
+ sl.add_cells(x, len, covers);
+ }
+ }
+ };
+
+
+
+
+ //----------------------------------------------sbool_intersect_spans_aa
+ // Functor.
+ // Intersect two spans preserving the anti-aliasing information.
+ // The result is added to the "sl" scanline.
+ //------------------
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline,
+ unsigned CoverShift = cover_shift>
+ struct sbool_intersect_spans_aa
+ {
+ enum cover_scale_e
+ {
+ cover_shift = CoverShift,
+ cover_size = 1 << cover_shift,
+ cover_mask = cover_size - 1,
+ cover_full = cover_mask
+ };
+
+
+ void operator () (const typename Scanline1::const_iterator& span1,
+ const typename Scanline2::const_iterator& span2,
+ int x, unsigned len,
+ Scanline& sl) const
+ {
+ unsigned cover;
+ const typename Scanline1::cover_type* covers1;
+ const typename Scanline2::cover_type* covers2;
+
+ // Calculate the operation code and choose the
+ // proper combination algorithm.
+ // 0 = Both spans are of AA type
+ // 1 = span1 is solid, span2 is AA
+ // 2 = span1 is AA, span2 is solid
+ // 3 = Both spans are of solid type
+ //-----------------
+ switch((span1->len < 0) | ((span2->len < 0) << 1))
+ {
+ case 0: // Both are AA spans
+ covers1 = span1->covers;
+ covers2 = span2->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ if(span2->x < x) covers2 += x - span2->x;
+ do
+ {
+ cover = *covers1++ * *covers2++;
+ sl.add_cell(x++,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ while(--len);
+ break;
+
+ case 1: // span1 is solid, span2 is AA
+ covers2 = span2->covers;
+ if(span2->x < x) covers2 += x - span2->x;
+ if(*(span1->covers) == cover_full)
+ {
+ sl.add_cells(x, len, covers2);
+ }
+ else
+ {
+ do
+ {
+ cover = *(span1->covers) * *covers2++;
+ sl.add_cell(x++,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ while(--len);
+ }
+ break;
+
+ case 2: // span1 is AA, span2 is solid
+ covers1 = span1->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ if(*(span2->covers) == cover_full)
+ {
+ sl.add_cells(x, len, covers1);
+ }
+ else
+ {
+ do
+ {
+ cover = *covers1++ * *(span2->covers);
+ sl.add_cell(x++,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ while(--len);
+ }
+ break;
+
+ case 3: // Both are solid spans
+ cover = *(span1->covers) * *(span2->covers);
+ sl.add_span(x, len,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ break;
+ }
+ }
+ };
+
+
+
+
+
+
+ //--------------------------------------------------sbool_unite_spans_aa
+ // Functor.
+ // Unite two spans preserving the anti-aliasing information.
+ // The result is added to the "sl" scanline.
+ //------------------
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline,
+ unsigned CoverShift = cover_shift>
+ struct sbool_unite_spans_aa
+ {
+ enum cover_scale_e
+ {
+ cover_shift = CoverShift,
+ cover_size = 1 << cover_shift,
+ cover_mask = cover_size - 1,
+ cover_full = cover_mask
+ };
+
+
+ void operator () (const typename Scanline1::const_iterator& span1,
+ const typename Scanline2::const_iterator& span2,
+ int x, unsigned len,
+ Scanline& sl) const
+ {
+ unsigned cover;
+ const typename Scanline1::cover_type* covers1;
+ const typename Scanline2::cover_type* covers2;
+
+ // Calculate the operation code and choose the
+ // proper combination algorithm.
+ // 0 = Both spans are of AA type
+ // 1 = span1 is solid, span2 is AA
+ // 2 = span1 is AA, span2 is solid
+ // 3 = Both spans are of solid type
+ //-----------------
+ switch((span1->len < 0) | ((span2->len < 0) << 1))
+ {
+ case 0: // Both are AA spans
+ covers1 = span1->covers;
+ covers2 = span2->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ if(span2->x < x) covers2 += x - span2->x;
+ do
+ {
+ cover = cover_mask * cover_mask -
+ (cover_mask - *covers1++) *
+ (cover_mask - *covers2++);
+ sl.add_cell(x++,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ while(--len);
+ break;
+
+ case 1: // span1 is solid, span2 is AA
+ covers2 = span2->covers;
+ if(span2->x < x) covers2 += x - span2->x;
+ if(*(span1->covers) == cover_full)
+ {
+ sl.add_span(x, len, cover_full);
+ }
+ else
+ {
+ do
+ {
+ cover = cover_mask * cover_mask -
+ (cover_mask - *(span1->covers)) *
+ (cover_mask - *covers2++);
+ sl.add_cell(x++,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ while(--len);
+ }
+ break;
+
+ case 2: // span1 is AA, span2 is solid
+ covers1 = span1->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ if(*(span2->covers) == cover_full)
+ {
+ sl.add_span(x, len, cover_full);
+ }
+ else
+ {
+ do
+ {
+ cover = cover_mask * cover_mask -
+ (cover_mask - *covers1++) *
+ (cover_mask - *(span2->covers));
+ sl.add_cell(x++,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ while(--len);
+ }
+ break;
+
+ case 3: // Both are solid spans
+ cover = cover_mask * cover_mask -
+ (cover_mask - *(span1->covers)) *
+ (cover_mask - *(span2->covers));
+ sl.add_span(x, len,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ break;
+ }
+ }
+ };
+
+
+ //---------------------------------------------sbool_xor_formula_linear
+ template<unsigned CoverShift = cover_shift>
+ struct sbool_xor_formula_linear
+ {
+ enum cover_scale_e
+ {
+ cover_shift = CoverShift,
+ cover_size = 1 << cover_shift,
+ cover_mask = cover_size - 1
+ };
+
+ static AGG_INLINE unsigned calculate(unsigned a, unsigned b)
+ {
+ unsigned cover = a + b;
+ if(cover > cover_mask) cover = cover_mask + cover_mask - cover;
+ return cover;
+ }
+ };
+
+
+ //---------------------------------------------sbool_xor_formula_saddle
+ template<unsigned CoverShift = cover_shift>
+ struct sbool_xor_formula_saddle
+ {
+ enum cover_scale_e
+ {
+ cover_shift = CoverShift,
+ cover_size = 1 << cover_shift,
+ cover_mask = cover_size - 1
+ };
+
+ static AGG_INLINE unsigned calculate(unsigned a, unsigned b)
+ {
+ unsigned k = a * b;
+ if(k == cover_mask * cover_mask) return 0;
+
+ a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift;
+ b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift;
+ return cover_mask - ((a * b) >> cover_shift);
+ }
+ };
+
+
+ //-------------------------------------------sbool_xor_formula_abs_diff
+ struct sbool_xor_formula_abs_diff
+ {
+ static AGG_INLINE unsigned calculate(unsigned a, unsigned b)
+ {
+ return unsigned(abs(int(a) - int(b)));
+ }
+ };
+
+
+
+ //----------------------------------------------------sbool_xor_spans_aa
+ // Functor.
+ // XOR two spans preserving the anti-aliasing information.
+ // The result is added to the "sl" scanline.
+ //------------------
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class XorFormula,
+ unsigned CoverShift = cover_shift>
+ struct sbool_xor_spans_aa
+ {
+ enum cover_scale_e
+ {
+ cover_shift = CoverShift,
+ cover_size = 1 << cover_shift,
+ cover_mask = cover_size - 1,
+ cover_full = cover_mask
+ };
+
+
+ void operator () (const typename Scanline1::const_iterator& span1,
+ const typename Scanline2::const_iterator& span2,
+ int x, unsigned len,
+ Scanline& sl) const
+ {
+ unsigned cover;
+ const typename Scanline1::cover_type* covers1;
+ const typename Scanline2::cover_type* covers2;
+
+ // Calculate the operation code and choose the
+ // proper combination algorithm.
+ // 0 = Both spans are of AA type
+ // 1 = span1 is solid, span2 is AA
+ // 2 = span1 is AA, span2 is solid
+ // 3 = Both spans are of solid type
+ //-----------------
+ switch((span1->len < 0) | ((span2->len < 0) << 1))
+ {
+ case 0: // Both are AA spans
+ covers1 = span1->covers;
+ covers2 = span2->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ if(span2->x < x) covers2 += x - span2->x;
+ do
+ {
+ cover = XorFormula::calculate(*covers1++, *covers2++);
+ if(cover) sl.add_cell(x, cover);
+ ++x;
+ }
+ while(--len);
+ break;
+
+ case 1: // span1 is solid, span2 is AA
+ covers2 = span2->covers;
+ if(span2->x < x) covers2 += x - span2->x;
+ do
+ {
+ cover = XorFormula::calculate(*(span1->covers), *covers2++);
+ if(cover) sl.add_cell(x, cover);
+ ++x;
+ }
+ while(--len);
+ break;
+
+ case 2: // span1 is AA, span2 is solid
+ covers1 = span1->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ do
+ {
+ cover = XorFormula::calculate(*covers1++, *(span2->covers));
+ if(cover) sl.add_cell(x, cover);
+ ++x;
+ }
+ while(--len);
+ break;
+
+ case 3: // Both are solid spans
+ cover = XorFormula::calculate(*(span1->covers), *(span2->covers));
+ if(cover) sl.add_span(x, len, cover);
+ break;
+
+ }
+ }
+ };
+
+
+
+
+
+ //-----------------------------------------------sbool_subtract_spans_aa
+ // Functor.
+ // Unite two spans preserving the anti-aliasing information.
+ // The result is added to the "sl" scanline.
+ //------------------
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline,
+ unsigned CoverShift = cover_shift>
+ struct sbool_subtract_spans_aa
+ {
+ enum cover_scale_e
+ {
+ cover_shift = CoverShift,
+ cover_size = 1 << cover_shift,
+ cover_mask = cover_size - 1,
+ cover_full = cover_mask
+ };
+
+
+ void operator () (const typename Scanline1::const_iterator& span1,
+ const typename Scanline2::const_iterator& span2,
+ int x, unsigned len,
+ Scanline& sl) const
+ {
+ unsigned cover;
+ const typename Scanline1::cover_type* covers1;
+ const typename Scanline2::cover_type* covers2;
+
+ // Calculate the operation code and choose the
+ // proper combination algorithm.
+ // 0 = Both spans are of AA type
+ // 1 = span1 is solid, span2 is AA
+ // 2 = span1 is AA, span2 is solid
+ // 3 = Both spans are of solid type
+ //-----------------
+ switch((span1->len < 0) | ((span2->len < 0) << 1))
+ {
+ case 0: // Both are AA spans
+ covers1 = span1->covers;
+ covers2 = span2->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ if(span2->x < x) covers2 += x - span2->x;
+ do
+ {
+ cover = *covers1++ * (cover_mask - *covers2++);
+ if(cover)
+ {
+ sl.add_cell(x,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ ++x;
+ }
+ while(--len);
+ break;
+
+ case 1: // span1 is solid, span2 is AA
+ covers2 = span2->covers;
+ if(span2->x < x) covers2 += x - span2->x;
+ do
+ {
+ cover = *(span1->covers) * (cover_mask - *covers2++);
+ if(cover)
+ {
+ sl.add_cell(x,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ ++x;
+ }
+ while(--len);
+ break;
+
+ case 2: // span1 is AA, span2 is solid
+ covers1 = span1->covers;
+ if(span1->x < x) covers1 += x - span1->x;
+ if(*(span2->covers) != cover_full)
+ {
+ do
+ {
+ cover = *covers1++ * (cover_mask - *(span2->covers));
+ if(cover)
+ {
+ sl.add_cell(x,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ ++x;
+ }
+ while(--len);
+ }
+ break;
+
+ case 3: // Both are solid spans
+ cover = *(span1->covers) * (cover_mask - *(span2->covers));
+ if(cover)
+ {
+ sl.add_span(x, len,
+ (cover == cover_full * cover_full) ?
+ cover_full :
+ (cover >> cover_shift));
+ }
+ break;
+ }
+ }
+ };
+
+
+
+
+
+
+ //--------------------------------------------sbool_add_spans_and_render
+ template<class Scanline1,
+ class Scanline,
+ class Renderer,
+ class AddSpanFunctor>
+ void sbool_add_spans_and_render(const Scanline1& sl1,
+ Scanline& sl,
+ Renderer& ren,
+ AddSpanFunctor add_span)
+ {
+ sl.reset_spans();
+ typename Scanline1::const_iterator span = sl1.begin();
+ unsigned num_spans = sl1.num_spans();
+ for(;;)
+ {
+ add_span(span, span->x, abs((int)span->len), sl);
+ if(--num_spans == 0) break;
+ ++span;
+ }
+ sl.finalize(sl1.y());
+ ren.render(sl);
+ }
+
+
+
+
+
+
+
+ //---------------------------------------------sbool_intersect_scanlines
+ // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one.
+ // The combine_spans functor can be of type sbool_combine_spans_bin or
+ // sbool_intersect_spans_aa. First is a general functor to combine
+ // two spans without Anti-Aliasing, the second preserves the AA
+ // information, but works slower
+ //
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class CombineSpansFunctor>
+ void sbool_intersect_scanlines(const Scanline1& sl1,
+ const Scanline2& sl2,
+ Scanline& sl,
+ CombineSpansFunctor combine_spans)
+ {
+ sl.reset_spans();
+
+ unsigned num1 = sl1.num_spans();
+ if(num1 == 0) return;
+
+ unsigned num2 = sl2.num_spans();
+ if(num2 == 0) return;
+
+ typename Scanline1::const_iterator span1 = sl1.begin();
+ typename Scanline2::const_iterator span2 = sl2.begin();
+
+ while(num1 && num2)
+ {
+ int xb1 = span1->x;
+ int xb2 = span2->x;
+ int xe1 = xb1 + abs((int)span1->len) - 1;
+ int xe2 = xb2 + abs((int)span2->len) - 1;
+
+ // Determine what spans we should advance in the next step
+ // The span with the least ending X should be advanced
+ // advance_both is just an optimization when we ending
+ // coordinates are the same and we can advance both
+ //--------------
+ bool advance_span1 = xe1 < xe2;
+ bool advance_both = xe1 == xe2;
+
+ // Find the intersection of the spans
+ // and check if they intersect
+ //--------------
+ if(xb1 < xb2) xb1 = xb2;
+ if(xe1 > xe2) xe1 = xe2;
+ if(xb1 <= xe1)
+ {
+ combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl);
+ }
+
+ // Advance the spans
+ //--------------
+ if(advance_both)
+ {
+ --num1;
+ --num2;
+ if(num1) ++span1;
+ if(num2) ++span2;
+ }
+ else
+ {
+ if(advance_span1)
+ {
+ --num1;
+ if(num1) ++span1;
+ }
+ else
+ {
+ --num2;
+ if(num2) ++span2;
+ }
+ }
+ }
+ }
+
+
+
+
+
+
+
+
+ //------------------------------------------------sbool_intersect_shapes
+ // Intersect the scanline shapes. Here the "Scanline Generator"
+ // abstraction is used. ScanlineGen1 and ScanlineGen2 are
+ // the generators, and can be of type rasterizer_scanline_aa<>.
+ // There function requires three scanline containers that can be of
+ // different types.
+ // "sl1" and "sl2" are used to retrieve scanlines from the generators,
+ // "sl" is ised as the resulting scanline to render it.
+ // The external "sl1" and "sl2" are used only for the sake of
+ // optimization and reusing of the scanline objects.
+ // the function calls sbool_intersect_scanlines with CombineSpansFunctor
+ // as the last argument. See sbool_intersect_scanlines for details.
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer,
+ class CombineSpansFunctor>
+ void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren,
+ CombineSpansFunctor combine_spans)
+ {
+ // Prepare the scanline generators.
+ // If anyone of them doesn't contain
+ // any scanlines, then return.
+ //-----------------
+ if(!sg1.rewind_scanlines()) return;
+ if(!sg2.rewind_scanlines()) return;
+
+ // Get the bounding boxes
+ //----------------
+ rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
+ rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y());
+
+ // Calculate the intersection of the bounding
+ // boxes and return if they don't intersect.
+ //-----------------
+ rect_i ir = intersect_rectangles(r1, r2);
+ if(!ir.is_valid()) return;
+
+ // Reset the scanlines and get two first ones
+ //-----------------
+ sl.reset(ir.x1, ir.x2);
+ sl1.reset(sg1.min_x(), sg1.max_x());
+ sl2.reset(sg2.min_x(), sg2.max_x());
+ if(!sg1.sweep_scanline(sl1)) return;
+ if(!sg2.sweep_scanline(sl2)) return;
+
+ ren.prepare();
+
+ // The main loop
+ // Here we synchronize the scanlines with
+ // the same Y coordinate, ignoring all other ones.
+ // Only scanlines having the same Y-coordinate
+ // are to be combined.
+ //-----------------
+ for(;;)
+ {
+ while(sl1.y() < sl2.y())
+ {
+ if(!sg1.sweep_scanline(sl1)) return;
+ }
+ while(sl2.y() < sl1.y())
+ {
+ if(!sg2.sweep_scanline(sl2)) return;
+ }
+
+ if(sl1.y() == sl2.y())
+ {
+ // The Y coordinates are the same.
+ // Combine the scanlines, render if they contain any spans,
+ // and advance both generators to the next scanlines
+ //----------------------
+ sbool_intersect_scanlines(sl1, sl2, sl, combine_spans);
+ if(sl.num_spans())
+ {
+ sl.finalize(sl1.y());
+ ren.render(sl);
+ }
+ if(!sg1.sweep_scanline(sl1)) return;
+ if(!sg2.sweep_scanline(sl2)) return;
+ }
+ }
+ }
+
+
+
+
+
+
+
+ //-------------------------------------------------sbool_unite_scanlines
+ // Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one.
+ // The combine_spans functor can be of type sbool_combine_spans_bin or
+ // sbool_intersect_spans_aa. First is a general functor to combine
+ // two spans without Anti-Aliasing, the second preserves the AA
+ // information, but works slower
+ //
+ template<class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class AddSpanFunctor1,
+ class AddSpanFunctor2,
+ class CombineSpansFunctor>
+ void sbool_unite_scanlines(const Scanline1& sl1,
+ const Scanline2& sl2,
+ Scanline& sl,
+ AddSpanFunctor1 add_span1,
+ AddSpanFunctor2 add_span2,
+ CombineSpansFunctor combine_spans)
+ {
+ sl.reset_spans();
+
+ unsigned num1 = sl1.num_spans();
+ unsigned num2 = sl2.num_spans();
+
+ typename Scanline1::const_iterator span1;// = sl1.begin();
+ typename Scanline2::const_iterator span2;// = sl2.begin();
+
+ enum invalidation_e
+ {
+ invalid_b = 0xFFFFFFF,
+ invalid_e = invalid_b - 1
+ };
+
+ // Initialize the spans as invalid
+ //---------------
+ int xb1 = invalid_b;
+ int xb2 = invalid_b;
+ int xe1 = invalid_e;
+ int xe2 = invalid_e;
+
+ // Initialize span1 if there are spans
+ //---------------
+ if(num1)
+ {
+ span1 = sl1.begin();
+ xb1 = span1->x;
+ xe1 = xb1 + abs((int)span1->len) - 1;
+ --num1;
+ }
+
+ // Initialize span2 if there are spans
+ //---------------
+ if(num2)
+ {
+ span2 = sl2.begin();
+ xb2 = span2->x;
+ xe2 = xb2 + abs((int)span2->len) - 1;
+ --num2;
+ }
+
+
+ for(;;)
+ {
+ // Retrieve a new span1 if it's invalid
+ //----------------
+ if(num1 && xb1 > xe1)
+ {
+ --num1;
+ ++span1;
+ xb1 = span1->x;
+ xe1 = xb1 + abs((int)span1->len) - 1;
+ }
+
+ // Retrieve a new span2 if it's invalid
+ //----------------
+ if(num2 && xb2 > xe2)
+ {
+ --num2;
+ ++span2;
+ xb2 = span2->x;
+ xe2 = xb2 + abs((int)span2->len) - 1;
+ }
+
+ if(xb1 > xe1 && xb2 > xe2) break;
+
+ // Calculate the intersection
+ //----------------
+ int xb = xb1;
+ int xe = xe1;
+ if(xb < xb2) xb = xb2;
+ if(xe > xe2) xe = xe2;
+ int len = xe - xb + 1; // The length of the intersection
+ if(len > 0)
+ {
+ // The spans intersect,
+ // add the beginning of the span
+ //----------------
+ if(xb1 < xb2)
+ {
+ add_span1(span1, xb1, xb2 - xb1, sl);
+ xb1 = xb2;
+ }
+ else
+ if(xb2 < xb1)
+ {
+ add_span2(span2, xb2, xb1 - xb2, sl);
+ xb2 = xb1;
+ }
+
+ // Add the combination part of the spans
+ //----------------
+ combine_spans(span1, span2, xb, len, sl);
+
+
+ // Invalidate the fully processed span or both
+ //----------------
+ if(xe1 < xe2)
+ {
+ // Invalidate span1 and eat
+ // the processed part of span2
+ //--------------
+ xb1 = invalid_b;
+ xe1 = invalid_e;
+ xb2 += len;
+ }
+ else
+ if(xe2 < xe1)
+ {
+ // Invalidate span2 and eat
+ // the processed part of span1
+ //--------------
+ xb2 = invalid_b;
+ xe2 = invalid_e;
+ xb1 += len;
+ }
+ else
+ {
+ xb1 = invalid_b; // Invalidate both
+ xb2 = invalid_b;
+ xe1 = invalid_e;
+ xe2 = invalid_e;
+ }
+ }
+ else
+ {
+ // The spans do not intersect
+ //--------------
+ if(xb1 < xb2)
+ {
+ // Advance span1
+ //---------------
+ if(xb1 <= xe1)
+ {
+ add_span1(span1, xb1, xe1 - xb1 + 1, sl);
+ }
+ xb1 = invalid_b; // Invalidate
+ xe1 = invalid_e;
+ }
+ else
+ {
+ // Advance span2
+ //---------------
+ if(xb2 <= xe2)
+ {
+ add_span2(span2, xb2, xe2 - xb2 + 1, sl);
+ }
+ xb2 = invalid_b; // Invalidate
+ xe2 = invalid_e;
+ }
+ }
+ }
+ }
+
+
+
+
+ //----------------------------------------------------sbool_unite_shapes
+ // Unite the scanline shapes. Here the "Scanline Generator"
+ // abstraction is used. ScanlineGen1 and ScanlineGen2 are
+ // the generators, and can be of type rasterizer_scanline_aa<>.
+ // There function requires three scanline containers that can be
+ // of different type.
+ // "sl1" and "sl2" are used to retrieve scanlines from the generators,
+ // "sl" is ised as the resulting scanline to render it.
+ // The external "sl1" and "sl2" are used only for the sake of
+ // optimization and reusing of the scanline objects.
+ // the function calls sbool_unite_scanlines with CombineSpansFunctor
+ // as the last argument. See sbool_unite_scanlines for details.
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer,
+ class AddSpanFunctor1,
+ class AddSpanFunctor2,
+ class CombineSpansFunctor>
+ void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren,
+ AddSpanFunctor1 add_span1,
+ AddSpanFunctor2 add_span2,
+ CombineSpansFunctor combine_spans)
+ {
+ // Prepare the scanline generators.
+ // If anyone of them doesn't contain
+ // any scanlines, then return.
+ //-----------------
+ bool flag1 = sg1.rewind_scanlines();
+ bool flag2 = sg2.rewind_scanlines();
+ if(!flag1 && !flag2) return;
+
+ // Get the bounding boxes
+ //----------------
+ rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
+ rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y());
+
+ // Calculate the union of the bounding boxes
+ //-----------------
+ rect_i ur(1,1,0,0);
+ if(flag1 && flag2) ur = unite_rectangles(r1, r2);
+ else if(flag1) ur = r1;
+ else if(flag2) ur = r2;
+
+ if(!ur.is_valid()) return;
+
+ ren.prepare();
+
+ // Reset the scanlines and get two first ones
+ //-----------------
+ sl.reset(ur.x1, ur.x2);
+ if(flag1)
+ {
+ sl1.reset(sg1.min_x(), sg1.max_x());
+ flag1 = sg1.sweep_scanline(sl1);
+ }
+
+ if(flag2)
+ {
+ sl2.reset(sg2.min_x(), sg2.max_x());
+ flag2 = sg2.sweep_scanline(sl2);
+ }
+
+ // The main loop
+ // Here we synchronize the scanlines with
+ // the same Y coordinate.
+ //-----------------
+ while(flag1 || flag2)
+ {
+ if(flag1 && flag2)
+ {
+ if(sl1.y() == sl2.y())
+ {
+ // The Y coordinates are the same.
+ // Combine the scanlines, render if they contain any spans,
+ // and advance both generators to the next scanlines
+ //----------------------
+ sbool_unite_scanlines(sl1, sl2, sl,
+ add_span1, add_span2, combine_spans);
+ if(sl.num_spans())
+ {
+ sl.finalize(sl1.y());
+ ren.render(sl);
+ }
+ flag1 = sg1.sweep_scanline(sl1);
+ flag2 = sg2.sweep_scanline(sl2);
+ }
+ else
+ {
+ if(sl1.y() < sl2.y())
+ {
+ sbool_add_spans_and_render(sl1, sl, ren, add_span1);
+ flag1 = sg1.sweep_scanline(sl1);
+ }
+ else
+ {
+ sbool_add_spans_and_render(sl2, sl, ren, add_span2);
+ flag2 = sg2.sweep_scanline(sl2);
+ }
+ }
+ }
+ else
+ {
+ if(flag1)
+ {
+ sbool_add_spans_and_render(sl1, sl, ren, add_span1);
+ flag1 = sg1.sweep_scanline(sl1);
+ }
+ if(flag2)
+ {
+ sbool_add_spans_and_render(sl2, sl, ren, add_span2);
+ flag2 = sg2.sweep_scanline(sl2);
+ }
+ }
+ }
+ }
+
+
+
+
+
+
+
+
+ //-------------------------------------------------sbool_subtract_shapes
+ // Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator"
+ // abstraction is used. ScanlineGen1 and ScanlineGen2 are
+ // the generators, and can be of type rasterizer_scanline_aa<>.
+ // There function requires three scanline containers that can be of
+ // different types.
+ // "sl1" and "sl2" are used to retrieve scanlines from the generators,
+ // "sl" is ised as the resulting scanline to render it.
+ // The external "sl1" and "sl2" are used only for the sake of
+ // optimization and reusing of the scanline objects.
+ // the function calls sbool_intersect_scanlines with CombineSpansFunctor
+ // as the last argument. See combine_scanlines_sub for details.
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer,
+ class AddSpanFunctor1,
+ class CombineSpansFunctor>
+ void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren,
+ AddSpanFunctor1 add_span1,
+ CombineSpansFunctor combine_spans)
+ {
+ // Prepare the scanline generators.
+ // Here "sg1" is master, "sg2" is slave.
+ //-----------------
+ if(!sg1.rewind_scanlines()) return;
+ bool flag2 = sg2.rewind_scanlines();
+
+ // Get the bounding box
+ //----------------
+ rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y());
+
+ // Reset the scanlines and get two first ones
+ //-----------------
+ sl.reset(sg1.min_x(), sg1.max_x());
+ sl1.reset(sg1.min_x(), sg1.max_x());
+ sl2.reset(sg2.min_x(), sg2.max_x());
+ if(!sg1.sweep_scanline(sl1)) return;
+
+ if(flag2) flag2 = sg2.sweep_scanline(sl2);
+
+ ren.prepare();
+
+ // A fake span2 processor
+ sbool_add_span_empty<Scanline2, Scanline> add_span2;
+
+ // The main loop
+ // Here we synchronize the scanlines with
+ // the same Y coordinate, ignoring all other ones.
+ // Only scanlines having the same Y-coordinate
+ // are to be combined.
+ //-----------------
+ bool flag1 = true;
+ do
+ {
+ // Synchronize "slave" with "master"
+ //-----------------
+ while(flag2 && sl2.y() < sl1.y())
+ {
+ flag2 = sg2.sweep_scanline(sl2);
+ }
+
+
+ if(flag2 && sl2.y() == sl1.y())
+ {
+ // The Y coordinates are the same.
+ // Combine the scanlines and render if they contain any spans.
+ //----------------------
+ sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans);
+ if(sl.num_spans())
+ {
+ sl.finalize(sl1.y());
+ ren.render(sl);
+ }
+ }
+ else
+ {
+ sbool_add_spans_and_render(sl1, sl, ren, add_span1);
+ }
+
+ // Advance the "master"
+ flag1 = sg1.sweep_scanline(sl1);
+ }
+ while(flag1);
+ }
+
+
+
+
+
+
+
+ //---------------------------------------------sbool_intersect_shapes_aa
+ // Intersect two anti-aliased scanline shapes.
+ // Here the "Scanline Generator" abstraction is used.
+ // ScanlineGen1 and ScanlineGen2 are the generators, and can be of
+ // type rasterizer_scanline_aa<>. There function requires three
+ // scanline containers that can be of different types.
+ // "sl1" and "sl2" are used to retrieve scanlines from the generators,
+ // "sl" is ised as the resulting scanline to render it.
+ // The external "sl1" and "sl2" are used only for the sake of
+ // optimization and reusing of the scanline objects.
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_intersect_spans_aa<Scanline1, Scanline2, Scanline> combine_functor;
+ sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor);
+ }
+
+
+
+
+
+ //--------------------------------------------sbool_intersect_shapes_bin
+ // Intersect two binary scanline shapes (without anti-aliasing).
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor;
+ sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor);
+ }
+
+
+
+
+
+ //-------------------------------------------------sbool_unite_shapes_aa
+ // Unite two anti-aliased scanline shapes
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_aa<Scanline1, Scanline> add_functor1;
+ sbool_add_span_aa<Scanline2, Scanline> add_functor2;
+ sbool_unite_spans_aa<Scanline1, Scanline2, Scanline> combine_functor;
+ sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor1, add_functor2, combine_functor);
+ }
+
+
+
+
+
+ //------------------------------------------------sbool_unite_shapes_bin
+ // Unite two binary scanline shapes (without anti-aliasing).
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_bin<Scanline1, Scanline> add_functor1;
+ sbool_add_span_bin<Scanline2, Scanline> add_functor2;
+ sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor;
+ sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor1, add_functor2, combine_functor);
+ }
+
+
+
+
+
+
+
+
+
+ //---------------------------------------------------sbool_xor_shapes_aa
+ // Apply eXclusive OR to two anti-aliased scanline shapes. There's
+ // a modified "Linear" XOR used instead of classical "Saddle" one.
+ // The reason is to have the result absolutely conststent with what
+ // the scanline rasterizer produces.
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_aa<Scanline1, Scanline> add_functor1;
+ sbool_add_span_aa<Scanline2, Scanline> add_functor2;
+ sbool_xor_spans_aa<Scanline1, Scanline2, Scanline,
+ sbool_xor_formula_linear<> > combine_functor;
+ sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor1, add_functor2, combine_functor);
+ }
+
+
+
+ //------------------------------------------sbool_xor_shapes_saddle_aa
+ // Apply eXclusive OR to two anti-aliased scanline shapes.
+ // There's the classical "Saddle" used to calculate the
+ // Anti-Aliasing values, that is:
+ // a XOR b : 1-((1-a+a*b)*(1-b+a*b))
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_aa<Scanline1, Scanline> add_functor1;
+ sbool_add_span_aa<Scanline2, Scanline> add_functor2;
+ sbool_xor_spans_aa<Scanline1,
+ Scanline2,
+ Scanline,
+ sbool_xor_formula_saddle<> > combine_functor;
+ sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor1, add_functor2, combine_functor);
+ }
+
+
+ //--------------------------------------sbool_xor_shapes_abs_diff_aa
+ // Apply eXclusive OR to two anti-aliased scanline shapes.
+ // There's the absolute difference used to calculate
+ // Anti-Aliasing values, that is:
+ // a XOR b : abs(a-b)
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_aa<Scanline1, Scanline> add_functor1;
+ sbool_add_span_aa<Scanline2, Scanline> add_functor2;
+ sbool_xor_spans_aa<Scanline1,
+ Scanline2,
+ Scanline,
+ sbool_xor_formula_abs_diff> combine_functor;
+ sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor1, add_functor2, combine_functor);
+ }
+
+
+
+ //--------------------------------------------------sbool_xor_shapes_bin
+ // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing).
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_bin<Scanline1, Scanline> add_functor1;
+ sbool_add_span_bin<Scanline2, Scanline> add_functor2;
+ sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor;
+ sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor1, add_functor2, combine_functor);
+ }
+
+
+
+
+
+
+ //----------------------------------------------sbool_subtract_shapes_aa
+ // Subtract shapes "sg1-sg2" with anti-aliasing
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_aa<Scanline1, Scanline> add_functor;
+ sbool_subtract_spans_aa<Scanline1, Scanline2, Scanline> combine_functor;
+ sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor, combine_functor);
+ }
+
+
+
+
+
+ //---------------------------------------------sbool_subtract_shapes_bin
+ // Subtract binary shapes "sg1-sg2" without anti-aliasing
+ // See intersect_shapes_aa for more comments
+ //----------
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ sbool_add_span_bin<Scanline1, Scanline> add_functor;
+ sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor;
+ sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren,
+ add_functor, combine_functor);
+ }
+
+
+
+
+
+
+ //------------------------------------------------------------sbool_op_e
+ enum sbool_op_e
+ {
+ sbool_or, //----sbool_or
+ sbool_and, //----sbool_and
+ sbool_xor, //----sbool_xor
+ sbool_xor_saddle, //----sbool_xor_saddle
+ sbool_xor_abs_diff, //----sbool_xor_abs_diff
+ sbool_a_minus_b, //----sbool_a_minus_b
+ sbool_b_minus_a //----sbool_b_minus_a
+ };
+
+
+
+
+
+
+ //----------------------------------------------sbool_combine_shapes_bin
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_combine_shapes_bin(sbool_op_e op,
+ ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ switch(op)
+ {
+ case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_xor :
+ case sbool_xor_saddle :
+ case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break;
+ }
+ }
+
+
+
+
+ //-----------------------------------------------sbool_combine_shapes_aa
+ template<class ScanlineGen1,
+ class ScanlineGen2,
+ class Scanline1,
+ class Scanline2,
+ class Scanline,
+ class Renderer>
+ void sbool_combine_shapes_aa(sbool_op_e op,
+ ScanlineGen1& sg1, ScanlineGen2& sg2,
+ Scanline1& sl1, Scanline2& sl2,
+ Scanline& sl, Renderer& ren)
+ {
+ switch(op)
+ {
+ case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break;
+ case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break;
+ }
+ }
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_scanline_p.h b/plugins/Clist_ng/AGG/include/agg_scanline_p.h new file mode 100644 index 0000000000..2380bcefb8 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_scanline_p.h @@ -0,0 +1,334 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+#ifndef AGG_SCANLINE_P_INCLUDED
+#define AGG_SCANLINE_P_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+
+ //=============================================================scanline_p8
+ //
+ // This is a general purpose scaline container which supports the interface
+ // used in the rasterizer::render(). See description of scanline_u8
+ // for details.
+ //
+ //------------------------------------------------------------------------
+ class scanline_p8
+ {
+ public:
+ typedef scanline_p8 self_type;
+ typedef int8u cover_type;
+ typedef int16 coord_type;
+
+ //--------------------------------------------------------------------
+ struct span
+ {
+ coord_type x;
+ coord_type len; // If negative, it's a solid span, covers is valid
+ const cover_type* covers;
+ };
+
+ typedef span* iterator;
+ typedef const span* const_iterator;
+
+ scanline_p8() :
+ m_last_x(0x7FFFFFF0),
+ m_covers(),
+ m_cover_ptr(0),
+ m_spans(),
+ m_cur_span(0)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void reset(int min_x, int max_x)
+ {
+ unsigned max_len = max_x - min_x + 3;
+ if(max_len > m_spans.size())
+ {
+ m_spans.resize(max_len);
+ m_covers.resize(max_len);
+ }
+ m_last_x = 0x7FFFFFF0;
+ m_cover_ptr = &m_covers[0];
+ m_cur_span = &m_spans[0];
+ m_cur_span->len = 0;
+ }
+
+ //--------------------------------------------------------------------
+ void add_cell(int x, unsigned cover)
+ {
+ *m_cover_ptr = (cover_type)cover;
+ if(x == m_last_x+1 && m_cur_span->len > 0)
+ {
+ m_cur_span->len++;
+ }
+ else
+ {
+ m_cur_span++;
+ m_cur_span->covers = m_cover_ptr;
+ m_cur_span->x = (int16)x;
+ m_cur_span->len = 1;
+ }
+ m_last_x = x;
+ m_cover_ptr++;
+ }
+
+ //--------------------------------------------------------------------
+ void add_cells(int x, unsigned len, const cover_type* covers)
+ {
+ memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
+ if(x == m_last_x+1 && m_cur_span->len > 0)
+ {
+ m_cur_span->len += (int16)len;
+ }
+ else
+ {
+ m_cur_span++;
+ m_cur_span->covers = m_cover_ptr;
+ m_cur_span->x = (int16)x;
+ m_cur_span->len = (int16)len;
+ }
+ m_cover_ptr += len;
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void add_span(int x, unsigned len, unsigned cover)
+ {
+ if(x == m_last_x+1 &&
+ m_cur_span->len < 0 &&
+ cover == *m_cur_span->covers)
+ {
+ m_cur_span->len -= (int16)len;
+ }
+ else
+ {
+ *m_cover_ptr = (cover_type)cover;
+ m_cur_span++;
+ m_cur_span->covers = m_cover_ptr++;
+ m_cur_span->x = (int16)x;
+ m_cur_span->len = (int16)(-int(len));
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void finalize(int y)
+ {
+ m_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_spans()
+ {
+ m_last_x = 0x7FFFFFF0;
+ m_cover_ptr = &m_covers[0];
+ m_cur_span = &m_spans[0];
+ m_cur_span->len = 0;
+ }
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y; }
+ unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
+ const_iterator begin() const { return &m_spans[1]; }
+
+ private:
+ scanline_p8(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ int m_last_x;
+ int m_y;
+ pod_array<cover_type> m_covers;
+ cover_type* m_cover_ptr;
+ pod_array<span> m_spans;
+ span* m_cur_span;
+ };
+
+
+
+
+
+
+
+
+ //==========================================================scanline32_p8
+ class scanline32_p8
+ {
+ public:
+ typedef scanline32_p8 self_type;
+ typedef int8u cover_type;
+ typedef int32 coord_type;
+
+ struct span
+ {
+ span() {}
+ span(coord_type x_, coord_type len_, const cover_type* covers_) :
+ x(x_), len(len_), covers(covers_) {}
+
+ coord_type x;
+ coord_type len; // If negative, it's a solid span, covers is valid
+ const cover_type* covers;
+ };
+ typedef pod_bvector<span, 4> span_array_type;
+
+
+ //--------------------------------------------------------------------
+ class const_iterator
+ {
+ public:
+ const_iterator(const span_array_type& spans) :
+ m_spans(spans),
+ m_span_idx(0)
+ {}
+
+ const span& operator*() const { return m_spans[m_span_idx]; }
+ const span* operator->() const { return &m_spans[m_span_idx]; }
+
+ void operator ++ () { ++m_span_idx; }
+
+ private:
+ const span_array_type& m_spans;
+ unsigned m_span_idx;
+ };
+
+ //--------------------------------------------------------------------
+ scanline32_p8() :
+ m_max_len(0),
+ m_last_x(0x7FFFFFF0),
+ m_covers(),
+ m_cover_ptr(0)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void reset(int min_x, int max_x)
+ {
+ unsigned max_len = max_x - min_x + 3;
+ if(max_len > m_covers.size())
+ {
+ m_covers.resize(max_len);
+ }
+ m_last_x = 0x7FFFFFF0;
+ m_cover_ptr = &m_covers[0];
+ m_spans.remove_all();
+ }
+
+ //--------------------------------------------------------------------
+ void add_cell(int x, unsigned cover)
+ {
+ *m_cover_ptr = cover_type(cover);
+ if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
+ {
+ m_spans.last().len++;
+ }
+ else
+ {
+ m_spans.add(span(coord_type(x), 1, m_cover_ptr));
+ }
+ m_last_x = x;
+ m_cover_ptr++;
+ }
+
+ //--------------------------------------------------------------------
+ void add_cells(int x, unsigned len, const cover_type* covers)
+ {
+ memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
+ if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
+ {
+ m_spans.last().len += coord_type(len);
+ }
+ else
+ {
+ m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr));
+ }
+ m_cover_ptr += len;
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void add_span(int x, unsigned len, unsigned cover)
+ {
+ if(x == m_last_x+1 &&
+ m_spans.size() &&
+ m_spans.last().len < 0 &&
+ cover == *m_spans.last().covers)
+ {
+ m_spans.last().len -= coord_type(len);
+ }
+ else
+ {
+ *m_cover_ptr = cover_type(cover);
+ m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void finalize(int y)
+ {
+ m_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_spans()
+ {
+ m_last_x = 0x7FFFFFF0;
+ m_cover_ptr = &m_covers[0];
+ m_spans.remove_all();
+ }
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y; }
+ unsigned num_spans() const { return m_spans.size(); }
+ const_iterator begin() const { return const_iterator(m_spans); }
+
+ private:
+ scanline32_p8(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ unsigned m_max_len;
+ int m_last_x;
+ int m_y;
+ pod_array<cover_type> m_covers;
+ cover_type* m_cover_ptr;
+ span_array_type m_spans;
+ };
+
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_scanline_storage_aa.h b/plugins/Clist_ng/AGG/include/agg_scanline_storage_aa.h new file mode 100644 index 0000000000..09e3434e1f --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_scanline_storage_aa.h @@ -0,0 +1,824 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED
+#define AGG_SCANLINE_STORAGE_AA_INCLUDED
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include "agg_array.h"
+
+
+namespace agg
+{
+
+ //----------------------------------------------scanline_cell_storage
+ template<class T> class scanline_cell_storage
+ {
+ struct extra_span
+ {
+ unsigned len;
+ T* ptr;
+ };
+
+ public:
+ typedef T value_type;
+
+ //---------------------------------------------------------------
+ ~scanline_cell_storage()
+ {
+ remove_all();
+ }
+
+ //---------------------------------------------------------------
+ scanline_cell_storage() :
+ m_cells(128-2),
+ m_extra_storage()
+ {}
+
+
+ // Copying
+ //---------------------------------------------------------------
+ scanline_cell_storage(const scanline_cell_storage<T>& v) :
+ m_cells(v.m_cells),
+ m_extra_storage()
+ {
+ copy_extra_storage(v);
+ }
+
+ //---------------------------------------------------------------
+ const scanline_cell_storage<T>&
+ operator = (const scanline_cell_storage<T>& v)
+ {
+ remove_all();
+ m_cells = v.m_cells;
+ copy_extra_storage(v);
+ return *this;
+ }
+
+ //---------------------------------------------------------------
+ void remove_all()
+ {
+ int i;
+ for(i = m_extra_storage.size()-1; i >= 0; --i)
+ {
+ pod_allocator<T>::deallocate(m_extra_storage[i].ptr,
+ m_extra_storage[i].len);
+ }
+ m_extra_storage.remove_all();
+ m_cells.remove_all();
+ }
+
+ //---------------------------------------------------------------
+ int add_cells(const T* cells, unsigned num_cells)
+ {
+ int idx = m_cells.allocate_continuous_block(num_cells);
+ if(idx >= 0)
+ {
+ T* ptr = &m_cells[idx];
+ memcpy(ptr, cells, sizeof(T) * num_cells);
+ return idx;
+ }
+ extra_span s;
+ s.len = num_cells;
+ s.ptr = pod_allocator<T>::allocate(num_cells);
+ memcpy(s.ptr, cells, sizeof(T) * num_cells);
+ m_extra_storage.add(s);
+ return -int(m_extra_storage.size());
+ }
+
+ //---------------------------------------------------------------
+ const T* operator [] (int idx) const
+ {
+ if(idx >= 0)
+ {
+ if((unsigned)idx >= m_cells.size()) return 0;
+ return &m_cells[(unsigned)idx];
+ }
+ unsigned i = unsigned(-idx - 1);
+ if(i >= m_extra_storage.size()) return 0;
+ return m_extra_storage[i].ptr;
+ }
+
+ //---------------------------------------------------------------
+ T* operator [] (int idx)
+ {
+ if(idx >= 0)
+ {
+ if((unsigned)idx >= m_cells.size()) return 0;
+ return &m_cells[(unsigned)idx];
+ }
+ unsigned i = unsigned(-idx - 1);
+ if(i >= m_extra_storage.size()) return 0;
+ return m_extra_storage[i].ptr;
+ }
+
+ private:
+ void copy_extra_storage(const scanline_cell_storage<T>& v)
+ {
+ unsigned i;
+ for(i = 0; i < v.m_extra_storage.size(); ++i)
+ {
+ const extra_span& src = v.m_extra_storage[i];
+ extra_span dst;
+ dst.len = src.len;
+ dst.ptr = pod_allocator<T>::allocate(dst.len);
+ memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
+ m_extra_storage.add(dst);
+ }
+ }
+
+ pod_bvector<T, 12> m_cells;
+ pod_bvector<extra_span, 6> m_extra_storage;
+ };
+
+
+
+
+
+
+ //-----------------------------------------------scanline_storage_aa
+ template<class T> class scanline_storage_aa
+ {
+ public:
+ typedef T cover_type;
+
+ //---------------------------------------------------------------
+ struct span_data
+ {
+ int32 x;
+ int32 len; // If negative, it's a solid span, covers is valid
+ int covers_id; // The index of the cells in the scanline_cell_storage
+ };
+
+ //---------------------------------------------------------------
+ struct scanline_data
+ {
+ int y;
+ unsigned num_spans;
+ unsigned start_span;
+ };
+
+
+ //---------------------------------------------------------------
+ class embedded_scanline
+ {
+ public:
+
+ //-----------------------------------------------------------
+ class const_iterator
+ {
+ public:
+ struct span
+ {
+ int32 x;
+ int32 len; // If negative, it's a solid span, covers is valid
+ const T* covers;
+ };
+
+ const_iterator() : m_storage(0) {}
+ const_iterator(const embedded_scanline& sl) :
+ m_storage(sl.m_storage),
+ m_span_idx(sl.m_scanline.start_span)
+ {
+ init_span();
+ }
+
+ const span& operator*() const { return m_span; }
+ const span* operator->() const { return &m_span; }
+
+ void operator ++ ()
+ {
+ ++m_span_idx;
+ init_span();
+ }
+
+ private:
+ void init_span()
+ {
+ const span_data& s = m_storage->span_by_index(m_span_idx);
+ m_span.x = s.x;
+ m_span.len = s.len;
+ m_span.covers = m_storage->covers_by_index(s.covers_id);
+ }
+
+ const scanline_storage_aa* m_storage;
+ unsigned m_span_idx;
+ span m_span;
+ };
+
+ friend class const_iterator;
+
+
+ //-----------------------------------------------------------
+ embedded_scanline(const scanline_storage_aa& storage) :
+ m_storage(&storage)
+ {
+ init(0);
+ }
+
+ //-----------------------------------------------------------
+ void reset(int, int) {}
+ unsigned num_spans() const { return m_scanline.num_spans; }
+ int y() const { return m_scanline.y; }
+ const_iterator begin() const { return const_iterator(*this); }
+
+ //-----------------------------------------------------------
+ void init(unsigned scanline_idx)
+ {
+ m_scanline_idx = scanline_idx;
+ m_scanline = m_storage->scanline_by_index(m_scanline_idx);
+ }
+
+ private:
+ const scanline_storage_aa* m_storage;
+ scanline_data m_scanline;
+ unsigned m_scanline_idx;
+ };
+
+
+ //---------------------------------------------------------------
+ scanline_storage_aa() :
+ m_covers(),
+ m_spans(256-2), // Block increment size
+ m_scanlines(),
+ m_min_x( 0x7FFFFFFF),
+ m_min_y( 0x7FFFFFFF),
+ m_max_x(-0x7FFFFFFF),
+ m_max_y(-0x7FFFFFFF),
+ m_cur_scanline(0)
+ {
+ m_fake_scanline.y = 0;
+ m_fake_scanline.num_spans = 0;
+ m_fake_scanline.start_span = 0;
+ m_fake_span.x = 0;
+ m_fake_span.len = 0;
+ m_fake_span.covers_id = 0;
+ }
+
+ // Renderer Interface
+ //---------------------------------------------------------------
+ void prepare()
+ {
+ m_covers.remove_all();
+ m_scanlines.remove_all();
+ m_spans.remove_all();
+ m_min_x = 0x7FFFFFFF;
+ m_min_y = 0x7FFFFFFF;
+ m_max_x = -0x7FFFFFFF;
+ m_max_y = -0x7FFFFFFF;
+ m_cur_scanline = 0;
+ }
+
+ //---------------------------------------------------------------
+ template<class Scanline> void render(const Scanline& sl)
+ {
+ scanline_data sl_this;
+
+ int y = sl.y();
+ if(y < m_min_y) m_min_y = y;
+ if(y > m_max_y) m_max_y = y;
+
+ sl_this.y = y;
+ sl_this.num_spans = sl.num_spans();
+ sl_this.start_span = m_spans.size();
+ typename Scanline::const_iterator span_iterator = sl.begin();
+
+ unsigned num_spans = sl_this.num_spans;
+ for(;;)
+ {
+ span_data sp;
+
+ sp.x = span_iterator->x;
+ sp.len = span_iterator->len;
+ int len = abs(int(sp.len));
+ sp.covers_id =
+ m_covers.add_cells(span_iterator->covers,
+ unsigned(len));
+ m_spans.add(sp);
+ int x1 = sp.x;
+ int x2 = sp.x + len - 1;
+ if(x1 < m_min_x) m_min_x = x1;
+ if(x2 > m_max_x) m_max_x = x2;
+ if(--num_spans == 0) break;
+ ++span_iterator;
+ }
+ m_scanlines.add(sl_this);
+ }
+
+
+ //---------------------------------------------------------------
+ // Iterate scanlines interface
+ int min_x() const { return m_min_x; }
+ int min_y() const { return m_min_y; }
+ int max_x() const { return m_max_x; }
+ int max_y() const { return m_max_y; }
+
+ //---------------------------------------------------------------
+ bool rewind_scanlines()
+ {
+ m_cur_scanline = 0;
+ return m_scanlines.size() > 0;
+ }
+
+
+ //---------------------------------------------------------------
+ template<class Scanline> bool sweep_scanline(Scanline& sl)
+ {
+ sl.reset_spans();
+ for(;;)
+ {
+ if(m_cur_scanline >= m_scanlines.size()) return false;
+ const scanline_data& sl_this = m_scanlines[m_cur_scanline];
+
+ unsigned num_spans = sl_this.num_spans;
+ unsigned span_idx = sl_this.start_span;
+ do
+ {
+ const span_data& sp = m_spans[span_idx++];
+ const T* covers = covers_by_index(sp.covers_id);
+ if(sp.len < 0)
+ {
+ sl.add_span(sp.x, unsigned(-sp.len), *covers);
+ }
+ else
+ {
+ sl.add_cells(sp.x, sp.len, covers);
+ }
+ }
+ while(--num_spans);
+ ++m_cur_scanline;
+ if(sl.num_spans())
+ {
+ sl.finalize(sl_this.y);
+ break;
+ }
+ }
+ return true;
+ }
+
+
+ //---------------------------------------------------------------
+ // Specialization for embedded_scanline
+ bool sweep_scanline(embedded_scanline& sl)
+ {
+ do
+ {
+ if(m_cur_scanline >= m_scanlines.size()) return false;
+ sl.init(m_cur_scanline);
+ ++m_cur_scanline;
+ }
+ while(sl.num_spans() == 0);
+ return true;
+ }
+
+ //---------------------------------------------------------------
+ unsigned byte_size() const
+ {
+ unsigned i;
+ unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
+
+ for(i = 0; i < m_scanlines.size(); ++i)
+ {
+ size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans
+
+ const scanline_data& sl_this = m_scanlines[i];
+
+ unsigned num_spans = sl_this.num_spans;
+ unsigned span_idx = sl_this.start_span;
+ do
+ {
+ const span_data& sp = m_spans[span_idx++];
+
+ size += sizeof(int32) * 2; // X, span_len
+ if(sp.len < 0)
+ {
+ size += sizeof(T); // cover
+ }
+ else
+ {
+ size += sizeof(T) * unsigned(sp.len); // covers
+ }
+ }
+ while(--num_spans);
+ }
+ return size;
+ }
+
+
+ //---------------------------------------------------------------
+ static void write_int32(int8u* dst, int32 val)
+ {
+ dst[0] = ((const int8u*)&val)[0];
+ dst[1] = ((const int8u*)&val)[1];
+ dst[2] = ((const int8u*)&val)[2];
+ dst[3] = ((const int8u*)&val)[3];
+ }
+
+
+ //---------------------------------------------------------------
+ void serialize(int8u* data) const
+ {
+ unsigned i;
+
+ write_int32(data, min_x()); // min_x
+ data += sizeof(int32);
+ write_int32(data, min_y()); // min_y
+ data += sizeof(int32);
+ write_int32(data, max_x()); // max_x
+ data += sizeof(int32);
+ write_int32(data, max_y()); // max_y
+ data += sizeof(int32);
+
+ for(i = 0; i < m_scanlines.size(); ++i)
+ {
+ const scanline_data& sl_this = m_scanlines[i];
+
+ int8u* size_ptr = data;
+ data += sizeof(int32); // Reserve space for scanline size in bytes
+
+ write_int32(data, sl_this.y); // Y
+ data += sizeof(int32);
+
+ write_int32(data, sl_this.num_spans); // num_spans
+ data += sizeof(int32);
+
+ unsigned num_spans = sl_this.num_spans;
+ unsigned span_idx = sl_this.start_span;
+ do
+ {
+ const span_data& sp = m_spans[span_idx++];
+ const T* covers = covers_by_index(sp.covers_id);
+
+ write_int32(data, sp.x); // X
+ data += sizeof(int32);
+
+ write_int32(data, sp.len); // span_len
+ data += sizeof(int32);
+
+ if(sp.len < 0)
+ {
+ memcpy(data, covers, sizeof(T));
+ data += sizeof(T);
+ }
+ else
+ {
+ memcpy(data, covers, unsigned(sp.len) * sizeof(T));
+ data += sizeof(T) * unsigned(sp.len);
+ }
+ }
+ while(--num_spans);
+ write_int32(size_ptr, int32(unsigned(data - size_ptr)));
+ }
+ }
+
+
+ //---------------------------------------------------------------
+ const scanline_data& scanline_by_index(unsigned i) const
+ {
+ return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
+ }
+
+ //---------------------------------------------------------------
+ const span_data& span_by_index(unsigned i) const
+ {
+ return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
+ }
+
+ //---------------------------------------------------------------
+ const T* covers_by_index(int i) const
+ {
+ return m_covers[i];
+ }
+
+ private:
+ scanline_cell_storage<T> m_covers;
+ pod_bvector<span_data, 10> m_spans;
+ pod_bvector<scanline_data, 8> m_scanlines;
+ span_data m_fake_span;
+ scanline_data m_fake_scanline;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+ unsigned m_cur_scanline;
+ };
+
+
+ typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8
+ typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16
+ typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32
+
+
+
+
+ //------------------------------------------serialized_scanlines_adaptor_aa
+ template<class T> class serialized_scanlines_adaptor_aa
+ {
+ public:
+ typedef T cover_type;
+
+ //---------------------------------------------------------------------
+ class embedded_scanline
+ {
+ public:
+ typedef T cover_type;
+
+ //-----------------------------------------------------------------
+ class const_iterator
+ {
+ public:
+ struct span
+ {
+ int32 x;
+ int32 len; // If negative, it's a solid span, "covers" is valid
+ const T* covers;
+ };
+
+ const_iterator() : m_ptr(0) {}
+ const_iterator(const embedded_scanline& sl) :
+ m_ptr(sl.m_ptr),
+ m_dx(sl.m_dx)
+ {
+ init_span();
+ }
+
+ const span& operator*() const { return m_span; }
+ const span* operator->() const { return &m_span; }
+
+ void operator ++ ()
+ {
+ if(m_span.len < 0)
+ {
+ m_ptr += sizeof(T);
+ }
+ else
+ {
+ m_ptr += m_span.len * sizeof(T);
+ }
+ init_span();
+ }
+
+ private:
+ int read_int32()
+ {
+ int32 val;
+ ((int8u*)&val)[0] = *m_ptr++;
+ ((int8u*)&val)[1] = *m_ptr++;
+ ((int8u*)&val)[2] = *m_ptr++;
+ ((int8u*)&val)[3] = *m_ptr++;
+ return val;
+ }
+
+ void init_span()
+ {
+ m_span.x = read_int32() + m_dx;
+ m_span.len = read_int32();
+ m_span.covers = m_ptr;
+ }
+
+ const int8u* m_ptr;
+ span m_span;
+ int m_dx;
+ };
+
+ friend class const_iterator;
+
+
+ //-----------------------------------------------------------------
+ embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
+
+ //-----------------------------------------------------------------
+ void reset(int, int) {}
+ unsigned num_spans() const { return m_num_spans; }
+ int y() const { return m_y; }
+ const_iterator begin() const { return const_iterator(*this); }
+
+
+ private:
+ //-----------------------------------------------------------------
+ int read_int32()
+ {
+ int32 val;
+ ((int8u*)&val)[0] = *m_ptr++;
+ ((int8u*)&val)[1] = *m_ptr++;
+ ((int8u*)&val)[2] = *m_ptr++;
+ ((int8u*)&val)[3] = *m_ptr++;
+ return val;
+ }
+
+ public:
+ //-----------------------------------------------------------------
+ void init(const int8u* ptr, int dx, int dy)
+ {
+ m_ptr = ptr;
+ m_y = read_int32() + dy;
+ m_num_spans = unsigned(read_int32());
+ m_dx = dx;
+ }
+
+ private:
+ const int8u* m_ptr;
+ int m_y;
+ unsigned m_num_spans;
+ int m_dx;
+ };
+
+
+
+ public:
+ //--------------------------------------------------------------------
+ serialized_scanlines_adaptor_aa() :
+ m_data(0),
+ m_end(0),
+ m_ptr(0),
+ m_dx(0),
+ m_dy(0),
+ m_min_x(0x7FFFFFFF),
+ m_min_y(0x7FFFFFFF),
+ m_max_x(-0x7FFFFFFF),
+ m_max_y(-0x7FFFFFFF)
+ {}
+
+ //--------------------------------------------------------------------
+ serialized_scanlines_adaptor_aa(const int8u* data, unsigned size,
+ double dx, double dy) :
+ m_data(data),
+ m_end(data + size),
+ m_ptr(data),
+ m_dx(iround(dx)),
+ m_dy(iround(dy)),
+ m_min_x(0x7FFFFFFF),
+ m_min_y(0x7FFFFFFF),
+ m_max_x(-0x7FFFFFFF),
+ m_max_y(-0x7FFFFFFF)
+ {}
+
+ //--------------------------------------------------------------------
+ void init(const int8u* data, unsigned size, double dx, double dy)
+ {
+ m_data = data;
+ m_end = data + size;
+ m_ptr = data;
+ m_dx = iround(dx);
+ m_dy = iround(dy);
+ m_min_x = 0x7FFFFFFF;
+ m_min_y = 0x7FFFFFFF;
+ m_max_x = -0x7FFFFFFF;
+ m_max_y = -0x7FFFFFFF;
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ int read_int32()
+ {
+ int32 val;
+ ((int8u*)&val)[0] = *m_ptr++;
+ ((int8u*)&val)[1] = *m_ptr++;
+ ((int8u*)&val)[2] = *m_ptr++;
+ ((int8u*)&val)[3] = *m_ptr++;
+ return val;
+ }
+
+ //--------------------------------------------------------------------
+ unsigned read_int32u()
+ {
+ int32u val;
+ ((int8u*)&val)[0] = *m_ptr++;
+ ((int8u*)&val)[1] = *m_ptr++;
+ ((int8u*)&val)[2] = *m_ptr++;
+ ((int8u*)&val)[3] = *m_ptr++;
+ return val;
+ }
+
+ public:
+ // Iterate scanlines interface
+ //--------------------------------------------------------------------
+ bool rewind_scanlines()
+ {
+ m_ptr = m_data;
+ if(m_ptr < m_end)
+ {
+ m_min_x = read_int32() + m_dx;
+ m_min_y = read_int32() + m_dy;
+ m_max_x = read_int32() + m_dx;
+ m_max_y = read_int32() + m_dy;
+ }
+ return m_ptr < m_end;
+ }
+
+ //--------------------------------------------------------------------
+ int min_x() const { return m_min_x; }
+ int min_y() const { return m_min_y; }
+ int max_x() const { return m_max_x; }
+ int max_y() const { return m_max_y; }
+
+ //--------------------------------------------------------------------
+ template<class Scanline> bool sweep_scanline(Scanline& sl)
+ {
+ sl.reset_spans();
+ for(;;)
+ {
+ if(m_ptr >= m_end) return false;
+
+ read_int32(); // Skip scanline size in bytes
+ int y = read_int32() + m_dy;
+ unsigned num_spans = read_int32();
+
+ do
+ {
+ int x = read_int32() + m_dx;
+ int len = read_int32();
+
+ if(len < 0)
+ {
+ sl.add_span(x, unsigned(-len), *m_ptr);
+ m_ptr += sizeof(T);
+ }
+ else
+ {
+ sl.add_cells(x, len, m_ptr);
+ m_ptr += len * sizeof(T);
+ }
+ }
+ while(--num_spans);
+
+ if(sl.num_spans())
+ {
+ sl.finalize(y);
+ break;
+ }
+ }
+ return true;
+ }
+
+
+ //--------------------------------------------------------------------
+ // Specialization for embedded_scanline
+ bool sweep_scanline(embedded_scanline& sl)
+ {
+ do
+ {
+ if(m_ptr >= m_end) return false;
+
+ unsigned byte_size = read_int32u();
+ sl.init(m_ptr, m_dx, m_dy);
+ m_ptr += byte_size - sizeof(int32);
+ }
+ while(sl.num_spans() == 0);
+ return true;
+ }
+
+ private:
+ const int8u* m_data;
+ const int8u* m_end;
+ const int8u* m_ptr;
+ int m_dx;
+ int m_dy;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+ };
+
+
+
+ typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8
+ typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16
+ typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_scanline_storage_bin.h b/plugins/Clist_ng/AGG/include/agg_scanline_storage_bin.h new file mode 100644 index 0000000000..bdbbfa47ec --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_scanline_storage_bin.h @@ -0,0 +1,595 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+
+#ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED
+#define AGG_SCANLINE_STORAGE_BIN_INCLUDED
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include "agg_array.h"
+
+
+namespace agg
+{
+
+ //-----------------------------------------------scanline_storage_bin
+ class scanline_storage_bin
+ {
+ public:
+ //---------------------------------------------------------------
+ struct span_data
+ {
+ int32 x;
+ int32 len;
+ };
+
+ //---------------------------------------------------------------
+ struct scanline_data
+ {
+ int y;
+ unsigned num_spans;
+ unsigned start_span;
+ };
+
+
+ //---------------------------------------------------------------
+ class embedded_scanline
+ {
+ public:
+
+ //-----------------------------------------------------------
+ class const_iterator
+ {
+ public:
+ const_iterator() : m_storage(0) {}
+ const_iterator(const embedded_scanline& sl) :
+ m_storage(sl.m_storage),
+ m_span_idx(sl.m_scanline.start_span)
+ {
+ m_span = m_storage->span_by_index(m_span_idx);
+ }
+
+ const span_data& operator*() const { return m_span; }
+ const span_data* operator->() const { return &m_span; }
+
+ void operator ++ ()
+ {
+ ++m_span_idx;
+ m_span = m_storage->span_by_index(m_span_idx);
+ }
+
+ private:
+ const scanline_storage_bin* m_storage;
+ unsigned m_span_idx;
+ span_data m_span;
+ };
+
+ friend class const_iterator;
+
+
+ //-----------------------------------------------------------
+ embedded_scanline(const scanline_storage_bin& storage) :
+ m_storage(&storage)
+ {
+ setup(0);
+ }
+
+ //-----------------------------------------------------------
+ void reset(int, int) {}
+ unsigned num_spans() const { return m_scanline.num_spans; }
+ int y() const { return m_scanline.y; }
+ const_iterator begin() const { return const_iterator(*this); }
+
+ //-----------------------------------------------------------
+ void setup(unsigned scanline_idx)
+ {
+ m_scanline_idx = scanline_idx;
+ m_scanline = m_storage->scanline_by_index(m_scanline_idx);
+ }
+
+ private:
+ const scanline_storage_bin* m_storage;
+ scanline_data m_scanline;
+ unsigned m_scanline_idx;
+ };
+
+
+ //---------------------------------------------------------------
+ scanline_storage_bin() :
+ m_spans(256-2), // Block increment size
+ m_scanlines(),
+ m_min_x( 0x7FFFFFFF),
+ m_min_y( 0x7FFFFFFF),
+ m_max_x(-0x7FFFFFFF),
+ m_max_y(-0x7FFFFFFF),
+ m_cur_scanline(0)
+ {
+ m_fake_scanline.y = 0;
+ m_fake_scanline.num_spans = 0;
+ m_fake_scanline.start_span = 0;
+ m_fake_span.x = 0;
+ m_fake_span.len = 0;
+ }
+
+ // Renderer Interface
+ //---------------------------------------------------------------
+ void prepare()
+ {
+ m_scanlines.remove_all();
+ m_spans.remove_all();
+ m_min_x = 0x7FFFFFFF;
+ m_min_y = 0x7FFFFFFF;
+ m_max_x = -0x7FFFFFFF;
+ m_max_y = -0x7FFFFFFF;
+ m_cur_scanline = 0;
+ }
+
+ //---------------------------------------------------------------
+ template<class Scanline> void render(const Scanline& sl)
+ {
+ scanline_data sl_this;
+
+ int y = sl.y();
+ if(y < m_min_y) m_min_y = y;
+ if(y > m_max_y) m_max_y = y;
+
+ sl_this.y = y;
+ sl_this.num_spans = sl.num_spans();
+ sl_this.start_span = m_spans.size();
+ typename Scanline::const_iterator span_iterator = sl.begin();
+
+ unsigned num_spans = sl_this.num_spans;
+ for(;;)
+ {
+ span_data sp;
+ sp.x = span_iterator->x;
+ sp.len = (int32)abs((int)(span_iterator->len));
+ m_spans.add(sp);
+ int x1 = sp.x;
+ int x2 = sp.x + sp.len - 1;
+ if(x1 < m_min_x) m_min_x = x1;
+ if(x2 > m_max_x) m_max_x = x2;
+ if(--num_spans == 0) break;
+ ++span_iterator;
+ }
+ m_scanlines.add(sl_this);
+ }
+
+
+ //---------------------------------------------------------------
+ // Iterate scanlines interface
+ int min_x() const { return m_min_x; }
+ int min_y() const { return m_min_y; }
+ int max_x() const { return m_max_x; }
+ int max_y() const { return m_max_y; }
+
+ //---------------------------------------------------------------
+ bool rewind_scanlines()
+ {
+ m_cur_scanline = 0;
+ return m_scanlines.size() > 0;
+ }
+
+
+ //---------------------------------------------------------------
+ template<class Scanline> bool sweep_scanline(Scanline& sl)
+ {
+ sl.reset_spans();
+ for(;;)
+ {
+ if(m_cur_scanline >= m_scanlines.size()) return false;
+ const scanline_data& sl_this = m_scanlines[m_cur_scanline];
+
+ unsigned num_spans = sl_this.num_spans;
+ unsigned span_idx = sl_this.start_span;
+ do
+ {
+ const span_data& sp = m_spans[span_idx++];
+ sl.add_span(sp.x, sp.len, cover_full);
+ }
+ while(--num_spans);
+
+ ++m_cur_scanline;
+ if(sl.num_spans())
+ {
+ sl.finalize(sl_this.y);
+ break;
+ }
+ }
+ return true;
+ }
+
+
+ //---------------------------------------------------------------
+ // Specialization for embedded_scanline
+ bool sweep_scanline(embedded_scanline& sl)
+ {
+ do
+ {
+ if(m_cur_scanline >= m_scanlines.size()) return false;
+ sl.setup(m_cur_scanline);
+ ++m_cur_scanline;
+ }
+ while(sl.num_spans() == 0);
+ return true;
+ }
+
+
+ //---------------------------------------------------------------
+ unsigned byte_size() const
+ {
+ unsigned i;
+ unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y
+
+ for(i = 0; i < m_scanlines.size(); ++i)
+ {
+ size += sizeof(int32) * 2 + // Y, num_spans
+ unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len
+ }
+ return size;
+ }
+
+
+ //---------------------------------------------------------------
+ static void write_int32(int8u* dst, int32 val)
+ {
+ dst[0] = ((const int8u*)&val)[0];
+ dst[1] = ((const int8u*)&val)[1];
+ dst[2] = ((const int8u*)&val)[2];
+ dst[3] = ((const int8u*)&val)[3];
+ }
+
+
+ //---------------------------------------------------------------
+ void serialize(int8u* data) const
+ {
+ unsigned i;
+
+ write_int32(data, min_x()); // min_x
+ data += sizeof(int32);
+ write_int32(data, min_y()); // min_y
+ data += sizeof(int32);
+ write_int32(data, max_x()); // max_x
+ data += sizeof(int32);
+ write_int32(data, max_y()); // max_y
+ data += sizeof(int32);
+
+ for(i = 0; i < m_scanlines.size(); ++i)
+ {
+ const scanline_data& sl_this = m_scanlines[i];
+
+ write_int32(data, sl_this.y); // Y
+ data += sizeof(int32);
+
+ write_int32(data, sl_this.num_spans); // num_spans
+ data += sizeof(int32);
+
+ unsigned num_spans = sl_this.num_spans;
+ unsigned span_idx = sl_this.start_span;
+ do
+ {
+ const span_data& sp = m_spans[span_idx++];
+
+ write_int32(data, sp.x); // X
+ data += sizeof(int32);
+
+ write_int32(data, sp.len); // len
+ data += sizeof(int32);
+ }
+ while(--num_spans);
+ }
+ }
+
+
+ //---------------------------------------------------------------
+ const scanline_data& scanline_by_index(unsigned i) const
+ {
+ return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
+ }
+
+ //---------------------------------------------------------------
+ const span_data& span_by_index(unsigned i) const
+ {
+ return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
+ }
+
+
+ private:
+ pod_bvector<span_data, 10> m_spans;
+ pod_bvector<scanline_data, 8> m_scanlines;
+ span_data m_fake_span;
+ scanline_data m_fake_scanline;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+ unsigned m_cur_scanline;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //---------------------------------------serialized_scanlines_adaptor_bin
+ class serialized_scanlines_adaptor_bin
+ {
+ public:
+ typedef bool cover_type;
+
+ //--------------------------------------------------------------------
+ class embedded_scanline
+ {
+ public:
+
+ //----------------------------------------------------------------
+ class const_iterator
+ {
+ public:
+ struct span
+ {
+ int32 x;
+ int32 len;
+ };
+
+ const_iterator() : m_ptr(0) {}
+ const_iterator(const embedded_scanline& sl) :
+ m_ptr(sl.m_ptr),
+ m_dx(sl.m_dx)
+ {
+ m_span.x = read_int32() + m_dx;
+ m_span.len = read_int32();
+ }
+
+ const span& operator*() const { return m_span; }
+ const span* operator->() const { return &m_span; }
+
+ void operator ++ ()
+ {
+ m_span.x = read_int32() + m_dx;
+ m_span.len = read_int32();
+ }
+
+ private:
+ int read_int32()
+ {
+ int32 val;
+ ((int8u*)&val)[0] = *m_ptr++;
+ ((int8u*)&val)[1] = *m_ptr++;
+ ((int8u*)&val)[2] = *m_ptr++;
+ ((int8u*)&val)[3] = *m_ptr++;
+ return val;
+ }
+
+ const int8u* m_ptr;
+ span m_span;
+ int m_dx;
+ };
+
+ friend class const_iterator;
+
+
+ //----------------------------------------------------------------
+ embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
+
+ //----------------------------------------------------------------
+ void reset(int, int) {}
+ unsigned num_spans() const { return m_num_spans; }
+ int y() const { return m_y; }
+ const_iterator begin() const { return const_iterator(*this); }
+
+
+ private:
+ //----------------------------------------------------------------
+ int read_int32()
+ {
+ int32 val;
+ ((int8u*)&val)[0] = *m_ptr++;
+ ((int8u*)&val)[1] = *m_ptr++;
+ ((int8u*)&val)[2] = *m_ptr++;
+ ((int8u*)&val)[3] = *m_ptr++;
+ return val;
+ }
+
+ public:
+ //----------------------------------------------------------------
+ void init(const int8u* ptr, int dx, int dy)
+ {
+ m_ptr = ptr;
+ m_y = read_int32() + dy;
+ m_num_spans = unsigned(read_int32());
+ m_dx = dx;
+ }
+
+ private:
+ const int8u* m_ptr;
+ int m_y;
+ unsigned m_num_spans;
+ int m_dx;
+ };
+
+
+
+ public:
+ //--------------------------------------------------------------------
+ serialized_scanlines_adaptor_bin() :
+ m_data(0),
+ m_end(0),
+ m_ptr(0),
+ m_dx(0),
+ m_dy(0),
+ m_min_x(0x7FFFFFFF),
+ m_min_y(0x7FFFFFFF),
+ m_max_x(-0x7FFFFFFF),
+ m_max_y(-0x7FFFFFFF)
+ {}
+
+ //--------------------------------------------------------------------
+ serialized_scanlines_adaptor_bin(const int8u* data, unsigned size,
+ double dx, double dy) :
+ m_data(data),
+ m_end(data + size),
+ m_ptr(data),
+ m_dx(iround(dx)),
+ m_dy(iround(dy)),
+ m_min_x(0x7FFFFFFF),
+ m_min_y(0x7FFFFFFF),
+ m_max_x(-0x7FFFFFFF),
+ m_max_y(-0x7FFFFFFF)
+ {}
+
+ //--------------------------------------------------------------------
+ void init(const int8u* data, unsigned size, double dx, double dy)
+ {
+ m_data = data;
+ m_end = data + size;
+ m_ptr = data;
+ m_dx = iround(dx);
+ m_dy = iround(dy);
+ m_min_x = 0x7FFFFFFF;
+ m_min_y = 0x7FFFFFFF;
+ m_max_x = -0x7FFFFFFF;
+ m_max_y = -0x7FFFFFFF;
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ int read_int32()
+ {
+ int32 val;
+ ((int8u*)&val)[0] = *m_ptr++;
+ ((int8u*)&val)[1] = *m_ptr++;
+ ((int8u*)&val)[2] = *m_ptr++;
+ ((int8u*)&val)[3] = *m_ptr++;
+ return val;
+ }
+
+ public:
+ // Iterate scanlines interface
+ //--------------------------------------------------------------------
+ bool rewind_scanlines()
+ {
+ m_ptr = m_data;
+ if(m_ptr < m_end)
+ {
+ m_min_x = read_int32() + m_dx;
+ m_min_y = read_int32() + m_dy;
+ m_max_x = read_int32() + m_dx;
+ m_max_y = read_int32() + m_dy;
+ }
+ return m_ptr < m_end;
+ }
+
+ //--------------------------------------------------------------------
+ int min_x() const { return m_min_x; }
+ int min_y() const { return m_min_y; }
+ int max_x() const { return m_max_x; }
+ int max_y() const { return m_max_y; }
+
+ //--------------------------------------------------------------------
+ template<class Scanline> bool sweep_scanline(Scanline& sl)
+ {
+ sl.reset_spans();
+ for(;;)
+ {
+ if(m_ptr >= m_end) return false;
+
+ int y = read_int32() + m_dy;
+ unsigned num_spans = read_int32();
+
+ do
+ {
+ int x = read_int32() + m_dx;
+ int len = read_int32();
+
+ if(len < 0) len = -len;
+ sl.add_span(x, unsigned(len), cover_full);
+ }
+ while(--num_spans);
+
+ if(sl.num_spans())
+ {
+ sl.finalize(y);
+ break;
+ }
+ }
+ return true;
+ }
+
+
+ //--------------------------------------------------------------------
+ // Specialization for embedded_scanline
+ bool sweep_scanline(embedded_scanline& sl)
+ {
+ do
+ {
+ if(m_ptr >= m_end) return false;
+
+ sl.init(m_ptr, m_dx, m_dy);
+
+ // Jump to the next scanline
+ //--------------------------
+ read_int32(); // Y
+ int num_spans = read_int32(); // num_spans
+ m_ptr += num_spans * sizeof(int32) * 2;
+ }
+ while(sl.num_spans() == 0);
+ return true;
+ }
+
+ private:
+ const int8u* m_data;
+ const int8u* m_end;
+ const int8u* m_ptr;
+ int m_dx;
+ int m_dy;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+ };
+
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_scanline_u.h b/plugins/Clist_ng/AGG/include/agg_scanline_u.h new file mode 100644 index 0000000000..c3443b5f22 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_scanline_u.h @@ -0,0 +1,508 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SCANLINE_U_INCLUDED
+#define AGG_SCANLINE_U_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+ //=============================================================scanline_u8
+ //
+ // Unpacked scanline container class
+ //
+ // This class is used to transfer data from a scanline rasterizer
+ // to the rendering buffer. It's organized very simple. The class stores
+ // information of horizontal spans to render it into a pixel-map buffer.
+ // Each span has staring X, length, and an array of bytes that determine the
+ // cover-values for each pixel.
+ // Before using this class you should know the minimal and maximal pixel
+ // coordinates of your scanline. The protocol of using is:
+ // 1. reset(min_x, max_x)
+ // 2. add_cell() / add_span() - accumulate scanline.
+ // When forming one scanline the next X coordinate must be always greater
+ // than the last stored one, i.e. it works only with ordered coordinates.
+ // 3. Call finalize(y) and render the scanline.
+ // 3. Call reset_spans() to prepare for the new scanline.
+ //
+ // 4. Rendering:
+ //
+ // Scanline provides an iterator class that allows you to extract
+ // the spans and the cover values for each pixel. Be aware that clipping
+ // has not been done yet, so you should perform it yourself.
+ // Use scanline_u8::iterator to render spans:
+ //-------------------------------------------------------------------------
+ //
+ // int y = sl.y(); // Y-coordinate of the scanline
+ //
+ // ************************************
+ // ...Perform vertical clipping here...
+ // ************************************
+ //
+ // scanline_u8::const_iterator span = sl.begin();
+ //
+ // unsigned char* row = m_rbuf->row(y); // The the address of the beginning
+ // // of the current row
+ //
+ // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
+ // // num_spans is always greater than 0.
+ //
+ // do
+ // {
+ // const scanline_u8::cover_type* covers =
+ // span->covers; // The array of the cover values
+ //
+ // int num_pix = span->len; // Number of pixels of the span.
+ // // Always greater than 0, still it's
+ // // better to use "int" instead of
+ // // "unsigned" because it's more
+ // // convenient for clipping
+ // int x = span->x;
+ //
+ // **************************************
+ // ...Perform horizontal clipping here...
+ // ...you have x, covers, and pix_count..
+ // **************************************
+ //
+ // unsigned char* dst = row + x; // Calculate the start address of the row.
+ // // In this case we assume a simple
+ // // grayscale image 1-byte per pixel.
+ // do
+ // {
+ // *dst++ = *covers++; // Hypotetical rendering.
+ // }
+ // while(--num_pix);
+ //
+ // ++span;
+ // }
+ // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
+ //------------------------------------------------------------------------
+ //
+ // The question is: why should we accumulate the whole scanline when we
+ // could render just separate spans when they're ready?
+ // That's because using the scanline is generally faster. When is consists
+ // of more than one span the conditions for the processor cash system
+ // are better, because switching between two different areas of memory
+ // (that can be very large) occurs less frequently.
+ //------------------------------------------------------------------------
+ class scanline_u8
+ {
+ public:
+ typedef scanline_u8 self_type;
+ typedef int8u cover_type;
+ typedef int16 coord_type;
+
+ //--------------------------------------------------------------------
+ struct span
+ {
+ coord_type x;
+ coord_type len;
+ cover_type* covers;
+ };
+
+ typedef span* iterator;
+ typedef const span* const_iterator;
+
+ //--------------------------------------------------------------------
+ scanline_u8() :
+ m_min_x(0),
+ m_last_x(0x7FFFFFF0),
+ m_cur_span(0)
+ {}
+
+ //--------------------------------------------------------------------
+ void reset(int min_x, int max_x)
+ {
+ unsigned max_len = max_x - min_x + 2;
+ if(max_len > m_spans.size())
+ {
+ m_spans.resize(max_len);
+ m_covers.resize(max_len);
+ }
+ m_last_x = 0x7FFFFFF0;
+ m_min_x = min_x;
+ m_cur_span = &m_spans[0];
+ }
+
+ //--------------------------------------------------------------------
+ void add_cell(int x, unsigned cover)
+ {
+ x -= m_min_x;
+ m_covers[x] = (cover_type)cover;
+ if(x == m_last_x+1)
+ {
+ m_cur_span->len++;
+ }
+ else
+ {
+ m_cur_span++;
+ m_cur_span->x = (coord_type)(x + m_min_x);
+ m_cur_span->len = 1;
+ m_cur_span->covers = &m_covers[x];
+ }
+ m_last_x = x;
+ }
+
+ //--------------------------------------------------------------------
+ void add_cells(int x, unsigned len, const cover_type* covers)
+ {
+ x -= m_min_x;
+ memcpy(&m_covers[x], covers, len * sizeof(cover_type));
+ if(x == m_last_x+1)
+ {
+ m_cur_span->len += (coord_type)len;
+ }
+ else
+ {
+ m_cur_span++;
+ m_cur_span->x = (coord_type)(x + m_min_x);
+ m_cur_span->len = (coord_type)len;
+ m_cur_span->covers = &m_covers[x];
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void add_span(int x, unsigned len, unsigned cover)
+ {
+ x -= m_min_x;
+ memset(&m_covers[x], cover, len);
+ if(x == m_last_x+1)
+ {
+ m_cur_span->len += (coord_type)len;
+ }
+ else
+ {
+ m_cur_span++;
+ m_cur_span->x = (coord_type)(x + m_min_x);
+ m_cur_span->len = (coord_type)len;
+ m_cur_span->covers = &m_covers[x];
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void finalize(int y)
+ {
+ m_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_spans()
+ {
+ m_last_x = 0x7FFFFFF0;
+ m_cur_span = &m_spans[0];
+ }
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y; }
+ unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
+ const_iterator begin() const { return &m_spans[1]; }
+ iterator begin() { return &m_spans[1]; }
+
+ private:
+ scanline_u8(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ private:
+ int m_min_x;
+ int m_last_x;
+ int m_y;
+ pod_array<cover_type> m_covers;
+ pod_array<span> m_spans;
+ span* m_cur_span;
+ };
+
+
+
+
+ //==========================================================scanline_u8_am
+ //
+ // The scanline container with alpha-masking
+ //
+ //------------------------------------------------------------------------
+ template<class AlphaMask>
+ class scanline_u8_am : public scanline_u8
+ {
+ public:
+ typedef scanline_u8 base_type;
+ typedef AlphaMask alpha_mask_type;
+ typedef base_type::cover_type cover_type;
+ typedef base_type::coord_type coord_type;
+
+ scanline_u8_am() : base_type(), m_alpha_mask(0) {}
+ scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
+
+ //--------------------------------------------------------------------
+ void finalize(int span_y)
+ {
+ base_type::finalize(span_y);
+ if(m_alpha_mask)
+ {
+ typename base_type::iterator span = base_type::begin();
+ unsigned count = base_type::num_spans();
+ do
+ {
+ m_alpha_mask->combine_hspan(span->x,
+ base_type::y(),
+ span->covers,
+ span->len);
+ ++span;
+ }
+ while(--count);
+ }
+ }
+
+ private:
+ const AlphaMask* m_alpha_mask;
+ };
+
+
+
+
+ //===========================================================scanline32_u8
+ class scanline32_u8
+ {
+ public:
+ typedef scanline32_u8 self_type;
+ typedef int8u cover_type;
+ typedef int32 coord_type;
+
+ //--------------------------------------------------------------------
+ struct span
+ {
+ span() {}
+ span(coord_type x_, coord_type len_, cover_type* covers_) :
+ x(x_), len(len_), covers(covers_) {}
+
+ coord_type x;
+ coord_type len;
+ cover_type* covers;
+ };
+
+ typedef pod_bvector<span, 4> span_array_type;
+
+ //--------------------------------------------------------------------
+ class const_iterator
+ {
+ public:
+ const_iterator(const span_array_type& spans) :
+ m_spans(spans),
+ m_span_idx(0)
+ {}
+
+ const span& operator*() const { return m_spans[m_span_idx]; }
+ const span* operator->() const { return &m_spans[m_span_idx]; }
+
+ void operator ++ () { ++m_span_idx; }
+
+ private:
+ const span_array_type& m_spans;
+ unsigned m_span_idx;
+ };
+
+ //--------------------------------------------------------------------
+ class iterator
+ {
+ public:
+ iterator(span_array_type& spans) :
+ m_spans(spans),
+ m_span_idx(0)
+ {}
+
+ span& operator*() { return m_spans[m_span_idx]; }
+ span* operator->() { return &m_spans[m_span_idx]; }
+
+ void operator ++ () { ++m_span_idx; }
+
+ private:
+ span_array_type& m_spans;
+ unsigned m_span_idx;
+ };
+
+
+
+ //--------------------------------------------------------------------
+ scanline32_u8() :
+ m_min_x(0),
+ m_last_x(0x7FFFFFF0),
+ m_covers()
+ {}
+
+ //--------------------------------------------------------------------
+ void reset(int min_x, int max_x)
+ {
+ unsigned max_len = max_x - min_x + 2;
+ if(max_len > m_covers.size())
+ {
+ m_covers.resize(max_len);
+ }
+ m_last_x = 0x7FFFFFF0;
+ m_min_x = min_x;
+ m_spans.remove_all();
+ }
+
+ //--------------------------------------------------------------------
+ void add_cell(int x, unsigned cover)
+ {
+ x -= m_min_x;
+ m_covers[x] = cover_type(cover);
+ if(x == m_last_x+1)
+ {
+ m_spans.last().len++;
+ }
+ else
+ {
+ m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
+ }
+ m_last_x = x;
+ }
+
+ //--------------------------------------------------------------------
+ void add_cells(int x, unsigned len, const cover_type* covers)
+ {
+ x -= m_min_x;
+ memcpy(&m_covers[x], covers, len * sizeof(cover_type));
+ if(x == m_last_x+1)
+ {
+ m_spans.last().len += coord_type(len);
+ }
+ else
+ {
+ m_spans.add(span(coord_type(x + m_min_x),
+ coord_type(len),
+ &m_covers[x]));
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void add_span(int x, unsigned len, unsigned cover)
+ {
+ x -= m_min_x;
+ memset(&m_covers[x], cover, len);
+ if(x == m_last_x+1)
+ {
+ m_spans.last().len += coord_type(len);
+ }
+ else
+ {
+ m_spans.add(span(coord_type(x + m_min_x),
+ coord_type(len),
+ &m_covers[x]));
+ }
+ m_last_x = x + len - 1;
+ }
+
+ //--------------------------------------------------------------------
+ void finalize(int y)
+ {
+ m_y = y;
+ }
+
+ //--------------------------------------------------------------------
+ void reset_spans()
+ {
+ m_last_x = 0x7FFFFFF0;
+ m_spans.remove_all();
+ }
+
+ //--------------------------------------------------------------------
+ int y() const { return m_y; }
+ unsigned num_spans() const { return m_spans.size(); }
+ const_iterator begin() const { return const_iterator(m_spans); }
+ iterator begin() { return iterator(m_spans); }
+
+ private:
+ scanline32_u8(const self_type&);
+ const self_type& operator = (const self_type&);
+
+ private:
+ int m_min_x;
+ int m_last_x;
+ int m_y;
+ pod_array<cover_type> m_covers;
+ span_array_type m_spans;
+ };
+
+
+
+
+ //========================================================scanline32_u8_am
+ //
+ // The scanline container with alpha-masking
+ //
+ //------------------------------------------------------------------------
+ template<class AlphaMask>
+ class scanline32_u8_am : public scanline32_u8
+ {
+ public:
+ typedef scanline32_u8 base_type;
+ typedef AlphaMask alpha_mask_type;
+ typedef base_type::cover_type cover_type;
+ typedef base_type::coord_type coord_type;
+
+
+ scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
+ scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
+
+ //--------------------------------------------------------------------
+ void finalize(int span_y)
+ {
+ base_type::finalize(span_y);
+ if(m_alpha_mask)
+ {
+ typename base_type::iterator span = base_type::begin();
+ unsigned count = base_type::num_spans();
+ do
+ {
+ m_alpha_mask->combine_hspan(span->x,
+ base_type::y(),
+ span->covers,
+ span->len);
+ ++span;
+ }
+ while(--count);
+ }
+ }
+
+ private:
+ const AlphaMask* m_alpha_mask;
+ };
+
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_shorten_path.h b/plugins/Clist_ng/AGG/include/agg_shorten_path.h new file mode 100644 index 0000000000..c914c42b74 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_shorten_path.h @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SHORTEN_PATH_INCLUDED
+#define AGG_SHORTEN_PATH_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vertex_sequence.h"
+
+namespace agg
+{
+
+ //===========================================================shorten_path
+ template<class VertexSequence>
+ void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
+ {
+ typedef typename VertexSequence::value_type vertex_type;
+
+ if(s > 0.0 && vs.size() > 1)
+ {
+ double d;
+ int n = int(vs.size() - 2);
+ while(n)
+ {
+ d = vs[n].dist;
+ if(d > s) break;
+ vs.remove_last();
+ s -= d;
+ --n;
+ }
+ if(vs.size() < 2)
+ {
+ vs.remove_all();
+ }
+ else
+ {
+ n = vs.size() - 1;
+ vertex_type& prev = vs[n-1];
+ vertex_type& last = vs[n];
+ d = (prev.dist - s) / prev.dist;
+ double x = prev.x + (last.x - prev.x) * d;
+ double y = prev.y + (last.y - prev.y) * d;
+ last.x = x;
+ last.y = y;
+ if(!prev(last)) vs.remove_last();
+ vs.close(closed != 0);
+ }
+ }
+ }
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_simul_eq.h b/plugins/Clist_ng/AGG/include/agg_simul_eq.h new file mode 100644 index 0000000000..c45f5ca338 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_simul_eq.h @@ -0,0 +1,153 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SIMUL_EQ_INCLUDED
+#define AGG_SIMUL_EQ_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //=============================================================swap_arrays
+ template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
+ {
+ unsigned i;
+ for(i = 0; i < n; i++)
+ {
+ T tmp = *a1;
+ *a1++ = *a2;
+ *a2++ = tmp;
+ }
+ }
+
+
+ //============================================================matrix_pivot
+ template<unsigned Rows, unsigned Cols>
+ struct matrix_pivot
+ {
+ static int pivot(double m[Rows][Cols], unsigned row)
+ {
+ int k = int(row);
+ double max_val, tmp;
+
+ max_val = -1.0;
+ unsigned i;
+ for(i = row; i < Rows; i++)
+ {
+ if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0)
+ {
+ max_val = tmp;
+ k = i;
+ }
+ }
+
+ if(m[k][row] == 0.0)
+ {
+ return -1;
+ }
+
+ if(k != int(row))
+ {
+ swap_arrays(m[k], m[row], Cols);
+ return k;
+ }
+ return 0;
+ }
+ };
+
+
+
+ //===============================================================simul_eq
+ template<unsigned Size, unsigned RightCols>
+ struct simul_eq
+ {
+ static bool solve(const double left[Size][Size],
+ const double right[Size][RightCols],
+ double result[Size][RightCols])
+ {
+ unsigned i, j, k;
+ double a1;
+
+ double tmp[Size][Size + RightCols];
+
+ for(i = 0; i < Size; i++)
+ {
+ for(j = 0; j < Size; j++)
+ {
+ tmp[i][j] = left[i][j];
+ }
+ for(j = 0; j < RightCols; j++)
+ {
+ tmp[i][Size + j] = right[i][j];
+ }
+ }
+
+ for(k = 0; k < Size; k++)
+ {
+ if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0)
+ {
+ return false; // Singularity....
+ }
+
+ a1 = tmp[k][k];
+
+ for(j = k; j < Size + RightCols; j++)
+ {
+ tmp[k][j] /= a1;
+ }
+
+ for(i = k + 1; i < Size; i++)
+ {
+ a1 = tmp[i][k];
+ for (j = k; j < Size + RightCols; j++)
+ {
+ tmp[i][j] -= a1 * tmp[k][j];
+ }
+ }
+ }
+
+
+ for(k = 0; k < RightCols; k++)
+ {
+ int m;
+ for(m = int(Size - 1); m >= 0; m--)
+ {
+ result[m][k] = tmp[m][Size + k];
+ for(j = m + 1; j < Size; j++)
+ {
+ result[m][k] -= tmp[m][j] * result[j][k];
+ }
+ }
+ }
+ return true;
+ }
+
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_allocator.h b/plugins/Clist_ng/AGG/include/agg_span_allocator.h new file mode 100644 index 0000000000..6a9c3835a2 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_allocator.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_ALLOCATOR_INCLUDED
+#define AGG_SPAN_ALLOCATOR_INCLUDED
+
+#include "agg_array.h"
+
+namespace agg
+{
+ //----------------------------------------------------------span_allocator
+ template<class ColorT> class span_allocator
+ {
+ public:
+ typedef ColorT color_type;
+
+ //--------------------------------------------------------------------
+ AGG_INLINE color_type* allocate(unsigned span_len)
+ {
+ if(span_len > m_span.size())
+ {
+ // To reduce the number of reallocs we align the
+ // span_len to 256 color elements.
+ // Well, I just like this number and it looks reasonable.
+ //-----------------------
+ m_span.resize(((span_len + 255) >> 8) << 8);
+ }
+ return &m_span[0];
+ }
+
+ AGG_INLINE color_type* span() { return &m_span[0]; }
+ AGG_INLINE unsigned max_span_len() const { return m_span.size(); }
+
+ private:
+ pod_array<color_type> m_span;
+ };
+}
+
+
+#endif
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_converter.h b/plugins/Clist_ng/AGG/include/agg_span_converter.h new file mode 100644 index 0000000000..99f1a2398a --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_converter.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_CONVERTER_INCLUDED
+#define AGG_SPAN_CONVERTER_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //----------------------------------------------------------span_converter
+ template<class SpanGenerator, class SpanConverter> class span_converter
+ {
+ public:
+ typedef typename SpanGenerator::color_type color_type;
+
+ span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) :
+ m_span_gen(&span_gen), m_span_cnv(&span_cnv) {}
+
+ void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; }
+ void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; }
+
+ //--------------------------------------------------------------------
+ void prepare()
+ {
+ m_span_gen->prepare();
+ m_span_cnv->prepare();
+ }
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ m_span_gen->generate(span, x, y, len);
+ m_span_cnv->generate(span, x, y, len);
+ }
+
+ private:
+ SpanGenerator* m_span_gen;
+ SpanConverter* m_span_cnv;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_gouraud.h b/plugins/Clist_ng/AGG/include/agg_span_gouraud.h new file mode 100644 index 0000000000..9af2ab0011 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_gouraud.h @@ -0,0 +1,181 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_GOURAUD_INCLUDED
+#define AGG_SPAN_GOURAUD_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_math.h"
+
+namespace agg
+{
+
+ //============================================================span_gouraud
+ template<class ColorT> class span_gouraud
+ {
+ public:
+ typedef ColorT color_type;
+
+ struct coord_type
+ {
+ double x;
+ double y;
+ color_type color;
+ };
+
+ //--------------------------------------------------------------------
+ span_gouraud() :
+ m_vertex(0)
+ {
+ m_cmd[0] = path_cmd_stop;
+ }
+
+ //--------------------------------------------------------------------
+ span_gouraud(const color_type& c1,
+ const color_type& c2,
+ const color_type& c3,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double d) :
+ m_vertex(0)
+ {
+ colors(c1, c2, c3);
+ triangle(x1, y1, x2, y2, x3, y3, d);
+ }
+
+ //--------------------------------------------------------------------
+ void colors(ColorT c1, ColorT c2, ColorT c3)
+ {
+ m_coord[0].color = c1;
+ m_coord[1].color = c2;
+ m_coord[2].color = c3;
+ }
+
+ //--------------------------------------------------------------------
+ // Sets the triangle and dilates it if needed.
+ // The trick here is to calculate beveled joins in the vertices of the
+ // triangle and render it as a 6-vertex polygon.
+ // It's necessary to achieve numerical stability.
+ // However, the coordinates to interpolate colors are calculated
+ // as miter joins (calc_intersection).
+ void triangle(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double d)
+ {
+ m_coord[0].x = m_x[0] = x1;
+ m_coord[0].y = m_y[0] = y1;
+ m_coord[1].x = m_x[1] = x2;
+ m_coord[1].y = m_y[1] = y2;
+ m_coord[2].x = m_x[2] = x3;
+ m_coord[2].y = m_y[2] = y3;
+ m_cmd[0] = path_cmd_move_to;
+ m_cmd[1] = path_cmd_line_to;
+ m_cmd[2] = path_cmd_line_to;
+ m_cmd[3] = path_cmd_stop;
+
+ if(d != 0.0)
+ {
+ dilate_triangle(m_coord[0].x, m_coord[0].y,
+ m_coord[1].x, m_coord[1].y,
+ m_coord[2].x, m_coord[2].y,
+ m_x, m_y, d);
+
+ calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5],
+ m_x[0], m_y[0], m_x[1], m_y[1],
+ &m_coord[0].x, &m_coord[0].y);
+
+ calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1],
+ m_x[2], m_y[2], m_x[3], m_y[3],
+ &m_coord[1].x, &m_coord[1].y);
+
+ calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3],
+ m_x[4], m_y[4], m_x[5], m_y[5],
+ &m_coord[2].x, &m_coord[2].y);
+ m_cmd[3] = path_cmd_line_to;
+ m_cmd[4] = path_cmd_line_to;
+ m_cmd[5] = path_cmd_line_to;
+ m_cmd[6] = path_cmd_stop;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ // Vertex Source Interface to feed the coordinates to the rasterizer
+ void rewind(unsigned)
+ {
+ m_vertex = 0;
+ }
+
+ //--------------------------------------------------------------------
+ unsigned vertex(double* x, double* y)
+ {
+ *x = m_x[m_vertex];
+ *y = m_y[m_vertex];
+ return m_cmd[m_vertex++];
+ }
+
+ protected:
+ //--------------------------------------------------------------------
+ void arrange_vertices(coord_type* coord) const
+ {
+ coord[0] = m_coord[0];
+ coord[1] = m_coord[1];
+ coord[2] = m_coord[2];
+
+ if(m_coord[0].y > m_coord[2].y)
+ {
+ coord[0] = m_coord[2];
+ coord[2] = m_coord[0];
+ }
+
+ coord_type tmp;
+ if(coord[0].y > coord[1].y)
+ {
+ tmp = coord[1];
+ coord[1] = coord[0];
+ coord[0] = tmp;
+ }
+
+ if(coord[1].y > coord[2].y)
+ {
+ tmp = coord[2];
+ coord[2] = coord[1];
+ coord[1] = tmp;
+ }
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ coord_type m_coord[3];
+ double m_x[8];
+ double m_y[8];
+ unsigned m_cmd[8];
+ unsigned m_vertex;
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_gouraud_gray.h b/plugins/Clist_ng/AGG/include/agg_span_gouraud_gray.h new file mode 100644 index 0000000000..46a446ce00 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_gouraud_gray.h @@ -0,0 +1,250 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_GOURAUD_GRAY_INCLUDED
+#define AGG_SPAN_GOURAUD_GRAY_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_gray.h"
+#include "agg_dda_line.h"
+#include "agg_span_gouraud.h"
+
+namespace agg
+{
+
+ //=======================================================span_gouraud_gray
+ template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT>
+ {
+ public:
+ typedef ColorT color_type;
+ typedef typename color_type::value_type value_type;
+ typedef span_gouraud<color_type> base_type;
+ typedef typename base_type::coord_type coord_type;
+ enum subpixel_scale_e
+ {
+ subpixel_shift = 4,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+ private:
+ //--------------------------------------------------------------------
+ struct gray_calc
+ {
+ void init(const coord_type& c1, const coord_type& c2)
+ {
+ m_x1 = c1.x - 0.5;
+ m_y1 = c1.y - 0.5;
+ m_dx = c2.x - c1.x;
+ double dy = c2.y - c1.y;
+ m_1dy = (fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy;
+ m_v1 = c1.color.v;
+ m_a1 = c1.color.a;
+ m_dv = c2.color.v - m_v1;
+ m_da = c2.color.a - m_a1;
+ }
+
+ void calc(double y)
+ {
+ double k = (y - m_y1) * m_1dy;
+ if(k < 0.0) k = 0.0;
+ if(k > 1.0) k = 1.0;
+ m_v = m_v1 + iround(m_dv * k);
+ m_a = m_a1 + iround(m_da * k);
+ m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
+ }
+
+ double m_x1;
+ double m_y1;
+ double m_dx;
+ double m_1dy;
+ int m_v1;
+ int m_a1;
+ int m_dv;
+ int m_da;
+ int m_v;
+ int m_a;
+ int m_x;
+ };
+
+
+ public:
+ //--------------------------------------------------------------------
+ span_gouraud_gray() {}
+ span_gouraud_gray(const color_type& c1,
+ const color_type& c2,
+ const color_type& c3,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double d = 0) :
+ base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
+ {}
+
+ //--------------------------------------------------------------------
+ void prepare()
+ {
+ coord_type coord[3];
+ base_type::arrange_vertices(coord);
+
+ m_y2 = int(coord[1].y);
+
+ m_swap = cross_product(coord[0].x, coord[0].y,
+ coord[2].x, coord[2].y,
+ coord[1].x, coord[1].y) < 0.0;
+
+ m_c1.init(coord[0], coord[2]);
+ m_c2.init(coord[0], coord[1]);
+ m_c3.init(coord[1], coord[2]);
+ }
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ m_c1.calc(y);
+ const gray_calc* pc1 = &m_c1;
+ const gray_calc* pc2 = &m_c2;
+
+ if(y < m_y2)
+ {
+ // Bottom part of the triangle (first subtriangle)
+ //-------------------------
+ m_c2.calc(y + m_c2.m_1dy);
+ }
+ else
+ {
+ // Upper part (second subtriangle)
+ //-------------------------
+ m_c3.calc(y - m_c3.m_1dy);
+ pc2 = &m_c3;
+ }
+
+ if(m_swap)
+ {
+ // It means that the triangle is oriented clockwise,
+ // so that we need to swap the controlling structures
+ //-------------------------
+ const gray_calc* t = pc2;
+ pc2 = pc1;
+ pc1 = t;
+ }
+
+ // Get the horizontal length with subpixel accuracy
+ // and protect it from division by zero
+ //-------------------------
+ int nlen = abs(pc2->m_x - pc1->m_x);
+ if(nlen <= 0) nlen = 1;
+
+ dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen);
+ dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
+
+ // Calculate the starting point of the gradient with subpixel
+ // accuracy and correct (roll back) the interpolators.
+ // This operation will also clip the beginning of the span
+ // if necessary.
+ //-------------------------
+ int start = pc1->m_x - (x << subpixel_shift);
+ v -= start;
+ a -= start;
+ nlen += start;
+
+ int vv, va;
+ enum lim_e { lim = color_type::base_mask };
+
+ // Beginning part of the span. Since we rolled back the
+ // interpolators, the color values may have overflow.
+ // So that, we render the beginning part with checking
+ // for overflow. It lasts until "start" is positive;
+ // typically it's 1-2 pixels, but may be more in some cases.
+ //-------------------------
+ while(len && start > 0)
+ {
+ vv = v.y();
+ va = a.y();
+ if(vv < 0) vv = 0; if(vv > lim) vv = lim;
+ if(va < 0) va = 0; if(va > lim) va = lim;
+ span->v = (value_type)vv;
+ span->a = (value_type)va;
+ v += subpixel_scale;
+ a += subpixel_scale;
+ nlen -= subpixel_scale;
+ start -= subpixel_scale;
+ ++span;
+ --len;
+ }
+
+ // Middle part, no checking for overflow.
+ // Actual spans can be longer than the calculated length
+ // because of anti-aliasing, thus, the interpolators can
+ // overflow. But while "nlen" is positive we are safe.
+ //-------------------------
+ while(len && nlen > 0)
+ {
+ span->v = (value_type)v.y();
+ span->a = (value_type)a.y();
+ v += subpixel_scale;
+ a += subpixel_scale;
+ nlen -= subpixel_scale;
+ ++span;
+ --len;
+ }
+
+ // Ending part; checking for overflow.
+ // Typically it's 1-2 pixels, but may be more in some cases.
+ //-------------------------
+ while(len)
+ {
+ vv = v.y();
+ va = a.y();
+ if(vv < 0) vv = 0; if(vv > lim) vv = lim;
+ if(va < 0) va = 0; if(va > lim) va = lim;
+ span->v = (value_type)vv;
+ span->a = (value_type)va;
+ v += subpixel_scale;
+ a += subpixel_scale;
+ ++span;
+ --len;
+ }
+ }
+
+
+ private:
+ bool m_swap;
+ int m_y2;
+ gray_calc m_c1;
+ gray_calc m_c2;
+ gray_calc m_c3;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_gouraud_rgba.h b/plugins/Clist_ng/AGG/include/agg_span_gouraud_rgba.h new file mode 100644 index 0000000000..a379ddd95f --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_gouraud_rgba.h @@ -0,0 +1,286 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_GOURAUD_RGBA_INCLUDED
+#define AGG_SPAN_GOURAUD_RGBA_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+#include "agg_dda_line.h"
+#include "agg_span_gouraud.h"
+
+namespace agg
+{
+
+ //=======================================================span_gouraud_rgba
+ template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT>
+ {
+ public:
+ typedef ColorT color_type;
+ typedef typename ColorT::value_type value_type;
+ typedef span_gouraud<color_type> base_type;
+ typedef typename base_type::coord_type coord_type;
+ enum subpixel_scale_e
+ {
+ subpixel_shift = 4,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+ private:
+ //--------------------------------------------------------------------
+ struct rgba_calc
+ {
+ void init(const coord_type& c1, const coord_type& c2)
+ {
+ m_x1 = c1.x - 0.5;
+ m_y1 = c1.y - 0.5;
+ m_dx = c2.x - c1.x;
+ double dy = c2.y - c1.y;
+ m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy;
+ m_r1 = c1.color.r;
+ m_g1 = c1.color.g;
+ m_b1 = c1.color.b;
+ m_a1 = c1.color.a;
+ m_dr = c2.color.r - m_r1;
+ m_dg = c2.color.g - m_g1;
+ m_db = c2.color.b - m_b1;
+ m_da = c2.color.a - m_a1;
+ }
+
+ void calc(double y)
+ {
+ double k = (y - m_y1) * m_1dy;
+ if(k < 0.0) k = 0.0;
+ if(k > 1.0) k = 1.0;
+ m_r = m_r1 + iround(m_dr * k);
+ m_g = m_g1 + iround(m_dg * k);
+ m_b = m_b1 + iround(m_db * k);
+ m_a = m_a1 + iround(m_da * k);
+ m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
+ }
+
+ double m_x1;
+ double m_y1;
+ double m_dx;
+ double m_1dy;
+ int m_r1;
+ int m_g1;
+ int m_b1;
+ int m_a1;
+ int m_dr;
+ int m_dg;
+ int m_db;
+ int m_da;
+ int m_r;
+ int m_g;
+ int m_b;
+ int m_a;
+ int m_x;
+ };
+
+ public:
+
+ //--------------------------------------------------------------------
+ span_gouraud_rgba() {}
+ span_gouraud_rgba(const color_type& c1,
+ const color_type& c2,
+ const color_type& c3,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double d = 0) :
+ base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
+ {}
+
+ //--------------------------------------------------------------------
+ void prepare()
+ {
+ coord_type coord[3];
+ base_type::arrange_vertices(coord);
+
+ m_y2 = int(coord[1].y);
+
+ m_swap = cross_product(coord[0].x, coord[0].y,
+ coord[2].x, coord[2].y,
+ coord[1].x, coord[1].y) < 0.0;
+
+ m_rgba1.init(coord[0], coord[2]);
+ m_rgba2.init(coord[0], coord[1]);
+ m_rgba3.init(coord[1], coord[2]);
+ }
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
+ const rgba_calc* pc1 = &m_rgba1;
+ const rgba_calc* pc2 = &m_rgba2;
+
+ if(y <= m_y2)
+ {
+ // Bottom part of the triangle (first subtriangle)
+ //-------------------------
+ m_rgba2.calc(y + m_rgba2.m_1dy);
+ }
+ else
+ {
+ // Upper part (second subtriangle)
+ m_rgba3.calc(y - m_rgba3.m_1dy);
+ //-------------------------
+ pc2 = &m_rgba3;
+ }
+
+ if(m_swap)
+ {
+ // It means that the triangle is oriented clockwise,
+ // so that we need to swap the controlling structures
+ //-------------------------
+ const rgba_calc* t = pc2;
+ pc2 = pc1;
+ pc1 = t;
+ }
+
+ // Get the horizontal length with subpixel accuracy
+ // and protect it from division by zero
+ //-------------------------
+ int nlen = abs(pc2->m_x - pc1->m_x);
+ if(nlen <= 0) nlen = 1;
+
+ dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen);
+ dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen);
+ dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen);
+ dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
+
+ // Calculate the starting point of the gradient with subpixel
+ // accuracy and correct (roll back) the interpolators.
+ // This operation will also clip the beginning of the span
+ // if necessary.
+ //-------------------------
+ int start = pc1->m_x - (x << subpixel_shift);
+ r -= start;
+ g -= start;
+ b -= start;
+ a -= start;
+ nlen += start;
+
+ int vr, vg, vb, va;
+ enum lim_e { lim = color_type::base_mask };
+
+ // Beginning part of the span. Since we rolled back the
+ // interpolators, the color values may have overflow.
+ // So that, we render the beginning part with checking
+ // for overflow. It lasts until "start" is positive;
+ // typically it's 1-2 pixels, but may be more in some cases.
+ //-------------------------
+ while(len && start > 0)
+ {
+ vr = r.y();
+ vg = g.y();
+ vb = b.y();
+ va = a.y();
+ if(vr < 0) vr = 0; if(vr > lim) vr = lim;
+ if(vg < 0) vg = 0; if(vg > lim) vg = lim;
+ if(vb < 0) vb = 0; if(vb > lim) vb = lim;
+ if(va < 0) va = 0; if(va > lim) va = lim;
+ span->r = (value_type)vr;
+ span->g = (value_type)vg;
+ span->b = (value_type)vb;
+ span->a = (value_type)va;
+ r += subpixel_scale;
+ g += subpixel_scale;
+ b += subpixel_scale;
+ a += subpixel_scale;
+ nlen -= subpixel_scale;
+ start -= subpixel_scale;
+ ++span;
+ --len;
+ }
+
+ // Middle part, no checking for overflow.
+ // Actual spans can be longer than the calculated length
+ // because of anti-aliasing, thus, the interpolators can
+ // overflow. But while "nlen" is positive we are safe.
+ //-------------------------
+ while(len && nlen > 0)
+ {
+ span->r = (value_type)r.y();
+ span->g = (value_type)g.y();
+ span->b = (value_type)b.y();
+ span->a = (value_type)a.y();
+ r += subpixel_scale;
+ g += subpixel_scale;
+ b += subpixel_scale;
+ a += subpixel_scale;
+ nlen -= subpixel_scale;
+ ++span;
+ --len;
+ }
+
+ // Ending part; checking for overflow.
+ // Typically it's 1-2 pixels, but may be more in some cases.
+ //-------------------------
+ while(len)
+ {
+ vr = r.y();
+ vg = g.y();
+ vb = b.y();
+ va = a.y();
+ if(vr < 0) vr = 0; if(vr > lim) vr = lim;
+ if(vg < 0) vg = 0; if(vg > lim) vg = lim;
+ if(vb < 0) vb = 0; if(vb > lim) vb = lim;
+ if(va < 0) va = 0; if(va > lim) va = lim;
+ span->r = (value_type)vr;
+ span->g = (value_type)vg;
+ span->b = (value_type)vb;
+ span->a = (value_type)va;
+ r += subpixel_scale;
+ g += subpixel_scale;
+ b += subpixel_scale;
+ a += subpixel_scale;
+ ++span;
+ --len;
+ }
+ }
+
+ private:
+ bool m_swap;
+ int m_y2;
+ rgba_calc m_rgba1;
+ rgba_calc m_rgba2;
+ rgba_calc m_rgba3;
+ };
+
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_gradient.h b/plugins/Clist_ng/AGG/include/agg_span_gradient.h new file mode 100644 index 0000000000..382d1d979c --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_gradient.h @@ -0,0 +1,373 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_GRADIENT_INCLUDED
+#define AGG_SPAN_GRADIENT_INCLUDED
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "agg_basics.h"
+#include "agg_math.h"
+#include "agg_array.h"
+
+
+namespace agg
+{
+
+ enum gradient_subpixel_scale_e
+ {
+ gradient_subpixel_shift = 4, //-----gradient_subpixel_shift
+ gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale
+ gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask
+ };
+
+
+
+ //==========================================================span_gradient
+ template<class ColorT,
+ class Interpolator,
+ class GradientF,
+ class ColorF>
+ class span_gradient
+ {
+ public:
+ typedef Interpolator interpolator_type;
+ typedef ColorT color_type;
+
+ enum downscale_shift_e
+ {
+ downscale_shift = interpolator_type::subpixel_shift -
+ gradient_subpixel_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_gradient() {}
+
+ //--------------------------------------------------------------------
+ span_gradient(interpolator_type& inter,
+ const GradientF& gradient_function,
+ const ColorF& color_function,
+ double d1, double d2) :
+ m_interpolator(&inter),
+ m_gradient_function(&gradient_function),
+ m_color_function(&color_function),
+ m_d1(iround(d1 * gradient_subpixel_scale)),
+ m_d2(iround(d2 * gradient_subpixel_scale))
+ {}
+
+ //--------------------------------------------------------------------
+ interpolator_type& interpolator() { return *m_interpolator; }
+ const GradientF& gradient_function() const { return *m_gradient_function; }
+ const ColorF& color_function() const { return *m_color_function; }
+ double d1() const { return double(m_d1) / gradient_subpixel_scale; }
+ double d2() const { return double(m_d2) / gradient_subpixel_scale; }
+
+ //--------------------------------------------------------------------
+ void interpolator(interpolator_type& i) { m_interpolator = &i; }
+ void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
+ void color_function(const ColorF& cf) { m_color_function = &cf; }
+ void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
+ void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ int dd = m_d2 - m_d1;
+ if(dd < 1) dd = 1;
+ m_interpolator->begin(x+0.5, y+0.5, len);
+ do
+ {
+ m_interpolator->coordinates(&x, &y);
+ int d = m_gradient_function->calculate(x >> downscale_shift,
+ y >> downscale_shift, m_d2);
+ d = ((d - m_d1) * (int)m_color_function->size()) / dd;
+ if(d < 0) d = 0;
+ if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1;
+ *span++ = (*m_color_function)[d];
+ ++(*m_interpolator);
+ }
+ while(--len);
+ }
+
+ private:
+ interpolator_type* m_interpolator;
+ const GradientF* m_gradient_function;
+ const ColorF* m_color_function;
+ int m_d1;
+ int m_d2;
+ };
+
+
+
+
+ //=====================================================gradient_linear_color
+ template<class ColorT>
+ struct gradient_linear_color
+ {
+ typedef ColorT color_type;
+
+ gradient_linear_color() {}
+ gradient_linear_color(const color_type& c1, const color_type& c2,
+ unsigned size = 256) :
+ m_c1(c1), m_c2(c2), m_size(size) {}
+
+ unsigned size() const { return m_size; }
+ color_type operator [] (unsigned v) const
+ {
+ return m_c1.gradient(m_c2, double(v) / double(m_size - 1));
+ }
+
+ void colors(const color_type& c1, const color_type& c2, unsigned size = 256)
+ {
+ m_c1 = c1;
+ m_c2 = c2;
+ m_size = size;
+ }
+
+ color_type m_c1;
+ color_type m_c2;
+ unsigned m_size;
+ };
+
+
+
+
+
+
+ //==========================================================gradient_circle
+ class gradient_circle
+ {
+ // Actually the same as radial. Just for compatibility
+ public:
+ static AGG_INLINE int calculate(int x, int y, int)
+ {
+ return int(fast_sqrt(x*x + y*y));
+ }
+ };
+
+
+ //==========================================================gradient_radial
+ class gradient_radial
+ {
+ public:
+ static AGG_INLINE int calculate(int x, int y, int)
+ {
+ return int(fast_sqrt(x*x + y*y));
+ }
+ };
+
+ //========================================================gradient_radial_d
+ class gradient_radial_d
+ {
+ public:
+ static AGG_INLINE int calculate(int x, int y, int)
+ {
+ return uround(sqrt(double(x)*double(x) + double(y)*double(y)));
+ }
+ };
+
+ //====================================================gradient_radial_focus
+ class gradient_radial_focus
+ {
+ public:
+ //---------------------------------------------------------------------
+ gradient_radial_focus() :
+ m_r(100 * gradient_subpixel_scale),
+ m_fx(0),
+ m_fy(0)
+ {
+ update_values();
+ }
+
+ //---------------------------------------------------------------------
+ gradient_radial_focus(double r, double fx, double fy) :
+ m_r (iround(r * gradient_subpixel_scale)),
+ m_fx(iround(fx * gradient_subpixel_scale)),
+ m_fy(iround(fy * gradient_subpixel_scale))
+ {
+ update_values();
+ }
+
+ //---------------------------------------------------------------------
+ void init(double r, double fx, double fy)
+ {
+ m_r = iround(r * gradient_subpixel_scale);
+ m_fx = iround(fx * gradient_subpixel_scale);
+ m_fy = iround(fy * gradient_subpixel_scale);
+ update_values();
+ }
+
+ //---------------------------------------------------------------------
+ double radius() const { return double(m_r) / gradient_subpixel_scale; }
+ double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
+ double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
+
+ //---------------------------------------------------------------------
+ int calculate(int x, int y, int) const
+ {
+ double dx = x - m_fx;
+ double dy = y - m_fy;
+ double d2 = dx * m_fy - dy * m_fx;
+ double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
+ return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul);
+ }
+
+ private:
+ //---------------------------------------------------------------------
+ void update_values()
+ {
+ // Calculate the invariant values. In case the focal center
+ // lies exactly on the gradient circle the divisor degenerates
+ // into zero. In this case we just move the focal center by
+ // one subpixel unit possibly in the direction to the origin (0,0)
+ // and calculate the values again.
+ //-------------------------
+ m_r2 = double(m_r) * double(m_r);
+ m_fx2 = double(m_fx) * double(m_fx);
+ m_fy2 = double(m_fy) * double(m_fy);
+ double d = (m_r2 - (m_fx2 + m_fy2));
+ if(d == 0)
+ {
+ if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
+ if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
+ m_fx2 = double(m_fx) * double(m_fx);
+ m_fy2 = double(m_fy) * double(m_fy);
+ d = (m_r2 - (m_fx2 + m_fy2));
+ }
+ m_mul = m_r / d;
+ }
+
+ int m_r;
+ int m_fx;
+ int m_fy;
+ double m_r2;
+ double m_fx2;
+ double m_fy2;
+ double m_mul;
+ };
+
+
+ //==============================================================gradient_x
+ class gradient_x
+ {
+ public:
+ static int calculate(int x, int, int) { return x; }
+ };
+
+
+ //==============================================================gradient_y
+ class gradient_y
+ {
+ public:
+ static int calculate(int, int y, int) { return y; }
+ };
+
+ //========================================================gradient_diamond
+ class gradient_diamond
+ {
+ public:
+ static AGG_INLINE int calculate(int x, int y, int)
+ {
+ int ax = abs(x);
+ int ay = abs(y);
+ return ax > ay ? ax : ay;
+ }
+ };
+
+ //=============================================================gradient_xy
+ class gradient_xy
+ {
+ public:
+ static AGG_INLINE int calculate(int x, int y, int d)
+ {
+ return abs(x) * abs(y) / d;
+ }
+ };
+
+ //========================================================gradient_sqrt_xy
+ class gradient_sqrt_xy
+ {
+ public:
+ static AGG_INLINE int calculate(int x, int y, int)
+ {
+ return fast_sqrt(abs(x) * abs(y));
+ }
+ };
+
+ //==========================================================gradient_conic
+ class gradient_conic
+ {
+ public:
+ static AGG_INLINE int calculate(int x, int y, int d)
+ {
+ return uround(fabs(atan2(double(y), double(x))) * double(d) / pi);
+ }
+ };
+
+ //=================================================gradient_repeat_adaptor
+ template<class GradientF> class gradient_repeat_adaptor
+ {
+ public:
+ gradient_repeat_adaptor(const GradientF& gradient) :
+ m_gradient(&gradient) {}
+
+ AGG_INLINE int calculate(int x, int y, int d) const
+ {
+ int ret = m_gradient->calculate(x, y, d) % d;
+ if(ret < 0) ret += d;
+ return ret;
+ }
+
+ private:
+ const GradientF* m_gradient;
+ };
+
+ //================================================gradient_reflect_adaptor
+ template<class GradientF> class gradient_reflect_adaptor
+ {
+ public:
+ gradient_reflect_adaptor(const GradientF& gradient) :
+ m_gradient(&gradient) {}
+
+ AGG_INLINE int calculate(int x, int y, int d) const
+ {
+ int d2 = d << 1;
+ int ret = m_gradient->calculate(x, y, d) % d2;
+ if(ret < 0) ret += d2;
+ if(ret >= d) ret = d2 - ret;
+ return ret;
+ }
+
+ private:
+ const GradientF* m_gradient;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_gradient_alpha.h b/plugins/Clist_ng/AGG/include/agg_span_gradient_alpha.h new file mode 100644 index 0000000000..862957686e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_gradient_alpha.h @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_GRADIENT_ALPHA_INCLUDED
+#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED
+
+#include "agg_span_gradient.h"
+
+namespace agg
+{
+ //======================================================span_gradient_alpha
+ template<class ColorT,
+ class Interpolator,
+ class GradientF,
+ class AlphaF>
+ class span_gradient_alpha
+ {
+ public:
+ typedef Interpolator interpolator_type;
+ typedef ColorT color_type;
+ typedef typename color_type::value_type alpha_type;
+
+ enum downscale_shift_e
+ {
+ downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift
+ };
+
+
+ //--------------------------------------------------------------------
+ span_gradient_alpha() {}
+
+ //--------------------------------------------------------------------
+ span_gradient_alpha(interpolator_type& inter,
+ const GradientF& gradient_function,
+ const AlphaF& alpha_function,
+ double d1, double d2) :
+ m_interpolator(&inter),
+ m_gradient_function(&gradient_function),
+ m_alpha_function(&alpha_function),
+ m_d1(iround(d1 * gradient_subpixel_scale)),
+ m_d2(iround(d2 * gradient_subpixel_scale))
+ {}
+
+ //--------------------------------------------------------------------
+ interpolator_type& interpolator() { return *m_interpolator; }
+ const GradientF& gradient_function() const { return *m_gradient_function; }
+ const AlphaF& alpha_function() const { return *m_alpha_function; }
+ double d1() const { return double(m_d1) / gradient_subpixel_scale; }
+ double d2() const { return double(m_d2) / gradient_subpixel_scale; }
+
+ //--------------------------------------------------------------------
+ void interpolator(interpolator_type& i) { m_interpolator = &i; }
+ void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
+ void alpha_function(const AlphaF& af) { m_alpha_function = ⁡ }
+ void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
+ void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ int dd = m_d2 - m_d1;
+ if(dd < 1) dd = 1;
+ m_interpolator->begin(x+0.5, y+0.5, len);
+ do
+ {
+ m_interpolator->coordinates(&x, &y);
+ int d = m_gradient_function->calculate(x >> downscale_shift,
+ y >> downscale_shift, m_d2);
+ d = ((d - m_d1) * (int)m_alpha_function->size()) / dd;
+ if(d < 0) d = 0;
+ if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1;
+ span->a = (*m_alpha_function)[d];
+ ++span;
+ ++(*m_interpolator);
+ }
+ while(--len);
+ }
+
+ private:
+ interpolator_type* m_interpolator;
+ const GradientF* m_gradient_function;
+ const AlphaF* m_alpha_function;
+ int m_d1;
+ int m_d2;
+ };
+
+
+ //=======================================================gradient_alpha_x
+ template<class ColorT> struct gradient_alpha_x
+ {
+ typedef typename ColorT::value_type alpha_type;
+ alpha_type operator [] (alpha_type x) const { return x; }
+ };
+
+ //====================================================gradient_alpha_x_u8
+ struct gradient_alpha_x_u8
+ {
+ typedef int8u alpha_type;
+ alpha_type operator [] (alpha_type x) const { return x; }
+ };
+
+ //==========================================gradient_alpha_one_munus_x_u8
+ struct gradient_alpha_one_munus_x_u8
+ {
+ typedef int8u alpha_type;
+ alpha_type operator [] (alpha_type x) const { return 255-x; }
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_image_filter.h b/plugins/Clist_ng/AGG/include/agg_span_image_filter.h new file mode 100644 index 0000000000..d0b1b9048b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_image_filter.h @@ -0,0 +1,252 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED
+#define AGG_SPAN_IMAGE_FILTER_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_image_filters.h"
+#include "agg_span_interpolator_linear.h"
+
+namespace agg
+{
+
+ //-------------------------------------------------------span_image_filter
+ template<class Source, class Interpolator> class span_image_filter
+ {
+ public:
+ typedef Source source_type;
+ typedef Interpolator interpolator_type;
+
+ //--------------------------------------------------------------------
+ span_image_filter() {}
+ span_image_filter(source_type& src,
+ interpolator_type& interpolator,
+ const image_filter_lut* filter) :
+ m_src(&src),
+ m_interpolator(&interpolator),
+ m_filter(filter),
+ m_dx_dbl(0.5),
+ m_dy_dbl(0.5),
+ m_dx_int(image_subpixel_scale / 2),
+ m_dy_int(image_subpixel_scale / 2)
+ {}
+ void attach(source_type& v) { m_src = &v; }
+
+ //--------------------------------------------------------------------
+ source_type& source() { return *m_src; }
+ const source_type& source() const { return *m_src; }
+ const image_filter_lut& filter() const { return *m_filter; }
+ int filter_dx_int() const { return m_dx_int; }
+ int filter_dy_int() const { return m_dy_int; }
+ double filter_dx_dbl() const { return m_dx_dbl; }
+ double filter_dy_dbl() const { return m_dy_dbl; }
+
+ //--------------------------------------------------------------------
+ void interpolator(interpolator_type& v) { m_interpolator = &v; }
+ void filter(const image_filter_lut& v) { m_filter = &v; }
+ void filter_offset(double dx, double dy)
+ {
+ m_dx_dbl = dx;
+ m_dy_dbl = dy;
+ m_dx_int = iround(dx * image_subpixel_scale);
+ m_dy_int = iround(dy * image_subpixel_scale);
+ }
+ void filter_offset(double d) { filter_offset(d, d); }
+
+ //--------------------------------------------------------------------
+ interpolator_type& interpolator() { return *m_interpolator; }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+
+ //--------------------------------------------------------------------
+ private:
+ source_type* m_src;
+ interpolator_type* m_interpolator;
+ const image_filter_lut* m_filter;
+ double m_dx_dbl;
+ double m_dy_dbl;
+ unsigned m_dx_int;
+ unsigned m_dy_int;
+ };
+
+
+
+
+ //==============================================span_image_resample_affine
+ template<class Source>
+ class span_image_resample_affine :
+ public span_image_filter<Source, span_interpolator_linear<trans_affine> >
+ {
+ public:
+ typedef Source source_type;
+ typedef span_interpolator_linear<trans_affine> interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+
+ //--------------------------------------------------------------------
+ span_image_resample_affine() :
+ m_scale_limit(200.0),
+ m_blur_x(1.0),
+ m_blur_y(1.0)
+ {}
+
+ //--------------------------------------------------------------------
+ span_image_resample_affine(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter),
+ m_scale_limit(200.0),
+ m_blur_x(1.0),
+ m_blur_y(1.0)
+ {}
+
+
+ //--------------------------------------------------------------------
+ int scale_limit() const { return uround(m_scale_limit); }
+ void scale_limit(int v) { m_scale_limit = v; }
+
+ //--------------------------------------------------------------------
+ double blur_x() const { return m_blur_x; }
+ double blur_y() const { return m_blur_y; }
+ void blur_x(double v) { m_blur_x = v; }
+ void blur_y(double v) { m_blur_y = v; }
+ void blur(double v) { m_blur_x = m_blur_y = v; }
+
+ //--------------------------------------------------------------------
+ void prepare()
+ {
+ double scale_x;
+ double scale_y;
+
+ base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
+
+ if(scale_x * scale_y > m_scale_limit)
+ {
+ scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
+ scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
+ }
+
+ if(scale_x < 1) scale_x = 1;
+ if(scale_y < 1) scale_y = 1;
+
+ if(scale_x > m_scale_limit) scale_x = m_scale_limit;
+ if(scale_y > m_scale_limit) scale_y = m_scale_limit;
+
+ scale_x *= m_blur_x;
+ scale_y *= m_blur_y;
+
+ if(scale_x < 1) scale_x = 1;
+ if(scale_y < 1) scale_y = 1;
+
+ m_rx = uround( scale_x * double(image_subpixel_scale));
+ m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
+
+ m_ry = uround( scale_y * double(image_subpixel_scale));
+ m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
+ }
+
+ protected:
+ int m_rx;
+ int m_ry;
+ int m_rx_inv;
+ int m_ry_inv;
+
+ private:
+ double m_scale_limit;
+ double m_blur_x;
+ double m_blur_y;
+ };
+
+
+
+ //=====================================================span_image_resample
+ template<class Source, class Interpolator>
+ class span_image_resample :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+
+ //--------------------------------------------------------------------
+ span_image_resample() :
+ m_scale_limit(20),
+ m_blur_x(image_subpixel_scale),
+ m_blur_y(image_subpixel_scale)
+ {}
+
+ //--------------------------------------------------------------------
+ span_image_resample(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter),
+ m_scale_limit(20),
+ m_blur_x(image_subpixel_scale),
+ m_blur_y(image_subpixel_scale)
+ {}
+
+ //--------------------------------------------------------------------
+ int scale_limit() const { return m_scale_limit; }
+ void scale_limit(int v) { m_scale_limit = v; }
+
+ //--------------------------------------------------------------------
+ double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
+ double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
+ void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
+ void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
+ void blur(double v) { m_blur_x =
+ m_blur_y = uround(v * double(image_subpixel_scale)); }
+
+ protected:
+ AGG_INLINE void adjust_scale(int* rx, int* ry)
+ {
+ if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
+ if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
+ if(*rx > image_subpixel_scale * m_scale_limit)
+ {
+ *rx = image_subpixel_scale * m_scale_limit;
+ }
+ if(*ry > image_subpixel_scale * m_scale_limit)
+ {
+ *ry = image_subpixel_scale * m_scale_limit;
+ }
+ *rx = (*rx * m_blur_x) >> image_subpixel_shift;
+ *ry = (*ry * m_blur_y) >> image_subpixel_shift;
+ if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
+ if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
+ }
+
+ int m_scale_limit;
+ int m_blur_x;
+ int m_blur_y;
+ };
+
+
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_image_filter_gray.h b/plugins/Clist_ng/AGG/include/agg_span_image_filter_gray.h new file mode 100644 index 0000000000..e5293e1e39 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_image_filter_gray.h @@ -0,0 +1,757 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+#ifndef AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED
+#define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_gray.h"
+#include "agg_span_image_filter.h"
+
+
+namespace agg
+{
+
+ //==============================================span_image_filter_gray_nn
+ template<class Source, class Interpolator>
+ class span_image_filter_gray_nn :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_gray_nn() {}
+ span_image_filter_gray_nn(source_type& src,
+ interpolator_type& inter) :
+ base_type(src, inter, 0)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+ span->v = *(const value_type*)
+ base_type::source().span(x >> image_subpixel_shift,
+ y >> image_subpixel_shift,
+ 1);
+ span->a = base_mask;
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+
+ //=========================================span_image_filter_gray_bilinear
+ template<class Source, class Interpolator>
+ class span_image_filter_gray_bilinear :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_gray_bilinear() {}
+ span_image_filter_gray_bilinear(source_type& src,
+ interpolator_type& inter) :
+ base_type(src, inter, 0)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ calc_type fg;
+ const value_type *fg_ptr;
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ fg = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+ fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr);
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr);
+
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ fg += *fg_ptr * x_hr * y_hr;
+
+ span->v = value_type(fg >> (image_subpixel_shift * 2));
+ span->a = base_mask;
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+ //====================================span_image_filter_gray_bilinear_clip
+ template<class Source, class Interpolator>
+ class span_image_filter_gray_bilinear_clip :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_gray_bilinear_clip() {}
+ span_image_filter_gray_bilinear_clip(source_type& src,
+ const color_type& back_color,
+ interpolator_type& inter) :
+ base_type(src, inter, 0),
+ m_back_color(back_color)
+ {}
+ const color_type& background_color() const { return m_back_color; }
+ void background_color(const color_type& v) { m_back_color = v; }
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ calc_type fg;
+ calc_type src_alpha;
+ value_type back_v = m_back_color.v;
+ value_type back_a = m_back_color.a;
+
+ const value_type *fg_ptr;
+
+ int maxx = base_type::source().width() - 1;
+ int maxy = base_type::source().height() - 1;
+
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr < maxx && y_lr < maxy)
+ {
+ fg = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+ fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr;
+
+ fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr);
+ fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr;
+
+ ++y_lr;
+ fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr;
+
+ fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr;
+ fg += *fg_ptr++ * x_hr * y_hr;
+
+ fg >>= image_subpixel_shift * 2;
+ src_alpha = base_mask;
+ }
+ else
+ {
+ unsigned weight;
+ if(x_lr < -1 || y_lr < -1 ||
+ x_lr > maxx || y_lr > maxy)
+ {
+ fg = back_v;
+ src_alpha = back_a;
+ }
+ else
+ {
+ fg =
+ src_alpha = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ weight = (image_subpixel_scale - x_hr) *
+ (image_subpixel_scale - y_hr);
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg += weight *
+ *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg += back_v * weight;
+ src_alpha += back_a * weight;
+ }
+
+ x_lr++;
+
+ weight = x_hr * (image_subpixel_scale - y_hr);
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg += weight *
+ *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg += back_v * weight;
+ src_alpha += back_a * weight;
+ }
+
+ x_lr--;
+ y_lr++;
+
+ weight = (image_subpixel_scale - x_hr) * y_hr;
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg += weight *
+ *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg += back_v * weight;
+ src_alpha += back_a * weight;
+ }
+
+ x_lr++;
+
+ weight = x_hr * y_hr;
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg += weight *
+ *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg += back_v * weight;
+ src_alpha += back_a * weight;
+ }
+
+ fg >>= image_subpixel_shift * 2;
+ src_alpha >>= image_subpixel_shift * 2;
+ }
+ }
+
+ span->v = (value_type)fg;
+ span->a = (value_type)src_alpha;
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ private:
+ color_type m_back_color;
+ };
+
+
+
+ //==============================================span_image_filter_gray_2x2
+ template<class Source, class Interpolator>
+ class span_image_filter_gray_2x2 :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_gray_2x2() {}
+ span_image_filter_gray_2x2(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ calc_type fg;
+
+ const value_type *fg_ptr;
+ const int16* weight_array = base_type::filter().weight_array() +
+ ((base_type::filter().diameter()/2 - 1) <<
+ image_subpixel_shift);
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ unsigned weight;
+ fg = image_filter_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+ weight = (weight_array[x_hr + image_subpixel_scale] *
+ weight_array[y_hr + image_subpixel_scale] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = (weight_array[x_hr] *
+ weight_array[y_hr + image_subpixel_scale] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ weight = (weight_array[x_hr + image_subpixel_scale] *
+ weight_array[y_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = (weight_array[x_hr] *
+ weight_array[y_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg += weight * *fg_ptr;
+
+ fg >>= image_filter_shift;
+ if(fg > base_mask) fg = base_mask;
+
+ span->v = (value_type)fg;
+ span->a = base_mask;
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+
+ //==================================================span_image_filter_gray
+ template<class Source, class Interpolator>
+ class span_image_filter_gray :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_gray() {}
+ span_image_filter_gray(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ int fg;
+ const value_type *fg_ptr;
+
+ unsigned diameter = base_type::filter().diameter();
+ int start = base_type::filter().start();
+ const int16* weight_array = base_type::filter().weight_array();
+
+ int x_count;
+ int weight_y;
+
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+
+ x -= base_type::filter_dx_int();
+ y -= base_type::filter_dy_int();
+
+ int x_hr = x;
+ int y_hr = y;
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ fg = image_filter_scale / 2;
+
+ int x_fract = x_hr & image_subpixel_mask;
+ unsigned y_count = diameter;
+
+ y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
+ fg_ptr = (const value_type*)base_type::source().span(x_lr + start,
+ y_lr + start,
+ diameter);
+ for(;;)
+ {
+ x_count = diameter;
+ weight_y = weight_array[y_hr];
+ x_hr = image_subpixel_mask - x_fract;
+ for(;;)
+ {
+ fg += *fg_ptr *
+ ((weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift);
+ if(--x_count == 0) break;
+ x_hr += image_subpixel_scale;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+
+ if(--y_count == 0) break;
+ y_hr += image_subpixel_scale;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg >>= image_filter_shift;
+ if(fg < 0) fg = 0;
+ if(fg > base_mask) fg = base_mask;
+ span->v = (value_type)fg;
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //=========================================span_image_resample_gray_affine
+ template<class Source>
+ class span_image_resample_gray_affine :
+ public span_image_resample_affine<Source>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef span_image_resample_affine<source_type> base_type;
+ typedef typename base_type::interpolator_type interpolator_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask,
+ downscale_shift = image_filter_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_image_resample_gray_affine() {}
+ span_image_resample_gray_affine(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, filter)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ long_type fg;
+
+ int diameter = base_type::filter().diameter();
+ int filter_scale = diameter << image_subpixel_shift;
+ int radius_x = (diameter * base_type::m_rx) >> 1;
+ int radius_y = (diameter * base_type::m_ry) >> 1;
+ int len_x_lr =
+ (diameter * base_type::m_rx + image_subpixel_mask) >>
+ image_subpixel_shift;
+
+ const int16* weight_array = base_type::filter().weight_array();
+
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+
+ x += base_type::filter_dx_int() - radius_x;
+ y += base_type::filter_dy_int() - radius_y;
+
+ fg = image_filter_scale / 2;
+
+ int y_lr = y >> image_subpixel_shift;
+ int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
+ base_type::m_ry_inv) >>
+ image_subpixel_shift;
+ int total_weight = 0;
+ int x_lr = x >> image_subpixel_shift;
+ int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
+ base_type::m_rx_inv) >>
+ image_subpixel_shift;
+
+ int x_hr2 = x_hr;
+ const value_type* fg_ptr =
+ (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
+ for(;;)
+ {
+ int weight_y = weight_array[y_hr];
+ x_hr = x_hr2;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ downscale_shift;
+
+ fg += *fg_ptr * weight;
+ total_weight += weight;
+ x_hr += base_type::m_rx_inv;
+ if(x_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+ y_hr += base_type::m_ry_inv;
+ if(y_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg /= total_weight;
+ if(fg < 0) fg = 0;
+ if(fg > base_mask) fg = base_mask;
+
+ span->v = (value_type)fg;
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+
+ //================================================span_image_resample_gray
+ template<class Source, class Interpolator>
+ class span_image_resample_gray :
+ public span_image_resample<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_resample<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask,
+ downscale_shift = image_filter_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_image_resample_gray() {}
+ span_image_resample_gray(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, filter)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ long_type fg;
+
+ int diameter = base_type::filter().diameter();
+ int filter_scale = diameter << image_subpixel_shift;
+
+ const int16* weight_array = base_type::filter().weight_array();
+ do
+ {
+ int rx;
+ int ry;
+ int rx_inv = image_subpixel_scale;
+ int ry_inv = image_subpixel_scale;
+ base_type::interpolator().coordinates(&x, &y);
+ base_type::interpolator().local_scale(&rx, &ry);
+ base_type::adjust_scale(&rx, &ry);
+
+ rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
+ ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
+
+ int radius_x = (diameter * rx) >> 1;
+ int radius_y = (diameter * ry) >> 1;
+ int len_x_lr =
+ (diameter * rx + image_subpixel_mask) >>
+ image_subpixel_shift;
+
+ x += base_type::filter_dx_int() - radius_x;
+ y += base_type::filter_dy_int() - radius_y;
+
+ fg = image_filter_scale / 2;
+
+ int y_lr = y >> image_subpixel_shift;
+ int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
+ ry_inv) >>
+ image_subpixel_shift;
+ int total_weight = 0;
+ int x_lr = x >> image_subpixel_shift;
+ int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
+ rx_inv) >>
+ image_subpixel_shift;
+ int x_hr2 = x_hr;
+ const value_type* fg_ptr =
+ (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
+
+ for(;;)
+ {
+ int weight_y = weight_array[y_hr];
+ x_hr = x_hr2;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ downscale_shift;
+ fg += *fg_ptr * weight;
+ total_weight += weight;
+ x_hr += rx_inv;
+ if(x_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+ y_hr += ry_inv;
+ if(y_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg /= total_weight;
+ if(fg < 0) fg = 0;
+ if(fg > base_mask) fg = base_mask;
+
+ span->v = (value_type)fg;
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+}
+
+
+#endif
+
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_image_filter_rgb.h b/plugins/Clist_ng/AGG/include/agg_span_image_filter_rgb.h new file mode 100644 index 0000000000..870b5c36c3 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_image_filter_rgb.h @@ -0,0 +1,901 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+#ifndef AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED
+#define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+#include "agg_span_image_filter.h"
+
+
+namespace agg
+{
+
+ //===============================================span_image_filter_rgb_nn
+ template<class Source, class Interpolator>
+ class span_image_filter_rgb_nn :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgb_nn() {}
+ span_image_filter_rgb_nn(source_type& src,
+ interpolator_type& inter) :
+ base_type(src, inter, 0)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+ const value_type* fg_ptr = (const value_type*)
+ base_type::source().span(x >> image_subpixel_shift,
+ y >> image_subpixel_shift,
+ 1);
+ span->r = fg_ptr[order_type::R];
+ span->g = fg_ptr[order_type::G];
+ span->b = fg_ptr[order_type::B];
+ span->a = base_mask;
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //==========================================span_image_filter_rgb_bilinear
+ template<class Source, class Interpolator>
+ class span_image_filter_rgb_bilinear :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgb_bilinear() {}
+ span_image_filter_rgb_bilinear(source_type& src,
+ interpolator_type& inter) :
+ base_type(src, inter, 0)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ calc_type fg[3];
+ const value_type *fg_ptr;
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ unsigned weight;
+
+ fg[0] =
+ fg[1] =
+ fg[2] = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+ weight = (image_subpixel_scale - x_hr) *
+ (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = x_hr * (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ weight = (image_subpixel_scale - x_hr) * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = x_hr * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2));
+ span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2));
+ span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2));
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //=====================================span_image_filter_rgb_bilinear_clip
+ template<class Source, class Interpolator>
+ class span_image_filter_rgb_bilinear_clip :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgb_bilinear_clip() {}
+ span_image_filter_rgb_bilinear_clip(source_type& src,
+ const color_type& back_color,
+ interpolator_type& inter) :
+ base_type(src, inter, 0),
+ m_back_color(back_color)
+ {}
+ const color_type& background_color() const { return m_back_color; }
+ void background_color(const color_type& v) { m_back_color = v; }
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ calc_type fg[3];
+ calc_type src_alpha;
+ value_type back_r = m_back_color.r;
+ value_type back_g = m_back_color.g;
+ value_type back_b = m_back_color.b;
+ value_type back_a = m_back_color.a;
+
+ const value_type *fg_ptr;
+
+ int maxx = base_type::source().width() - 1;
+ int maxy = base_type::source().height() - 1;
+
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+ unsigned weight;
+
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr < maxx && y_lr < maxy)
+ {
+ fg[0] =
+ fg[1] =
+ fg[2] = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
+
+ weight = (image_subpixel_scale - x_hr) *
+ (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+
+ weight = x_hr * (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+
+ ++y_lr;
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
+
+ weight = (image_subpixel_scale - x_hr) * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+
+ weight = x_hr * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+
+ fg[0] >>= image_subpixel_shift * 2;
+ fg[1] >>= image_subpixel_shift * 2;
+ fg[2] >>= image_subpixel_shift * 2;
+ src_alpha = base_mask;
+ }
+ else
+ {
+ if(x_lr < -1 || y_lr < -1 ||
+ x_lr > maxx || y_lr > maxy)
+ {
+ fg[order_type::R] = back_r;
+ fg[order_type::G] = back_g;
+ fg[order_type::B] = back_b;
+ src_alpha = back_a;
+ }
+ else
+ {
+ fg[0] =
+ fg[1] =
+ fg[2] =
+ src_alpha = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ weight = (image_subpixel_scale - x_hr) *
+ (image_subpixel_scale - y_hr);
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ src_alpha += back_a * weight;
+ }
+
+ x_lr++;
+
+ weight = x_hr * (image_subpixel_scale - y_hr);
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ src_alpha += back_a * weight;
+ }
+
+ x_lr--;
+ y_lr++;
+
+ weight = (image_subpixel_scale - x_hr) * y_hr;
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ src_alpha += back_a * weight;
+ }
+
+ x_lr++;
+
+ weight = x_hr * y_hr;
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr;
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ src_alpha += weight * base_mask;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ src_alpha += back_a * weight;
+ }
+
+ fg[0] >>= image_subpixel_shift * 2;
+ fg[1] >>= image_subpixel_shift * 2;
+ fg[2] >>= image_subpixel_shift * 2;
+ src_alpha >>= image_subpixel_shift * 2;
+ }
+ }
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = (value_type)src_alpha;
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ private:
+ color_type m_back_color;
+ };
+
+
+
+ //===============================================span_image_filter_rgb_2x2
+ template<class Source, class Interpolator>
+ class span_image_filter_rgb_2x2 :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgb_2x2() {}
+ span_image_filter_rgb_2x2(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ calc_type fg[3];
+
+ const value_type *fg_ptr;
+ const int16* weight_array = base_type::filter().weight_array() +
+ ((base_type::filter().diameter()/2 - 1) <<
+ image_subpixel_shift);
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ unsigned weight;
+ fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+ weight = (weight_array[x_hr + image_subpixel_scale] *
+ weight_array[y_hr + image_subpixel_scale] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = (weight_array[x_hr] *
+ weight_array[y_hr + image_subpixel_scale] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ weight = (weight_array[x_hr + image_subpixel_scale] *
+ weight_array[y_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = (weight_array[x_hr] *
+ weight_array[y_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ fg[0] >>= image_filter_shift;
+ fg[1] >>= image_filter_shift;
+ fg[2] >>= image_filter_shift;
+
+ if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
+ if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
+ if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //===================================================span_image_filter_rgb
+ template<class Source, class Interpolator>
+ class span_image_filter_rgb :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgb() {}
+ span_image_filter_rgb(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ int fg[3];
+ const value_type *fg_ptr;
+
+ unsigned diameter = base_type::filter().diameter();
+ int start = base_type::filter().start();
+ const int16* weight_array = base_type::filter().weight_array();
+
+ int x_count;
+ int weight_y;
+
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+
+ x -= base_type::filter_dx_int();
+ y -= base_type::filter_dy_int();
+
+ int x_hr = x;
+ int y_hr = y;
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
+
+ int x_fract = x_hr & image_subpixel_mask;
+ unsigned y_count = diameter;
+
+ y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
+ fg_ptr = (const value_type*)base_type::source().span(x_lr + start,
+ y_lr + start,
+ diameter);
+ for(;;)
+ {
+ x_count = diameter;
+ weight_y = weight_array[y_hr];
+ x_hr = image_subpixel_mask - x_fract;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr;
+
+ if(--x_count == 0) break;
+ x_hr += image_subpixel_scale;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+
+ if(--y_count == 0) break;
+ y_hr += image_subpixel_scale;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg[0] >>= image_filter_shift;
+ fg[1] >>= image_filter_shift;
+ fg[2] >>= image_filter_shift;
+
+ if(fg[0] < 0) fg[0] = 0;
+ if(fg[1] < 0) fg[1] = 0;
+ if(fg[2] < 0) fg[2] = 0;
+
+ if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
+ if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
+ if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //==========================================span_image_resample_rgb_affine
+ template<class Source>
+ class span_image_resample_rgb_affine :
+ public span_image_resample_affine<Source>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef span_image_resample_affine<source_type> base_type;
+ typedef typename base_type::interpolator_type interpolator_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask,
+ downscale_shift = image_filter_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_image_resample_rgb_affine() {}
+ span_image_resample_rgb_affine(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, filter)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ long_type fg[3];
+
+ int diameter = base_type::filter().diameter();
+ int filter_scale = diameter << image_subpixel_shift;
+ int radius_x = (diameter * base_type::m_rx) >> 1;
+ int radius_y = (diameter * base_type::m_ry) >> 1;
+ int len_x_lr =
+ (diameter * base_type::m_rx + image_subpixel_mask) >>
+ image_subpixel_shift;
+
+ const int16* weight_array = base_type::filter().weight_array();
+
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+
+ x += base_type::filter_dx_int() - radius_x;
+ y += base_type::filter_dy_int() - radius_y;
+
+ fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
+
+ int y_lr = y >> image_subpixel_shift;
+ int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
+ base_type::m_ry_inv) >>
+ image_subpixel_shift;
+ int total_weight = 0;
+ int x_lr = x >> image_subpixel_shift;
+ int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
+ base_type::m_rx_inv) >>
+ image_subpixel_shift;
+
+ int x_hr2 = x_hr;
+ const value_type* fg_ptr =
+ (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
+ for(;;)
+ {
+ int weight_y = weight_array[y_hr];
+ x_hr = x_hr2;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ downscale_shift;
+
+ fg[0] += *fg_ptr++ * weight;
+ fg[1] += *fg_ptr++ * weight;
+ fg[2] += *fg_ptr * weight;
+ total_weight += weight;
+ x_hr += base_type::m_rx_inv;
+ if(x_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+ y_hr += base_type::m_ry_inv;
+ if(y_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg[0] /= total_weight;
+ fg[1] /= total_weight;
+ fg[2] /= total_weight;
+
+ if(fg[0] < 0) fg[0] = 0;
+ if(fg[1] < 0) fg[1] = 0;
+ if(fg[2] < 0) fg[2] = 0;
+
+ if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
+ if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
+ if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+
+ //=================================================span_image_resample_rgb
+ template<class Source, class Interpolator>
+ class span_image_resample_rgb :
+ public span_image_resample<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_resample<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask,
+ downscale_shift = image_filter_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_image_resample_rgb() {}
+ span_image_resample_rgb(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, filter)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ long_type fg[3];
+
+ int diameter = base_type::filter().diameter();
+ int filter_scale = diameter << image_subpixel_shift;
+
+ const int16* weight_array = base_type::filter().weight_array();
+ do
+ {
+ int rx;
+ int ry;
+ int rx_inv = image_subpixel_scale;
+ int ry_inv = image_subpixel_scale;
+ base_type::interpolator().coordinates(&x, &y);
+ base_type::interpolator().local_scale(&rx, &ry);
+ base_type::adjust_scale(&rx, &ry);
+
+ rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
+ ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
+
+ int radius_x = (diameter * rx) >> 1;
+ int radius_y = (diameter * ry) >> 1;
+ int len_x_lr =
+ (diameter * rx + image_subpixel_mask) >>
+ image_subpixel_shift;
+
+ x += base_type::filter_dx_int() - radius_x;
+ y += base_type::filter_dy_int() - radius_y;
+
+ fg[0] = fg[1] = fg[2] = image_filter_scale / 2;
+
+ int y_lr = y >> image_subpixel_shift;
+ int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
+ ry_inv) >>
+ image_subpixel_shift;
+ int total_weight = 0;
+ int x_lr = x >> image_subpixel_shift;
+ int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
+ rx_inv) >>
+ image_subpixel_shift;
+ int x_hr2 = x_hr;
+ const value_type* fg_ptr =
+ (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
+
+ for(;;)
+ {
+ int weight_y = weight_array[y_hr];
+ x_hr = x_hr2;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ downscale_shift;
+ fg[0] += *fg_ptr++ * weight;
+ fg[1] += *fg_ptr++ * weight;
+ fg[2] += *fg_ptr * weight;
+ total_weight += weight;
+ x_hr += rx_inv;
+ if(x_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+ y_hr += ry_inv;
+ if(y_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg[0] /= total_weight;
+ fg[1] /= total_weight;
+ fg[2] /= total_weight;
+
+ if(fg[0] < 0) fg[0] = 0;
+ if(fg[1] < 0) fg[1] = 0;
+ if(fg[2] < 0) fg[2] = 0;
+
+ if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask;
+ if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask;
+ if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask;
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = base_mask;
+
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+}
+
+
+#endif
+
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_image_filter_rgba.h b/plugins/Clist_ng/AGG/include/agg_span_image_filter_rgba.h new file mode 100644 index 0000000000..598ca3780e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_image_filter_rgba.h @@ -0,0 +1,929 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+#ifndef AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED
+#define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+#include "agg_span_image_filter.h"
+
+
+namespace agg
+{
+
+ //==============================================span_image_filter_rgba_nn
+ template<class Source, class Interpolator>
+ class span_image_filter_rgba_nn :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgba_nn() {}
+ span_image_filter_rgba_nn(source_type& src,
+ interpolator_type& inter) :
+ base_type(src, inter, 0)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+ const value_type* fg_ptr = (const value_type*)
+ base_type::source().span(x >> image_subpixel_shift,
+ y >> image_subpixel_shift,
+ 1);
+ span->r = fg_ptr[order_type::R];
+ span->g = fg_ptr[order_type::G];
+ span->b = fg_ptr[order_type::B];
+ span->a = fg_ptr[order_type::A];
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //=========================================span_image_filter_rgba_bilinear
+ template<class Source, class Interpolator>
+ class span_image_filter_rgba_bilinear :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgba_bilinear() {}
+ span_image_filter_rgba_bilinear(source_type& src,
+ interpolator_type& inter) :
+ base_type(src, inter, 0)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ calc_type fg[4];
+ const value_type *fg_ptr;
+
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ unsigned weight;
+
+ fg[0] =
+ fg[1] =
+ fg[2] =
+ fg[3] = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+ weight = (image_subpixel_scale - x_hr) *
+ (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = x_hr * (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ weight = (image_subpixel_scale - x_hr) * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = x_hr * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2));
+ span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2));
+ span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2));
+ span->a = value_type(fg[order_type::A] >> (image_subpixel_shift * 2));
+
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+ //====================================span_image_filter_rgba_bilinear_clip
+ template<class Source, class Interpolator>
+ class span_image_filter_rgba_bilinear_clip :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgba_bilinear_clip() {}
+ span_image_filter_rgba_bilinear_clip(source_type& src,
+ const color_type& back_color,
+ interpolator_type& inter) :
+ base_type(src, inter, 0),
+ m_back_color(back_color)
+ {}
+ const color_type& background_color() const { return m_back_color; }
+ void background_color(const color_type& v) { m_back_color = v; }
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ calc_type fg[4];
+ value_type back_r = m_back_color.r;
+ value_type back_g = m_back_color.g;
+ value_type back_b = m_back_color.b;
+ value_type back_a = m_back_color.a;
+
+ const value_type *fg_ptr;
+ int maxx = base_type::source().width() - 1;
+ int maxy = base_type::source().height() - 1;
+
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ unsigned weight;
+
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr < maxx && y_lr < maxy)
+ {
+ fg[0] =
+ fg[1] =
+ fg[2] =
+ fg[3] = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + (x_lr << 2);
+
+ weight = (image_subpixel_scale - x_hr) *
+ (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+
+ weight = x_hr * (image_subpixel_scale - y_hr);
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+
+ ++y_lr;
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + (x_lr << 2);
+
+ weight = (image_subpixel_scale - x_hr) * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+
+ weight = x_hr * y_hr;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+
+ fg[0] >>= image_subpixel_shift * 2;
+ fg[1] >>= image_subpixel_shift * 2;
+ fg[2] >>= image_subpixel_shift * 2;
+ fg[3] >>= image_subpixel_shift * 2;
+ }
+ else
+ {
+ if(x_lr < -1 || y_lr < -1 ||
+ x_lr > maxx || y_lr > maxy)
+ {
+ fg[order_type::R] = back_r;
+ fg[order_type::G] = back_g;
+ fg[order_type::B] = back_b;
+ fg[order_type::A] = back_a;
+ }
+ else
+ {
+ fg[0] =
+ fg[1] =
+ fg[2] =
+ fg[3] = image_subpixel_scale * image_subpixel_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ weight = (image_subpixel_scale - x_hr) *
+ (image_subpixel_scale - y_hr);
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + (x_lr << 2);
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ fg[order_type::A] += back_a * weight;
+ }
+
+ x_lr++;
+
+ weight = x_hr * (image_subpixel_scale - y_hr);
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + (x_lr << 2);
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ fg[order_type::A] += back_a * weight;
+ }
+
+ x_lr--;
+ y_lr++;
+
+ weight = (image_subpixel_scale - x_hr) * y_hr;
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + (x_lr << 2);
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ fg[order_type::A] += back_a * weight;
+ }
+
+ x_lr++;
+
+ weight = x_hr * y_hr;
+ if(x_lr >= 0 && y_lr >= 0 &&
+ x_lr <= maxx && y_lr <= maxy)
+ {
+ fg_ptr = (const value_type*)
+ base_type::source().row_ptr(y_lr) + (x_lr << 2);
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr++;
+ }
+ else
+ {
+ fg[order_type::R] += back_r * weight;
+ fg[order_type::G] += back_g * weight;
+ fg[order_type::B] += back_b * weight;
+ fg[order_type::A] += back_a * weight;
+ }
+
+ fg[0] >>= image_subpixel_shift * 2;
+ fg[1] >>= image_subpixel_shift * 2;
+ fg[2] >>= image_subpixel_shift * 2;
+ fg[3] >>= image_subpixel_shift * 2;
+ }
+ }
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = (value_type)fg[order_type::A];
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ private:
+ color_type m_back_color;
+ };
+
+
+ //==============================================span_image_filter_rgba_2x2
+ template<class Source, class Interpolator>
+ class span_image_filter_rgba_2x2 :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgba_2x2() {}
+ span_image_filter_rgba_2x2(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ calc_type fg[4];
+
+ const value_type *fg_ptr;
+ const int16* weight_array = base_type::filter().weight_array() +
+ ((base_type::filter().diameter()/2 - 1) <<
+ image_subpixel_shift);
+
+ do
+ {
+ int x_hr;
+ int y_hr;
+
+ base_type::interpolator().coordinates(&x_hr, &y_hr);
+
+ x_hr -= base_type::filter_dx_int();
+ y_hr -= base_type::filter_dy_int();
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ unsigned weight;
+ fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
+
+ x_hr &= image_subpixel_mask;
+ y_hr &= image_subpixel_mask;
+
+ fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+ weight = (weight_array[x_hr + image_subpixel_scale] *
+ weight_array[y_hr + image_subpixel_scale] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = (weight_array[x_hr] *
+ weight_array[y_hr + image_subpixel_scale] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ weight = (weight_array[x_hr + image_subpixel_scale] *
+ weight_array[y_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ weight = (weight_array[x_hr] *
+ weight_array[y_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ fg[0] >>= image_filter_shift;
+ fg[1] >>= image_filter_shift;
+ fg[2] >>= image_filter_shift;
+ fg[3] >>= image_filter_shift;
+
+ if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
+ if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
+ if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
+ if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = (value_type)fg[order_type::A];
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //==================================================span_image_filter_rgba
+ template<class Source, class Interpolator>
+ class span_image_filter_rgba :
+ public span_image_filter<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_filter<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask
+ };
+
+ //--------------------------------------------------------------------
+ span_image_filter_rgba() {}
+ span_image_filter_rgba(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, &filter)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ int fg[4];
+ const value_type *fg_ptr;
+
+ unsigned diameter = base_type::filter().diameter();
+ int start = base_type::filter().start();
+ const int16* weight_array = base_type::filter().weight_array();
+
+ int x_count;
+ int weight_y;
+
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+
+ x -= base_type::filter_dx_int();
+ y -= base_type::filter_dy_int();
+
+ int x_hr = x;
+ int y_hr = y;
+
+ int x_lr = x_hr >> image_subpixel_shift;
+ int y_lr = y_hr >> image_subpixel_shift;
+
+ fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
+
+ int x_fract = x_hr & image_subpixel_mask;
+ unsigned y_count = diameter;
+
+ y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
+ fg_ptr = (const value_type*)base_type::source().span(x_lr + start,
+ y_lr + start,
+ diameter);
+ for(;;)
+ {
+ x_count = diameter;
+ weight_y = weight_array[y_hr];
+ x_hr = image_subpixel_mask - x_fract;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ image_filter_shift;
+
+ fg[0] += weight * *fg_ptr++;
+ fg[1] += weight * *fg_ptr++;
+ fg[2] += weight * *fg_ptr++;
+ fg[3] += weight * *fg_ptr;
+
+ if(--x_count == 0) break;
+ x_hr += image_subpixel_scale;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+
+ if(--y_count == 0) break;
+ y_hr += image_subpixel_scale;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg[0] >>= image_filter_shift;
+ fg[1] >>= image_filter_shift;
+ fg[2] >>= image_filter_shift;
+ fg[3] >>= image_filter_shift;
+
+ if(fg[0] < 0) fg[0] = 0;
+ if(fg[1] < 0) fg[1] = 0;
+ if(fg[2] < 0) fg[2] = 0;
+ if(fg[3] < 0) fg[3] = 0;
+
+ if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
+ if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
+ if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
+ if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = (value_type)fg[order_type::A];
+ ++span;
+ ++base_type::interpolator();
+
+ } while(--len);
+ }
+ };
+
+
+
+ //========================================span_image_resample_rgba_affine
+ template<class Source>
+ class span_image_resample_rgba_affine :
+ public span_image_resample_affine<Source>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef span_image_resample_affine<source_type> base_type;
+ typedef typename base_type::interpolator_type interpolator_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask,
+ downscale_shift = image_filter_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_image_resample_rgba_affine() {}
+ span_image_resample_rgba_affine(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, filter)
+ {}
+
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+
+ long_type fg[4];
+
+ int diameter = base_type::filter().diameter();
+ int filter_scale = diameter << image_subpixel_shift;
+ int radius_x = (diameter * base_type::m_rx) >> 1;
+ int radius_y = (diameter * base_type::m_ry) >> 1;
+ int len_x_lr =
+ (diameter * base_type::m_rx + image_subpixel_mask) >>
+ image_subpixel_shift;
+
+ const int16* weight_array = base_type::filter().weight_array();
+
+ do
+ {
+ base_type::interpolator().coordinates(&x, &y);
+
+ x += base_type::filter_dx_int() - radius_x;
+ y += base_type::filter_dy_int() - radius_y;
+
+ fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
+
+ int y_lr = y >> image_subpixel_shift;
+ int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
+ base_type::m_ry_inv) >>
+ image_subpixel_shift;
+ int total_weight = 0;
+ int x_lr = x >> image_subpixel_shift;
+ int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
+ base_type::m_rx_inv) >>
+ image_subpixel_shift;
+
+ int x_hr2 = x_hr;
+ const value_type* fg_ptr =
+ (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
+ for(;;)
+ {
+ int weight_y = weight_array[y_hr];
+ x_hr = x_hr2;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ downscale_shift;
+
+ fg[0] += *fg_ptr++ * weight;
+ fg[1] += *fg_ptr++ * weight;
+ fg[2] += *fg_ptr++ * weight;
+ fg[3] += *fg_ptr++ * weight;
+ total_weight += weight;
+ x_hr += base_type::m_rx_inv;
+ if(x_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+ y_hr += base_type::m_ry_inv;
+ if(y_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg[0] /= total_weight;
+ fg[1] /= total_weight;
+ fg[2] /= total_weight;
+ fg[3] /= total_weight;
+
+ if(fg[0] < 0) fg[0] = 0;
+ if(fg[1] < 0) fg[1] = 0;
+ if(fg[2] < 0) fg[2] = 0;
+ if(fg[3] < 0) fg[3] = 0;
+
+ if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
+ if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
+ if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
+ if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = (value_type)fg[order_type::A];
+
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+
+ //==============================================span_image_resample_rgba
+ template<class Source, class Interpolator>
+ class span_image_resample_rgba :
+ public span_image_resample<Source, Interpolator>
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef Interpolator interpolator_type;
+ typedef span_image_resample<source_type, interpolator_type> base_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::long_type long_type;
+ enum base_scale_e
+ {
+ base_shift = color_type::base_shift,
+ base_mask = color_type::base_mask,
+ downscale_shift = image_filter_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_image_resample_rgba() {}
+ span_image_resample_rgba(source_type& src,
+ interpolator_type& inter,
+ const image_filter_lut& filter) :
+ base_type(src, inter, filter)
+ {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
+ y + base_type::filter_dy_dbl(), len);
+ long_type fg[4];
+
+ int diameter = base_type::filter().diameter();
+ int filter_scale = diameter << image_subpixel_shift;
+
+ const int16* weight_array = base_type::filter().weight_array();
+ do
+ {
+ int rx;
+ int ry;
+ int rx_inv = image_subpixel_scale;
+ int ry_inv = image_subpixel_scale;
+ base_type::interpolator().coordinates(&x, &y);
+ base_type::interpolator().local_scale(&rx, &ry);
+ base_type::adjust_scale(&rx, &ry);
+
+ rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
+ ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
+
+ int radius_x = (diameter * rx) >> 1;
+ int radius_y = (diameter * ry) >> 1;
+ int len_x_lr =
+ (diameter * rx + image_subpixel_mask) >>
+ image_subpixel_shift;
+
+ x += base_type::filter_dx_int() - radius_x;
+ y += base_type::filter_dy_int() - radius_y;
+
+ fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;
+
+ int y_lr = y >> image_subpixel_shift;
+ int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
+ ry_inv) >>
+ image_subpixel_shift;
+ int total_weight = 0;
+ int x_lr = x >> image_subpixel_shift;
+ int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
+ rx_inv) >>
+ image_subpixel_shift;
+ int x_hr2 = x_hr;
+ const value_type* fg_ptr =
+ (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
+
+ for(;;)
+ {
+ int weight_y = weight_array[y_hr];
+ x_hr = x_hr2;
+ for(;;)
+ {
+ int weight = (weight_y * weight_array[x_hr] +
+ image_filter_scale / 2) >>
+ downscale_shift;
+ fg[0] += *fg_ptr++ * weight;
+ fg[1] += *fg_ptr++ * weight;
+ fg[2] += *fg_ptr++ * weight;
+ fg[3] += *fg_ptr++ * weight;
+ total_weight += weight;
+ x_hr += rx_inv;
+ if(x_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_x();
+ }
+ y_hr += ry_inv;
+ if(y_hr >= filter_scale) break;
+ fg_ptr = (const value_type*)base_type::source().next_y();
+ }
+
+ fg[0] /= total_weight;
+ fg[1] /= total_weight;
+ fg[2] /= total_weight;
+ fg[3] /= total_weight;
+
+ if(fg[0] < 0) fg[0] = 0;
+ if(fg[1] < 0) fg[1] = 0;
+ if(fg[2] < 0) fg[2] = 0;
+ if(fg[3] < 0) fg[3] = 0;
+
+ if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask;
+ if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R];
+ if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G];
+ if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B];
+
+ span->r = (value_type)fg[order_type::R];
+ span->g = (value_type)fg[order_type::G];
+ span->b = (value_type)fg[order_type::B];
+ span->a = (value_type)fg[order_type::A];
+
+ ++span;
+ ++base_type::interpolator();
+ } while(--len);
+ }
+ };
+
+
+}
+
+
+#endif
+
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_interpolator_adaptor.h b/plugins/Clist_ng/AGG/include/agg_span_interpolator_adaptor.h new file mode 100644 index 0000000000..b3ff22e23f --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_interpolator_adaptor.h @@ -0,0 +1,86 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
+#define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //===============================================span_interpolator_adaptor
+ template<class Interpolator, class Distortion>
+ class span_interpolator_adaptor : public Interpolator
+ {
+ public:
+ typedef Interpolator base_type;
+ typedef typename base_type::trans_type trans_type;
+ typedef Distortion distortion_type;
+
+ //--------------------------------------------------------------------
+ span_interpolator_adaptor() {}
+ span_interpolator_adaptor(const trans_type& trans,
+ const distortion_type& dist) :
+ base_type(trans),
+ m_distortion(&dist)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ span_interpolator_adaptor(const trans_type& trans,
+ const distortion_type& dist,
+ double x, double y, unsigned len) :
+ base_type(trans, x, y, len),
+ m_distortion(&dist)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ const distortion_type& distortion() const
+ {
+ return *m_distortion;
+ }
+
+ //--------------------------------------------------------------------
+ void distortion(const distortion_type& dist)
+ {
+ m_distortion = dist;
+ }
+
+ //--------------------------------------------------------------------
+ void coordinates(int* x, int* y) const
+ {
+ base_type::coordinates(x, y);
+ m_distortion->calculate(x, y);
+ }
+
+ private:
+ //--------------------------------------------------------------------
+ const distortion_type* m_distortion;
+ };
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_interpolator_linear.h b/plugins/Clist_ng/AGG/include/agg_span_interpolator_linear.h new file mode 100644 index 0000000000..c9bfafdd39 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_interpolator_linear.h @@ -0,0 +1,241 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
+#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_dda_line.h"
+#include "agg_trans_affine.h"
+
+namespace agg
+{
+
+ //================================================span_interpolator_linear
+ template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
+ class span_interpolator_linear
+ {
+ public:
+ typedef Transformer trans_type;
+
+ enum subpixel_scale_e
+ {
+ subpixel_shift = SubpixelShift,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_interpolator_linear() {}
+ span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {}
+ span_interpolator_linear(const trans_type& trans,
+ double x, double y, unsigned len) :
+ m_trans(&trans)
+ {
+ begin(x, y, len);
+ }
+
+ //----------------------------------------------------------------
+ const trans_type& transformer() const { return *m_trans; }
+ void transformer(const trans_type& trans) { m_trans = &trans; }
+
+ //----------------------------------------------------------------
+ void begin(double x, double y, unsigned len)
+ {
+ double tx;
+ double ty;
+
+ tx = x;
+ ty = y;
+ m_trans->transform(&tx, &ty);
+ int x1 = iround(tx * subpixel_scale);
+ int y1 = iround(ty * subpixel_scale);
+
+ tx = x + len;
+ ty = y;
+ m_trans->transform(&tx, &ty);
+ int x2 = iround(tx * subpixel_scale);
+ int y2 = iround(ty * subpixel_scale);
+
+ m_li_x = dda2_line_interpolator(x1, x2, len);
+ m_li_y = dda2_line_interpolator(y1, y2, len);
+ }
+
+ //----------------------------------------------------------------
+ void resynchronize(double xe, double ye, unsigned len)
+ {
+ m_trans->transform(&xe, &ye);
+ m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len);
+ m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len);
+ }
+
+ //----------------------------------------------------------------
+ void operator++()
+ {
+ ++m_li_x;
+ ++m_li_y;
+ }
+
+ //----------------------------------------------------------------
+ void coordinates(int* x, int* y) const
+ {
+ *x = m_li_x.y();
+ *y = m_li_y.y();
+ }
+
+ private:
+ const trans_type* m_trans;
+ dda2_line_interpolator m_li_x;
+ dda2_line_interpolator m_li_y;
+ };
+
+
+
+
+
+
+ //=====================================span_interpolator_linear_subdiv
+ template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
+ class span_interpolator_linear_subdiv
+ {
+ public:
+ typedef Transformer trans_type;
+
+ enum subpixel_scale_e
+ {
+ subpixel_shift = SubpixelShift,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+
+ //----------------------------------------------------------------
+ span_interpolator_linear_subdiv() :
+ m_subdiv_shift(4),
+ m_subdiv_size(1 << m_subdiv_shift),
+ m_subdiv_mask(m_subdiv_size - 1) {}
+
+ span_interpolator_linear_subdiv(const trans_type& trans,
+ unsigned subdiv_shift = 4) :
+ m_subdiv_shift(subdiv_shift),
+ m_subdiv_size(1 << m_subdiv_shift),
+ m_subdiv_mask(m_subdiv_size - 1),
+ m_trans(&trans) {}
+
+ span_interpolator_linear_subdiv(const trans_type& trans,
+ double x, double y, unsigned len,
+ unsigned subdiv_shift = 4) :
+ m_subdiv_shift(subdiv_shift),
+ m_subdiv_size(1 << m_subdiv_shift),
+ m_subdiv_mask(m_subdiv_size - 1),
+ m_trans(&trans)
+ {
+ begin(x, y, len);
+ }
+
+ //----------------------------------------------------------------
+ const trans_type& transformer() const { return *m_trans; }
+ void transformer(const trans_type& trans) { m_trans = &trans; }
+
+ //----------------------------------------------------------------
+ unsigned subdiv_shift() const { return m_subdiv_shift; }
+ void subdiv_shift(unsigned shift)
+ {
+ m_subdiv_shift = shift;
+ m_subdiv_size = 1 << m_subdiv_shift;
+ m_subdiv_mask = m_subdiv_size - 1;
+ }
+
+ //----------------------------------------------------------------
+ void begin(double x, double y, unsigned len)
+ {
+ double tx;
+ double ty;
+ m_pos = 1;
+ m_src_x = iround(x * subpixel_scale) + subpixel_scale;
+ m_src_y = y;
+ m_len = len;
+
+ if(len > m_subdiv_size) len = m_subdiv_size;
+ tx = x;
+ ty = y;
+ m_trans->transform(&tx, &ty);
+ int x1 = iround(tx * subpixel_scale);
+ int y1 = iround(ty * subpixel_scale);
+
+ tx = x + len;
+ ty = y;
+ m_trans->transform(&tx, &ty);
+
+ m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len);
+ m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len);
+ }
+
+ //----------------------------------------------------------------
+ void operator++()
+ {
+ ++m_li_x;
+ ++m_li_y;
+ if(m_pos >= m_subdiv_size)
+ {
+ unsigned len = m_len;
+ if(len > m_subdiv_size) len = m_subdiv_size;
+ double tx = double(m_src_x) / double(subpixel_scale) + len;
+ double ty = m_src_y;
+ m_trans->transform(&tx, &ty);
+ m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len);
+ m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len);
+ m_pos = 0;
+ }
+ m_src_x += subpixel_scale;
+ ++m_pos;
+ --m_len;
+ }
+
+ //----------------------------------------------------------------
+ void coordinates(int* x, int* y) const
+ {
+ *x = m_li_x.y();
+ *y = m_li_y.y();
+ }
+
+ private:
+ unsigned m_subdiv_shift;
+ unsigned m_subdiv_size;
+ unsigned m_subdiv_mask;
+ const trans_type* m_trans;
+ dda2_line_interpolator m_li_x;
+ dda2_line_interpolator m_li_y;
+ int m_src_x;
+ double m_src_y;
+ unsigned m_pos;
+ unsigned m_len;
+ };
+
+
+}
+
+
+
+#endif
+
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_interpolator_persp.h b/plugins/Clist_ng/AGG/include/agg_span_interpolator_persp.h new file mode 100644 index 0000000000..1d9863a433 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_interpolator_persp.h @@ -0,0 +1,472 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
+#define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
+
+#include "agg_trans_perspective.h"
+#include "agg_dda_line.h"
+
+namespace agg
+{
+
+
+
+ //===========================================span_interpolator_persp_exact
+ template<unsigned SubpixelShift = 8>
+ class span_interpolator_persp_exact
+ {
+ public:
+ typedef trans_perspective trans_type;
+ typedef trans_perspective::iterator_x iterator_type;
+ enum subpixel_scale_e
+ {
+ subpixel_shift = SubpixelShift,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_interpolator_persp_exact() {}
+
+ //--------------------------------------------------------------------
+ // Arbitrary quadrangle transformations
+ span_interpolator_persp_exact(const double* src, const double* dst)
+ {
+ quad_to_quad(src, dst);
+ }
+
+ //--------------------------------------------------------------------
+ // Direct transformations
+ span_interpolator_persp_exact(double x1, double y1,
+ double x2, double y2,
+ const double* quad)
+ {
+ rect_to_quad(x1, y1, x2, y2, quad);
+ }
+
+ //--------------------------------------------------------------------
+ // Reverse transformations
+ span_interpolator_persp_exact(const double* quad,
+ double x1, double y1,
+ double x2, double y2)
+ {
+ quad_to_rect(quad, x1, y1, x2, y2);
+ }
+
+ //--------------------------------------------------------------------
+ // Set the transformations using two arbitrary quadrangles.
+ void quad_to_quad(const double* src, const double* dst)
+ {
+ m_trans_dir.quad_to_quad(src, dst);
+ m_trans_inv.quad_to_quad(dst, src);
+ }
+
+ //--------------------------------------------------------------------
+ // Set the direct transformations, i.e., rectangle -> quadrangle
+ void rect_to_quad(double x1, double y1, double x2, double y2,
+ const double* quad)
+ {
+ double src[8];
+ src[0] = src[6] = x1;
+ src[2] = src[4] = x2;
+ src[1] = src[3] = y1;
+ src[5] = src[7] = y2;
+ quad_to_quad(src, quad);
+ }
+
+
+ //--------------------------------------------------------------------
+ // Set the reverse transformations, i.e., quadrangle -> rectangle
+ void quad_to_rect(const double* quad,
+ double x1, double y1, double x2, double y2)
+ {
+ double dst[8];
+ dst[0] = dst[6] = x1;
+ dst[2] = dst[4] = x2;
+ dst[1] = dst[3] = y1;
+ dst[5] = dst[7] = y2;
+ quad_to_quad(quad, dst);
+ }
+
+ //--------------------------------------------------------------------
+ // Check if the equations were solved successfully
+ bool is_valid() const { return m_trans_dir.is_valid(); }
+
+ //----------------------------------------------------------------
+ void begin(double x, double y, unsigned len)
+ {
+ m_iterator = m_trans_dir.begin(x, y, 1.0);
+ double xt = m_iterator.x;
+ double yt = m_iterator.y;
+
+ double dx;
+ double dy;
+ const double delta = 1/double(subpixel_scale);
+ dx = xt + delta;
+ dy = yt;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+ dx = xt;
+ dy = yt + delta;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ x += len;
+ xt = x;
+ yt = y;
+ m_trans_dir.transform(&xt, &yt);
+
+ dx = xt + delta;
+ dy = yt;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+ dx = xt;
+ dy = yt + delta;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ m_scale_x = dda2_line_interpolator(sx1, sx2, len);
+ m_scale_y = dda2_line_interpolator(sy1, sy2, len);
+ }
+
+
+ //----------------------------------------------------------------
+ void resynchronize(double xe, double ye, unsigned len)
+ {
+ // Assume x1,y1 are equal to the ones at the previous end point
+ int sx1 = m_scale_x.y();
+ int sy1 = m_scale_y.y();
+
+ // Calculate transformed coordinates at x2,y2
+ double xt = xe;
+ double yt = ye;
+ m_trans_dir.transform(&xt, &yt);
+
+ const double delta = 1/double(subpixel_scale);
+ double dx;
+ double dy;
+
+ // Calculate scale by X at x2,y2
+ dx = xt + delta;
+ dy = yt;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= xe;
+ dy -= ye;
+ int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Calculate scale by Y at x2,y2
+ dx = xt;
+ dy = yt + delta;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= xe;
+ dy -= ye;
+ int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Initialize the interpolators
+ m_scale_x = dda2_line_interpolator(sx1, sx2, len);
+ m_scale_y = dda2_line_interpolator(sy1, sy2, len);
+ }
+
+
+
+ //----------------------------------------------------------------
+ void operator++()
+ {
+ ++m_iterator;
+ ++m_scale_x;
+ ++m_scale_y;
+ }
+
+ //----------------------------------------------------------------
+ void coordinates(int* x, int* y) const
+ {
+ *x = iround(m_iterator.x * subpixel_scale);
+ *y = iround(m_iterator.y * subpixel_scale);
+ }
+
+ //----------------------------------------------------------------
+ void local_scale(int* x, int* y)
+ {
+ *x = m_scale_x.y();
+ *y = m_scale_y.y();
+ }
+
+ //----------------------------------------------------------------
+ void transform(double* x, double* y) const
+ {
+ m_trans_dir.transform(x, y);
+ }
+
+ private:
+ trans_type m_trans_dir;
+ trans_type m_trans_inv;
+ iterator_type m_iterator;
+ dda2_line_interpolator m_scale_x;
+ dda2_line_interpolator m_scale_y;
+ };
+
+
+
+
+
+
+
+
+
+
+
+ //============================================span_interpolator_persp_lerp
+ template<unsigned SubpixelShift = 8>
+ class span_interpolator_persp_lerp
+ {
+ public:
+ typedef trans_perspective trans_type;
+ enum subpixel_scale_e
+ {
+ subpixel_shift = SubpixelShift,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_interpolator_persp_lerp() {}
+
+ //--------------------------------------------------------------------
+ // Arbitrary quadrangle transformations
+ span_interpolator_persp_lerp(const double* src, const double* dst)
+ {
+ quad_to_quad(src, dst);
+ }
+
+ //--------------------------------------------------------------------
+ // Direct transformations
+ span_interpolator_persp_lerp(double x1, double y1,
+ double x2, double y2,
+ const double* quad)
+ {
+ rect_to_quad(x1, y1, x2, y2, quad);
+ }
+
+ //--------------------------------------------------------------------
+ // Reverse transformations
+ span_interpolator_persp_lerp(const double* quad,
+ double x1, double y1,
+ double x2, double y2)
+ {
+ quad_to_rect(quad, x1, y1, x2, y2);
+ }
+
+ //--------------------------------------------------------------------
+ // Set the transformations using two arbitrary quadrangles.
+ void quad_to_quad(const double* src, const double* dst)
+ {
+ m_trans_dir.quad_to_quad(src, dst);
+ m_trans_inv.quad_to_quad(dst, src);
+ }
+
+ //--------------------------------------------------------------------
+ // Set the direct transformations, i.e., rectangle -> quadrangle
+ void rect_to_quad(double x1, double y1, double x2, double y2,
+ const double* quad)
+ {
+ double src[8];
+ src[0] = src[6] = x1;
+ src[2] = src[4] = x2;
+ src[1] = src[3] = y1;
+ src[5] = src[7] = y2;
+ quad_to_quad(src, quad);
+ }
+
+
+ //--------------------------------------------------------------------
+ // Set the reverse transformations, i.e., quadrangle -> rectangle
+ void quad_to_rect(const double* quad,
+ double x1, double y1, double x2, double y2)
+ {
+ double dst[8];
+ dst[0] = dst[6] = x1;
+ dst[2] = dst[4] = x2;
+ dst[1] = dst[3] = y1;
+ dst[5] = dst[7] = y2;
+ quad_to_quad(quad, dst);
+ }
+
+ //--------------------------------------------------------------------
+ // Check if the equations were solved successfully
+ bool is_valid() const { return m_trans_dir.is_valid(); }
+
+ //----------------------------------------------------------------
+ void begin(double x, double y, unsigned len)
+ {
+ // Calculate transformed coordinates at x1,y1
+ double xt = x;
+ double yt = y;
+ m_trans_dir.transform(&xt, &yt);
+ int x1 = iround(xt * subpixel_scale);
+ int y1 = iround(yt * subpixel_scale);
+
+ double dx;
+ double dy;
+ const double delta = 1/double(subpixel_scale);
+
+ // Calculate scale by X at x1,y1
+ dx = xt + delta;
+ dy = yt;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Calculate scale by Y at x1,y1
+ dx = xt;
+ dy = yt + delta;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Calculate transformed coordinates at x2,y2
+ x += len;
+ xt = x;
+ yt = y;
+ m_trans_dir.transform(&xt, &yt);
+ int x2 = iround(xt * subpixel_scale);
+ int y2 = iround(yt * subpixel_scale);
+
+ // Calculate scale by X at x2,y2
+ dx = xt + delta;
+ dy = yt;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Calculate scale by Y at x2,y2
+ dx = xt;
+ dy = yt + delta;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= x;
+ dy -= y;
+ int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Initialize the interpolators
+ m_coord_x = dda2_line_interpolator(x1, x2, len);
+ m_coord_y = dda2_line_interpolator(y1, y2, len);
+ m_scale_x = dda2_line_interpolator(sx1, sx2, len);
+ m_scale_y = dda2_line_interpolator(sy1, sy2, len);
+ }
+
+
+ //----------------------------------------------------------------
+ void resynchronize(double xe, double ye, unsigned len)
+ {
+ // Assume x1,y1 are equal to the ones at the previous end point
+ int x1 = m_coord_x.y();
+ int y1 = m_coord_y.y();
+ int sx1 = m_scale_x.y();
+ int sy1 = m_scale_y.y();
+
+ // Calculate transformed coordinates at x2,y2
+ double xt = xe;
+ double yt = ye;
+ m_trans_dir.transform(&xt, &yt);
+ int x2 = iround(xt * subpixel_scale);
+ int y2 = iround(yt * subpixel_scale);
+
+ const double delta = 1/double(subpixel_scale);
+ double dx;
+ double dy;
+
+ // Calculate scale by X at x2,y2
+ dx = xt + delta;
+ dy = yt;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= xe;
+ dy -= ye;
+ int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Calculate scale by Y at x2,y2
+ dx = xt;
+ dy = yt + delta;
+ m_trans_inv.transform(&dx, &dy);
+ dx -= xe;
+ dy -= ye;
+ int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
+
+ // Initialize the interpolators
+ m_coord_x = dda2_line_interpolator(x1, x2, len);
+ m_coord_y = dda2_line_interpolator(y1, y2, len);
+ m_scale_x = dda2_line_interpolator(sx1, sx2, len);
+ m_scale_y = dda2_line_interpolator(sy1, sy2, len);
+ }
+
+
+ //----------------------------------------------------------------
+ void operator++()
+ {
+ ++m_coord_x;
+ ++m_coord_y;
+ ++m_scale_x;
+ ++m_scale_y;
+ }
+
+ //----------------------------------------------------------------
+ void coordinates(int* x, int* y) const
+ {
+ *x = m_coord_x.y();
+ *y = m_coord_y.y();
+ }
+
+ //----------------------------------------------------------------
+ void local_scale(int* x, int* y)
+ {
+ *x = m_scale_x.y();
+ *y = m_scale_y.y();
+ }
+
+ //----------------------------------------------------------------
+ void transform(double* x, double* y) const
+ {
+ m_trans_dir.transform(x, y);
+ }
+
+ private:
+ trans_type m_trans_dir;
+ trans_type m_trans_inv;
+ dda2_line_interpolator m_coord_x;
+ dda2_line_interpolator m_coord_y;
+ dda2_line_interpolator m_scale_x;
+ dda2_line_interpolator m_scale_y;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_interpolator_trans.h b/plugins/Clist_ng/AGG/include/agg_span_interpolator_trans.h new file mode 100644 index 0000000000..0de1c19dca --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_interpolator_trans.h @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Horizontal span interpolator for use with an arbitrary transformer
+// The efficiency highly depends on the operations done in the transformer
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
+#define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //=================================================span_interpolator_trans
+ template<class Transformer, unsigned SubpixelShift = 8>
+ class span_interpolator_trans
+ {
+ public:
+ typedef Transformer trans_type;
+ enum subpixel_scale_e
+ {
+ subpixel_shift = SubpixelShift,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+ //--------------------------------------------------------------------
+ span_interpolator_trans() {}
+ span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {}
+ span_interpolator_trans(const trans_type& trans,
+ double x, double y, unsigned) :
+ m_trans(&trans)
+ {
+ begin(x, y, 0);
+ }
+
+ //----------------------------------------------------------------
+ const trans_type& transformer() const { return *m_trans; }
+ void transformer(const trans_type& trans) { m_trans = &trans; }
+
+ //----------------------------------------------------------------
+ void begin(double x, double y, unsigned)
+ {
+ m_x = x;
+ m_y = y;
+ m_trans->transform(&x, &y);
+ m_ix = iround(x * subpixel_scale);
+ m_iy = iround(y * subpixel_scale);
+ }
+
+ //----------------------------------------------------------------
+ void operator++()
+ {
+ m_x += 1.0;
+ double x = m_x;
+ double y = m_y;
+ m_trans->transform(&x, &y);
+ m_ix = iround(x * subpixel_scale);
+ m_iy = iround(y * subpixel_scale);
+ }
+
+ //----------------------------------------------------------------
+ void coordinates(int* x, int* y) const
+ {
+ *x = m_ix;
+ *y = m_iy;
+ }
+
+ private:
+ const trans_type* m_trans;
+ double m_x;
+ double m_y;
+ int m_ix;
+ int m_iy;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_pattern_gray.h b/plugins/Clist_ng/AGG/include/agg_span_pattern_gray.h new file mode 100644 index 0000000000..72d2c27086 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_pattern_gray.h @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+
+#ifndef AGG_SPAN_PATTERN_GRAY_INCLUDED
+#define AGG_SPAN_PATTERN_GRAY_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //=======================================================span_pattern_gray
+ template<class Source> class span_pattern_gray
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+
+ //--------------------------------------------------------------------
+ span_pattern_gray() {}
+ span_pattern_gray(source_type& src,
+ unsigned offset_x, unsigned offset_y) :
+ m_src(&src),
+ m_offset_x(offset_x),
+ m_offset_y(offset_y),
+ m_alpha(color_type::base_mask)
+ {}
+
+ //--------------------------------------------------------------------
+ void attach(source_type& v) { m_src = &v; }
+ source_type& source() { return *m_src; }
+ const source_type& source() const { return *m_src; }
+
+ //--------------------------------------------------------------------
+ void offset_x(unsigned v) { m_offset_x = v; }
+ void offset_y(unsigned v) { m_offset_y = v; }
+ unsigned offset_x() const { return m_offset_x; }
+ unsigned offset_y() const { return m_offset_y; }
+ void alpha(value_type v) { m_alpha = v; }
+ value_type alpha() const { return m_alpha; }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ x += m_offset_x;
+ y += m_offset_y;
+ const value_type* p = (const value_type*)m_src->span(x, y, len);
+ do
+ {
+ span->v = *p;
+ span->a = m_alpha;
+ p = m_src->next_x();
+ ++span;
+ }
+ while(--len);
+ }
+
+ private:
+ source_type* m_src;
+ unsigned m_offset_x;
+ unsigned m_offset_y;
+ value_type m_alpha;
+
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_pattern_rgb.h b/plugins/Clist_ng/AGG/include/agg_span_pattern_rgb.h new file mode 100644 index 0000000000..a2e272f0b3 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_pattern_rgb.h @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+
+#ifndef AGG_SPAN_PATTERN_RGB_INCLUDED
+#define AGG_SPAN_PATTERN_RGB_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //========================================================span_pattern_rgb
+ template<class Source> class span_pattern_rgb
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+
+ //--------------------------------------------------------------------
+ span_pattern_rgb() {}
+ span_pattern_rgb(source_type& src,
+ unsigned offset_x, unsigned offset_y) :
+ m_src(&src),
+ m_offset_x(offset_x),
+ m_offset_y(offset_y),
+ m_alpha(color_type::base_mask)
+ {}
+
+ //--------------------------------------------------------------------
+ void attach(source_type& v) { m_src = &v; }
+ source_type& source() { return *m_src; }
+ const source_type& source() const { return *m_src; }
+
+ //--------------------------------------------------------------------
+ void offset_x(unsigned v) { m_offset_x = v; }
+ void offset_y(unsigned v) { m_offset_y = v; }
+ unsigned offset_x() const { return m_offset_x; }
+ unsigned offset_y() const { return m_offset_y; }
+ void alpha(value_type v) { m_alpha = v; }
+ value_type alpha() const { return m_alpha; }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ x += m_offset_x;
+ y += m_offset_y;
+ const value_type* p = (const value_type*)m_src->span(x, y, len);
+ do
+ {
+ span->r = p[order_type::R];
+ span->g = p[order_type::G];
+ span->b = p[order_type::B];
+ span->a = m_alpha;
+ p = m_src->next_x();
+ ++span;
+ }
+ while(--len);
+ }
+
+ private:
+ source_type* m_src;
+ unsigned m_offset_x;
+ unsigned m_offset_y;
+ value_type m_alpha;
+
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_pattern_rgba.h b/plugins/Clist_ng/AGG/include/agg_span_pattern_rgba.h new file mode 100644 index 0000000000..248ae265c7 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_pattern_rgba.h @@ -0,0 +1,103 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Adaptation for high precision colors has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+
+
+#ifndef AGG_SPAN_PATTERN_RGBA_INCLUDED
+#define AGG_SPAN_PATTERN_RGBA_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //======================================================span_pattern_rgba
+ template<class Source> class span_pattern_rgba
+ {
+ public:
+ typedef Source source_type;
+ typedef typename source_type::color_type color_type;
+ typedef typename source_type::order_type order_type;
+ typedef typename color_type::value_type value_type;
+ typedef typename color_type::calc_type calc_type;
+
+ //--------------------------------------------------------------------
+ span_pattern_rgba() {}
+ span_pattern_rgba(source_type& src,
+ unsigned offset_x, unsigned offset_y) :
+ m_src(&src),
+ m_offset_x(offset_x),
+ m_offset_y(offset_y)
+ {}
+
+ //--------------------------------------------------------------------
+ void attach(source_type& v) { m_src = &v; }
+ source_type& source() { return *m_src; }
+ const source_type& source() const { return *m_src; }
+
+ //--------------------------------------------------------------------
+ void offset_x(unsigned v) { m_offset_x = v; }
+ void offset_y(unsigned v) { m_offset_y = v; }
+ unsigned offset_x() const { return m_offset_x; }
+ unsigned offset_y() const { return m_offset_y; }
+ void alpha(value_type) {}
+ value_type alpha() const { return 0; }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ x += m_offset_x;
+ y += m_offset_y;
+ const value_type* p = (const value_type*)m_src->span(x, y, len);
+ do
+ {
+ span->r = p[order_type::R];
+ span->g = p[order_type::G];
+ span->b = p[order_type::B];
+ span->a = p[order_type::A];
+ p = (const value_type*)m_src->next_x();
+ ++span;
+ }
+ while(--len);
+ }
+
+ private:
+ source_type* m_src;
+ unsigned m_offset_x;
+ unsigned m_offset_y;
+
+ };
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_span_solid.h b/plugins/Clist_ng/AGG/include/agg_span_solid.h new file mode 100644 index 0000000000..f82f5dc2ce --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_solid.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_SOLID_INCLUDED
+#define AGG_SPAN_SOLID_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ //--------------------------------------------------------------span_solid
+ template<class ColorT> class span_solid
+ {
+ public:
+ typedef ColorT color_type;
+
+ //--------------------------------------------------------------------
+ void color(const color_type& c) { m_color = c; }
+ const color_type& color() const { return m_color; }
+
+ //--------------------------------------------------------------------
+ void prepare() {}
+
+ //--------------------------------------------------------------------
+ void generate(color_type* span, int x, int y, unsigned len)
+ {
+ do { *span++ = m_color; } while(--len);
+ }
+
+ private:
+ color_type m_color;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_span_subdiv_adaptor.h b/plugins/Clist_ng/AGG/include/agg_span_subdiv_adaptor.h new file mode 100644 index 0000000000..5edab67b68 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_span_subdiv_adaptor.h @@ -0,0 +1,151 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED
+#define AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //=================================================span_subdiv_adaptor
+ template<class Interpolator, unsigned SubpixelShift = 8>
+ class span_subdiv_adaptor
+ {
+ public:
+ typedef Interpolator interpolator_type;
+ typedef typename interpolator_type::trans_type trans_type;
+
+ enum sublixel_scale_e
+ {
+ subpixel_shift = SubpixelShift,
+ subpixel_scale = 1 << subpixel_shift
+ };
+
+
+ //----------------------------------------------------------------
+ span_subdiv_adaptor() :
+ m_subdiv_shift(4),
+ m_subdiv_size(1 << m_subdiv_shift),
+ m_subdiv_mask(m_subdiv_size - 1) {}
+
+ span_subdiv_adaptor(interpolator_type& interpolator,
+ unsigned subdiv_shift = 4) :
+ m_subdiv_shift(subdiv_shift),
+ m_subdiv_size(1 << m_subdiv_shift),
+ m_subdiv_mask(m_subdiv_size - 1),
+ m_interpolator(&interpolator) {}
+
+ span_subdiv_adaptor(interpolator_type& interpolator,
+ double x, double y, unsigned len,
+ unsigned subdiv_shift = 4) :
+ m_subdiv_shift(subdiv_shift),
+ m_subdiv_size(1 << m_subdiv_shift),
+ m_subdiv_mask(m_subdiv_size - 1),
+ m_interpolator(&interpolator)
+ {
+ begin(x, y, len);
+ }
+
+
+ //----------------------------------------------------------------
+ const interpolator_type& interpolator() const { return *m_interpolator; }
+ void interpolator(interpolator_type& intr) { m_interpolator = &intr; }
+
+ //----------------------------------------------------------------
+ const trans_type& transformer() const
+ {
+ return *m_interpolator->transformer();
+ }
+ void transformer(const trans_type& trans)
+ {
+ m_interpolator->transformer(trans);
+ }
+
+ //----------------------------------------------------------------
+ unsigned subdiv_shift() const { return m_subdiv_shift; }
+ void subdiv_shift(unsigned shift)
+ {
+ m_subdiv_shift = shift;
+ m_subdiv_size = 1 << m_subdiv_shift;
+ m_subdiv_mask = m_subdiv_size - 1;
+ }
+
+ //----------------------------------------------------------------
+ void begin(double x, double y, unsigned len)
+ {
+ m_pos = 1;
+ m_src_x = iround(x * subpixel_scale) + subpixel_scale;
+ m_src_y = y;
+ m_len = len;
+ if(len > m_subdiv_size) len = m_subdiv_size;
+ m_interpolator->begin(x, y, len);
+ }
+
+ //----------------------------------------------------------------
+ void operator++()
+ {
+ ++(*m_interpolator);
+ if(m_pos >= m_subdiv_size)
+ {
+ unsigned len = m_len;
+ if(len > m_subdiv_size) len = m_subdiv_size;
+ m_interpolator->resynchronize(double(m_src_x) / double(subpixel_scale) + len,
+ m_src_y,
+ len);
+ m_pos = 0;
+ }
+ m_src_x += subpixel_scale;
+ ++m_pos;
+ --m_len;
+ }
+
+ //----------------------------------------------------------------
+ void coordinates(int* x, int* y) const
+ {
+ m_interpolator->coordinates(x, y);
+ }
+
+ //----------------------------------------------------------------
+ void local_scale(int* x, int* y) const
+ {
+ m_interpolator->local_scale(x, y);
+ }
+
+
+ private:
+ unsigned m_subdiv_shift;
+ unsigned m_subdiv_size;
+ unsigned m_subdiv_mask;
+ interpolator_type* m_interpolator;
+ int m_src_x;
+ double m_src_y;
+ unsigned m_pos;
+ unsigned m_len;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_trans_affine.h b/plugins/Clist_ng/AGG/include/agg_trans_affine.h new file mode 100644 index 0000000000..a9d2bd0a34 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_trans_affine.h @@ -0,0 +1,524 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_TRANS_AFFINE_INCLUDED
+#define AGG_TRANS_AFFINE_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+ const double affine_epsilon = 1e-14;
+
+ //============================================================trans_affine
+ //
+ // See Implementation agg_trans_affine.cpp
+ //
+ // Affine transformation are linear transformations in Cartesian coordinates
+ // (strictly speaking not only in Cartesian, but for the beginning we will
+ // think so). They are rotation, scaling, translation and skewing.
+ // After any affine transformation a line segment remains a line segment
+ // and it will never become a curve.
+ //
+ // There will be no math about matrix calculations, since it has been
+ // described many times. Ask yourself a very simple question:
+ // "why do we need to understand and use some matrix stuff instead of just
+ // rotating, scaling and so on". The answers are:
+ //
+ // 1. Any combination of transformations can be done by only 4 multiplications
+ // and 4 additions in floating point.
+ // 2. One matrix transformation is equivalent to the number of consecutive
+ // discrete transformations, i.e. the matrix "accumulates" all transformations
+ // in the order of their settings. Suppose we have 4 transformations:
+ // * rotate by 30 degrees,
+ // * scale X to 2.0,
+ // * scale Y to 1.5,
+ // * move to (100, 100).
+ // The result will depend on the order of these transformations,
+ // and the advantage of matrix is that the sequence of discret calls:
+ // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100)
+ // will have exactly the same result as the following matrix transformations:
+ //
+ // affine_matrix m;
+ // m *= rotate_matrix(30);
+ // m *= scaleX_matrix(2.0);
+ // m *= scaleY_matrix(1.5);
+ // m *= move_matrix(100,100);
+ //
+ // m.transform_my_point_at_last(x, y);
+ //
+ // What is the good of it? In real life we will set-up the matrix only once
+ // and then transform many points, let alone the convenience to set any
+ // combination of transformations.
+ //
+ // So, how to use it? Very easy - literally as it's shown above. Not quite,
+ // let us write a correct example:
+ //
+ // agg::trans_affine m;
+ // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
+ // m *= agg::trans_affine_scaling(2.0, 1.5);
+ // m *= agg::trans_affine_translation(100.0, 100.0);
+ // m.transform(&x, &y);
+ //
+ // The affine matrix is all you need to perform any linear transformation,
+ // but all transformations have origin point (0,0). It means that we need to
+ // use 2 translations if we want to rotate someting around (100,100):
+ //
+ // m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0)
+ // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
+ // m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
+ //----------------------------------------------------------------------
+ struct trans_affine
+ {
+ double sx, shy, shx, sy, tx, ty;
+
+ //------------------------------------------ Construction
+ // Identity matrix
+ trans_affine() :
+ sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0)
+ {}
+
+ // Custom matrix. Usually used in derived classes
+ trans_affine(double v0, double v1, double v2,
+ double v3, double v4, double v5) :
+ sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5)
+ {}
+
+ // Custom matrix from m[6]
+ explicit trans_affine(const double* m) :
+ sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5])
+ {}
+
+ // Rectangle to a parallelogram.
+ trans_affine(double x1, double y1, double x2, double y2,
+ const double* parl)
+ {
+ rect_to_parl(x1, y1, x2, y2, parl);
+ }
+
+ // Parallelogram to a rectangle.
+ trans_affine(const double* parl,
+ double x1, double y1, double x2, double y2)
+ {
+ parl_to_rect(parl, x1, y1, x2, y2);
+ }
+
+ // Arbitrary parallelogram transformation.
+ trans_affine(const double* src, const double* dst)
+ {
+ parl_to_parl(src, dst);
+ }
+
+ //---------------------------------- Parellelogram transformations
+ // transform a parallelogram to another one. Src and dst are
+ // pointers to arrays of three points (double[6], x1,y1,...) that
+ // identify three corners of the parallelograms assuming implicit
+ // fourth point. The arguments are arrays of double[6] mapped
+ // to x1,y1, x2,y2, x3,y3 where the coordinates are:
+ // *-----------------*
+ // / (x3,y3)/
+ // / /
+ // /(x1,y1) (x2,y2)/
+ // *-----------------*
+ const trans_affine& parl_to_parl(const double* src,
+ const double* dst);
+
+ const trans_affine& rect_to_parl(double x1, double y1,
+ double x2, double y2,
+ const double* parl);
+
+ const trans_affine& parl_to_rect(const double* parl,
+ double x1, double y1,
+ double x2, double y2);
+
+
+ //------------------------------------------ Operations
+ // Reset - load an identity matrix
+ const trans_affine& reset();
+
+ // Direct transformations operations
+ const trans_affine& translate(double x, double y);
+ const trans_affine& rotate(double a);
+ const trans_affine& scale(double s);
+ const trans_affine& scale(double x, double y);
+
+ // Multiply matrix to another one
+ const trans_affine& multiply(const trans_affine& m);
+
+ // Multiply "m" to "this" and assign the result to "this"
+ const trans_affine& premultiply(const trans_affine& m);
+
+ // Multiply matrix to inverse of another one
+ const trans_affine& multiply_inv(const trans_affine& m);
+
+ // Multiply inverse of "m" to "this" and assign the result to "this"
+ const trans_affine& premultiply_inv(const trans_affine& m);
+
+ // Invert matrix. Do not try to invert degenerate matrices,
+ // there's no check for validity. If you set scale to 0 and
+ // then try to invert matrix, expect unpredictable result.
+ const trans_affine& invert();
+
+ // Mirroring around X
+ const trans_affine& flip_x();
+
+ // Mirroring around Y
+ const trans_affine& flip_y();
+
+ //------------------------------------------- Load/Store
+ // Store matrix to an array [6] of double
+ void store_to(double* m) const
+ {
+ *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty;
+ }
+
+ // Load matrix from an array [6] of double
+ const trans_affine& load_from(const double* m)
+ {
+ sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++;
+ return *this;
+ }
+
+ //------------------------------------------- Operators
+
+ // Multiply the matrix by another one
+ const trans_affine& operator *= (const trans_affine& m)
+ {
+ return multiply(m);
+ }
+
+ // Multiply the matrix by inverse of another one
+ const trans_affine& operator /= (const trans_affine& m)
+ {
+ return multiply_inv(m);
+ }
+
+ // Multiply the matrix by another one and return
+ // the result in a separete matrix.
+ trans_affine operator * (const trans_affine& m)
+ {
+ return trans_affine(*this).multiply(m);
+ }
+
+ // Multiply the matrix by inverse of another one
+ // and return the result in a separete matrix.
+ trans_affine operator / (const trans_affine& m)
+ {
+ return trans_affine(*this).multiply_inv(m);
+ }
+
+ // Calculate and return the inverse matrix
+ trans_affine operator ~ () const
+ {
+ trans_affine ret = *this;
+ return ret.invert();
+ }
+
+ // Equal operator with default epsilon
+ bool operator == (const trans_affine& m) const
+ {
+ return is_equal(m, affine_epsilon);
+ }
+
+ // Not Equal operator with default epsilon
+ bool operator != (const trans_affine& m) const
+ {
+ return !is_equal(m, affine_epsilon);
+ }
+
+ //-------------------------------------------- Transformations
+ // Direct transformation of x and y
+ void transform(double* x, double* y) const;
+
+ // Direct transformation of x and y, 2x2 matrix only, no translation
+ void transform_2x2(double* x, double* y) const;
+
+ // Inverse transformation of x and y. It works slower than the
+ // direct transformation. For massive operations it's better to
+ // invert() the matrix and then use direct transformations.
+ void inverse_transform(double* x, double* y) const;
+
+ //-------------------------------------------- Auxiliary
+ // Calculate the determinant of matrix
+ double determinant() const
+ {
+ return sx * sy - shy * shx;
+ }
+
+ // Calculate the reciprocal of the determinant
+ double determinant_reciprocal() const
+ {
+ return 1.0 / (sx * sy - shy * shx);
+ }
+
+ // Get the average scale (by X and Y).
+ // Basically used to calculate the approximation_scale when
+ // decomposinting curves into line segments.
+ double scale() const;
+
+ // Check to see if the matrix is not degenerate
+ bool is_valid(double epsilon = affine_epsilon) const;
+
+ // Check to see if it's an identity matrix
+ bool is_identity(double epsilon = affine_epsilon) const;
+
+ // Check to see if two matrices are equal
+ bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
+
+ // Determine the major parameters. Use with caution considering
+ // possible degenerate cases.
+ double rotation() const;
+ void translation(double* dx, double* dy) const;
+ void scaling(double* x, double* y) const;
+ void scaling_abs(double* x, double* y) const;
+ };
+
+ //------------------------------------------------------------------------
+ inline void trans_affine::transform(double* x, double* y) const
+ {
+ register double tmp = *x;
+ *x = tmp * sx + *y * shx + tx;
+ *y = tmp * shy + *y * sy + ty;
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_affine::transform_2x2(double* x, double* y) const
+ {
+ register double tmp = *x;
+ *x = tmp * sx + *y * shx;
+ *y = tmp * shy + *y * sy;
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_affine::inverse_transform(double* x, double* y) const
+ {
+ register double d = determinant_reciprocal();
+ register double a = (*x - tx) * d;
+ register double b = (*y - ty) * d;
+ *x = a * sy - b * shx;
+ *y = b * sx - a * shy;
+ }
+
+ //------------------------------------------------------------------------
+ inline double trans_affine::scale() const
+ {
+ double x = 0.707106781 * sx + 0.707106781 * shx;
+ double y = 0.707106781 * shy + 0.707106781 * sy;
+ return sqrt(x*x + y*y);
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_affine& trans_affine::translate(double x, double y)
+ {
+ tx += x;
+ ty += y;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_affine& trans_affine::rotate(double a)
+ {
+ double ca = cos(a);
+ double sa = sin(a);
+ double t0 = sx * ca - shy * sa;
+ double t2 = shx * ca - sy * sa;
+ double t4 = tx * ca - ty * sa;
+ shy = sx * sa + shy * ca;
+ sy = shx * sa + sy * ca;
+ ty = tx * sa + ty * ca;
+ sx = t0;
+ shx = t2;
+ tx = t4;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_affine& trans_affine::scale(double x, double y)
+ {
+ double mm0 = x; // Possible hint for the optimizer
+ double mm3 = y;
+ sx *= mm0;
+ shx *= mm0;
+ tx *= mm0;
+ shy *= mm3;
+ sy *= mm3;
+ ty *= mm3;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_affine& trans_affine::scale(double s)
+ {
+ double m = s; // Possible hint for the optimizer
+ sx *= m;
+ shx *= m;
+ tx *= m;
+ shy *= m;
+ sy *= m;
+ ty *= m;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
+ {
+ trans_affine t = m;
+ return *this = t.multiply(*this);
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m)
+ {
+ trans_affine t = m;
+ t.invert();
+ return multiply(t);
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m)
+ {
+ trans_affine t = m;
+ t.invert();
+ return *this = t.multiply(*this);
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_affine::scaling_abs(double* x, double* y) const
+ {
+ // Used to calculate scaling coefficients in image resampling.
+ // When there is considerable shear this method gives us much
+ // better estimation than just sx, sy.
+ *x = sqrt(sx * sx + shx * shx);
+ *y = sqrt(shy * shy + sy * sy);
+ }
+
+ //====================================================trans_affine_rotation
+ // Rotation matrix. sin() and cos() are calculated twice for the same angle.
+ // There's no harm because the performance of sin()/cos() is very good on all
+ // modern processors. Besides, this operation is not going to be invoked too
+ // often.
+ class trans_affine_rotation : public trans_affine
+ {
+ public:
+ trans_affine_rotation(double a) :
+ trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0)
+ {}
+ };
+
+ //====================================================trans_affine_scaling
+ // Scaling matrix. x, y - scale coefficients by X and Y respectively
+ class trans_affine_scaling : public trans_affine
+ {
+ public:
+ trans_affine_scaling(double x, double y) :
+ trans_affine(x, 0.0, 0.0, y, 0.0, 0.0)
+ {}
+
+ trans_affine_scaling(double s) :
+ trans_affine(s, 0.0, 0.0, s, 0.0, 0.0)
+ {}
+ };
+
+ //================================================trans_affine_translation
+ // Translation matrix
+ class trans_affine_translation : public trans_affine
+ {
+ public:
+ trans_affine_translation(double x, double y) :
+ trans_affine(1.0, 0.0, 0.0, 1.0, x, y)
+ {}
+ };
+
+ //====================================================trans_affine_skewing
+ // Sckewing (shear) matrix
+ class trans_affine_skewing : public trans_affine
+ {
+ public:
+ trans_affine_skewing(double x, double y) :
+ trans_affine(1.0, tan(y), tan(x), 1.0, 0.0, 0.0)
+ {}
+ };
+
+
+ //===============================================trans_affine_line_segment
+ // Rotate, Scale and Translate, associating 0...dist with line segment
+ // x1,y1,x2,y2
+ class trans_affine_line_segment : public trans_affine
+ {
+ public:
+ trans_affine_line_segment(double x1, double y1, double x2, double y2,
+ double dist)
+ {
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+ if(dist > 0.0)
+ {
+ multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist));
+ }
+ multiply(trans_affine_rotation(atan2(dy, dx)));
+ multiply(trans_affine_translation(x1, y1));
+ }
+ };
+
+
+ //============================================trans_affine_reflection_unit
+ // Reflection matrix. Reflect coordinates across the line through
+ // the origin containing the unit vector (ux, uy).
+ // Contributed by John Horigan
+ class trans_affine_reflection_unit : public trans_affine
+ {
+ public:
+ trans_affine_reflection_unit(double ux, double uy) :
+ trans_affine(2.0 * ux * ux - 1.0,
+ 2.0 * ux * uy,
+ 2.0 * ux * uy,
+ 2.0 * uy * uy - 1.0,
+ 0.0, 0.0)
+ {}
+ };
+
+
+ //=================================================trans_affine_reflection
+ // Reflection matrix. Reflect coordinates across the line through
+ // the origin at the angle a or containing the non-unit vector (x, y).
+ // Contributed by John Horigan
+ class trans_affine_reflection : public trans_affine_reflection_unit
+ {
+ public:
+ trans_affine_reflection(double a) :
+ trans_affine_reflection_unit(cos(a), sin(a))
+ {}
+
+
+ trans_affine_reflection(double x, double y) :
+ trans_affine_reflection_unit(x / sqrt(x * x + y * y), y / sqrt(x * x + y * y))
+ {}
+ };
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_trans_bilinear.h b/plugins/Clist_ng/AGG/include/agg_trans_bilinear.h new file mode 100644 index 0000000000..215026224d --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_trans_bilinear.h @@ -0,0 +1,172 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_TRANS_BILINEAR_INCLUDED
+#define AGG_TRANS_BILINEAR_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_simul_eq.h"
+
+namespace agg
+{
+
+ //==========================================================trans_bilinear
+ class trans_bilinear
+ {
+ public:
+ //--------------------------------------------------------------------
+ trans_bilinear() : m_valid(false) {}
+
+ //--------------------------------------------------------------------
+ // Arbitrary quadrangle transformations
+ trans_bilinear(const double* src, const double* dst)
+ {
+ quad_to_quad(src, dst);
+ }
+
+
+ //--------------------------------------------------------------------
+ // Direct transformations
+ trans_bilinear(double x1, double y1, double x2, double y2,
+ const double* quad)
+ {
+ rect_to_quad(x1, y1, x2, y2, quad);
+ }
+
+
+ //--------------------------------------------------------------------
+ // Reverse transformations
+ trans_bilinear(const double* quad,
+ double x1, double y1, double x2, double y2)
+ {
+ quad_to_rect(quad, x1, y1, x2, y2);
+ }
+
+
+ //--------------------------------------------------------------------
+ // Set the transformations using two arbitrary quadrangles.
+ void quad_to_quad(const double* src, const double* dst)
+ {
+ double left[4][4];
+ double right[4][2];
+
+ unsigned i;
+ for(i = 0; i < 4; i++)
+ {
+ unsigned ix = i * 2;
+ unsigned iy = ix + 1;
+ left[i][0] = 1.0;
+ left[i][1] = src[ix] * src[iy];
+ left[i][2] = src[ix];
+ left[i][3] = src[iy];
+
+ right[i][0] = dst[ix];
+ right[i][1] = dst[iy];
+ }
+ m_valid = simul_eq<4, 2>::solve(left, right, m_mtx);
+ }
+
+
+ //--------------------------------------------------------------------
+ // Set the direct transformations, i.e., rectangle -> quadrangle
+ void rect_to_quad(double x1, double y1, double x2, double y2,
+ const double* quad)
+ {
+ double src[8];
+ src[0] = src[6] = x1;
+ src[2] = src[4] = x2;
+ src[1] = src[3] = y1;
+ src[5] = src[7] = y2;
+ quad_to_quad(src, quad);
+ }
+
+
+ //--------------------------------------------------------------------
+ // Set the reverse transformations, i.e., quadrangle -> rectangle
+ void quad_to_rect(const double* quad,
+ double x1, double y1, double x2, double y2)
+ {
+ double dst[8];
+ dst[0] = dst[6] = x1;
+ dst[2] = dst[4] = x2;
+ dst[1] = dst[3] = y1;
+ dst[5] = dst[7] = y2;
+ quad_to_quad(quad, dst);
+ }
+
+ //--------------------------------------------------------------------
+ // Check if the equations were solved successfully
+ bool is_valid() const { return m_valid; }
+
+ //--------------------------------------------------------------------
+ // Transform a point (x, y)
+ void transform(double* x, double* y) const
+ {
+ double tx = *x;
+ double ty = *y;
+ double xy = tx * ty;
+ *x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty;
+ *y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty;
+ }
+
+
+ //--------------------------------------------------------------------
+ class iterator_x
+ {
+ double inc_x;
+ double inc_y;
+
+ public:
+ double x;
+ double y;
+
+ iterator_x() {}
+ iterator_x(double tx, double ty, double step, const double m[4][2]) :
+ inc_x(m[1][0] * step * ty + m[2][0] * step),
+ inc_y(m[1][1] * step * ty + m[2][1] * step),
+ x(m[0][0] + m[1][0] * tx * ty + m[2][0] * tx + m[3][0] * ty),
+ y(m[0][1] + m[1][1] * tx * ty + m[2][1] * tx + m[3][1] * ty)
+ {
+ }
+
+ void operator ++ ()
+ {
+ x += inc_x;
+ y += inc_y;
+ }
+ };
+
+ iterator_x begin(double x, double y, double step) const
+ {
+ return iterator_x(x, y, step, m_mtx);
+ }
+
+ private:
+ double m_mtx[4][2];
+ bool m_valid;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_trans_double_path.h b/plugins/Clist_ng/AGG/include/agg_trans_double_path.h new file mode 100644 index 0000000000..736e921b77 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_trans_double_path.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_TRANS_DOUBLE_PATH_INCLUDED
+#define AGG_TRANS_DOUBLE_PATH_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vertex_sequence.h"
+
+namespace agg
+{
+
+ // See also: agg_trans_double_path.cpp
+ //
+ //-------------------------------------------------------trans_double_path
+ class trans_double_path
+ {
+ enum status_e
+ {
+ initial,
+ making_path,
+ ready
+ };
+
+ public:
+ typedef vertex_sequence<vertex_dist, 6> vertex_storage;
+
+ trans_double_path();
+
+ //--------------------------------------------------------------------
+ void base_length(double v) { m_base_length = v; }
+ double base_length() const { return m_base_length; }
+
+ //--------------------------------------------------------------------
+ void base_height(double v) { m_base_height = v; }
+ double base_height() const { return m_base_height; }
+
+ //--------------------------------------------------------------------
+ void preserve_x_scale(bool f) { m_preserve_x_scale = f; }
+ bool preserve_x_scale() const { return m_preserve_x_scale; }
+
+ //--------------------------------------------------------------------
+ void reset();
+ void move_to1(double x, double y);
+ void line_to1(double x, double y);
+ void move_to2(double x, double y);
+ void line_to2(double x, double y);
+ void finalize_paths();
+
+ //--------------------------------------------------------------------
+ template<class VertexSource1, class VertexSource2>
+ void add_paths(VertexSource1& vs1, VertexSource2& vs2,
+ unsigned path1_id=0, unsigned path2_id=0)
+ {
+ double x;
+ double y;
+
+ unsigned cmd;
+
+ vs1.rewind(path1_id);
+ while(!is_stop(cmd = vs1.vertex(&x, &y)))
+ {
+ if(is_move_to(cmd))
+ {
+ move_to1(x, y);
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ line_to1(x, y);
+ }
+ }
+ }
+
+ vs2.rewind(path2_id);
+ while(!is_stop(cmd = vs2.vertex(&x, &y)))
+ {
+ if(is_move_to(cmd))
+ {
+ move_to2(x, y);
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ line_to2(x, y);
+ }
+ }
+ }
+ finalize_paths();
+ }
+
+ //--------------------------------------------------------------------
+ double total_length1() const;
+ double total_length2() const;
+ void transform(double *x, double *y) const;
+
+ private:
+ double finalize_path(vertex_storage& vertices);
+ void transform1(const vertex_storage& vertices,
+ double kindex, double kx,
+ double *x, double* y) const;
+
+ vertex_storage m_src_vertices1;
+ vertex_storage m_src_vertices2;
+ double m_base_length;
+ double m_base_height;
+ double m_kindex1;
+ double m_kindex2;
+ status_e m_status1;
+ status_e m_status2;
+ bool m_preserve_x_scale;
+ };
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_trans_perspective.h b/plugins/Clist_ng/AGG/include/agg_trans_perspective.h new file mode 100644 index 0000000000..48b9ac8aff --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_trans_perspective.h @@ -0,0 +1,737 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED
+#define AGG_TRANS_PERSPECTIVE_INCLUDED
+
+#include "agg_trans_affine.h"
+
+namespace agg
+{
+ //=======================================================trans_perspective
+ struct trans_perspective
+ {
+ double sx, shy, w0, shx, sy, w1, tx, ty, w2;
+
+ //------------------------------------------------------- Construction
+ // Identity matrix
+ trans_perspective() :
+ sx (1), shy(0), w0(0),
+ shx(0), sy (1), w1(0),
+ tx (0), ty (0), w2(1) {}
+
+ // Custom matrix
+ trans_perspective(double v0, double v1, double v2,
+ double v3, double v4, double v5,
+ double v6, double v7, double v8) :
+ sx (v0), shy(v1), w0(v2),
+ shx(v3), sy (v4), w1(v5),
+ tx (v6), ty (v7), w2(v8) {}
+
+ // Custom matrix from m[9]
+ explicit trans_perspective(const double* m) :
+ sx (m[0]), shy(m[1]), w0(m[2]),
+ shx(m[3]), sy (m[4]), w1(m[5]),
+ tx (m[6]), ty (m[7]), w2(m[8]) {}
+
+ // From affine
+ explicit trans_perspective(const trans_affine& a) :
+ sx (a.sx ), shy(a.shy), w0(0),
+ shx(a.shx), sy (a.sy ), w1(0),
+ tx (a.tx ), ty (a.ty ), w2(1) {}
+
+ // Rectangle to quadrilateral
+ trans_perspective(double x1, double y1, double x2, double y2,
+ const double* quad);
+
+ // Quadrilateral to rectangle
+ trans_perspective(const double* quad,
+ double x1, double y1, double x2, double y2);
+
+ // Arbitrary quadrilateral transformations
+ trans_perspective(const double* src, const double* dst);
+
+ //-------------------------------------- Quadrilateral transformations
+ // The arguments are double[8] that are mapped to quadrilaterals:
+ // x1,y1, x2,y2, x3,y3, x4,y4
+ bool quad_to_quad(const double* qs, const double* qd);
+
+ bool rect_to_quad(double x1, double y1,
+ double x2, double y2,
+ const double* q);
+
+ bool quad_to_rect(const double* q,
+ double x1, double y1,
+ double x2, double y2);
+
+ // Map square (0,0,1,1) to the quadrilateral and vice versa
+ bool square_to_quad(const double* q);
+ bool quad_to_square(const double* q);
+
+
+ //--------------------------------------------------------- Operations
+ // Reset - load an identity matrix
+ const trans_perspective& reset();
+
+ // Invert matrix. Returns false in degenerate case
+ bool invert();
+
+ // Direct transformations operations
+ const trans_perspective& translate(double x, double y);
+ const trans_perspective& rotate(double a);
+ const trans_perspective& scale(double s);
+ const trans_perspective& scale(double x, double y);
+
+ // Multiply the matrix by another one
+ const trans_perspective& multiply(const trans_perspective& m);
+
+ // Multiply "m" by "this" and assign the result to "this"
+ const trans_perspective& premultiply(const trans_perspective& m);
+
+ // Multiply matrix to inverse of another one
+ const trans_perspective& multiply_inv(const trans_perspective& m);
+
+ // Multiply inverse of "m" by "this" and assign the result to "this"
+ const trans_perspective& premultiply_inv(const trans_perspective& m);
+
+ // Multiply the matrix by another one
+ const trans_perspective& multiply(const trans_affine& m);
+
+ // Multiply "m" by "this" and assign the result to "this"
+ const trans_perspective& premultiply(const trans_affine& m);
+
+ // Multiply the matrix by inverse of another one
+ const trans_perspective& multiply_inv(const trans_affine& m);
+
+ // Multiply inverse of "m" by "this" and assign the result to "this"
+ const trans_perspective& premultiply_inv(const trans_affine& m);
+
+ //--------------------------------------------------------- Load/Store
+ void store_to(double* m) const;
+ const trans_perspective& load_from(const double* m);
+
+ //---------------------------------------------------------- Operators
+ // Multiply the matrix by another one
+ const trans_perspective& operator *= (const trans_perspective& m)
+ {
+ return multiply(m);
+ }
+ const trans_perspective& operator *= (const trans_affine& m)
+ {
+ return multiply(m);
+ }
+
+ // Multiply the matrix by inverse of another one
+ const trans_perspective& operator /= (const trans_perspective& m)
+ {
+ return multiply_inv(m);
+ }
+ const trans_perspective& operator /= (const trans_affine& m)
+ {
+ return multiply_inv(m);
+ }
+
+ // Multiply the matrix by another one and return
+ // the result in a separete matrix.
+ trans_perspective operator * (const trans_perspective& m)
+ {
+ return trans_perspective(*this).multiply(m);
+ }
+ trans_perspective operator * (const trans_affine& m)
+ {
+ return trans_perspective(*this).multiply(m);
+ }
+
+ // Multiply the matrix by inverse of another one
+ // and return the result in a separete matrix.
+ trans_perspective operator / (const trans_perspective& m)
+ {
+ return trans_perspective(*this).multiply_inv(m);
+ }
+ trans_perspective operator / (const trans_affine& m)
+ {
+ return trans_perspective(*this).multiply_inv(m);
+ }
+
+ // Calculate and return the inverse matrix
+ trans_perspective operator ~ () const
+ {
+ trans_perspective ret = *this;
+ ret.invert();
+ return ret;
+ }
+
+ // Equal operator with default epsilon
+ bool operator == (const trans_perspective& m) const
+ {
+ return is_equal(m, affine_epsilon);
+ }
+
+ // Not Equal operator with default epsilon
+ bool operator != (const trans_perspective& m) const
+ {
+ return !is_equal(m, affine_epsilon);
+ }
+
+ //---------------------------------------------------- Transformations
+ // Direct transformation of x and y
+ void transform(double* x, double* y) const;
+
+ // Direct transformation of x and y, affine part only
+ void transform_affine(double* x, double* y) const;
+
+ // Direct transformation of x and y, 2x2 matrix only, no translation
+ void transform_2x2(double* x, double* y) const;
+
+ // Inverse transformation of x and y. It works slow because
+ // it explicitly inverts the matrix on every call. For massive
+ // operations it's better to invert() the matrix and then use
+ // direct transformations.
+ void inverse_transform(double* x, double* y) const;
+
+
+ //---------------------------------------------------------- Auxiliary
+ const trans_perspective& from_affine(const trans_affine& a);
+ double determinant() const;
+ double determinant_reciprocal() const;
+
+ bool is_valid(double epsilon = affine_epsilon) const;
+ bool is_identity(double epsilon = affine_epsilon) const;
+ bool is_equal(const trans_perspective& m,
+ double epsilon = affine_epsilon) const;
+
+ // Determine the major affine parameters. Use with caution
+ // considering possible degenerate cases.
+ double scale() const;
+ double rotation() const;
+ void translation(double* dx, double* dy) const;
+ void scaling(double* x, double* y) const;
+ void scaling_abs(double* x, double* y) const;
+
+
+
+ //--------------------------------------------------------------------
+ class iterator_x
+ {
+ double den;
+ double den_step;
+ double nom_x;
+ double nom_x_step;
+ double nom_y;
+ double nom_y_step;
+
+ public:
+ double x;
+ double y;
+
+ iterator_x() {}
+ iterator_x(double px, double py, double step, const trans_perspective& m) :
+ den(px * m.w0 + py * m.w1 + m.w2),
+ den_step(m.w0 * step),
+ nom_x(px * m.sx + py * m.shx + m.tx),
+ nom_x_step(step * m.sx),
+ nom_y(px * m.shy + py * m.sy + m.ty),
+ nom_y_step(step * m.shy),
+ x(nom_x / den),
+ y(nom_y / den)
+ {}
+
+ void operator ++ ()
+ {
+ den += den_step;
+ nom_x += nom_x_step;
+ nom_y += nom_y_step;
+ double d = 1.0 / den;
+ x = nom_x * d;
+ y = nom_y * d;
+ }
+ };
+
+ //--------------------------------------------------------------------
+ iterator_x begin(double x, double y, double step) const
+ {
+ return iterator_x(x, y, step, *this);
+ }
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::square_to_quad(const double* q)
+ {
+ double dx = q[0] - q[2] + q[4] - q[6];
+ double dy = q[1] - q[3] + q[5] - q[7];
+ if(dx == 0.0 && dy == 0.0)
+ {
+ // Affine case (parallelogram)
+ //---------------
+ sx = q[2] - q[0];
+ shy = q[3] - q[1];
+ w0 = 0.0;
+ shx = q[4] - q[2];
+ sy = q[5] - q[3];
+ w1 = 0.0;
+ tx = q[0];
+ ty = q[1];
+ w2 = 1.0;
+ }
+ else
+ {
+ double dx1 = q[2] - q[4];
+ double dy1 = q[3] - q[5];
+ double dx2 = q[6] - q[4];
+ double dy2 = q[7] - q[5];
+ double den = dx1 * dy2 - dx2 * dy1;
+ if(den == 0.0)
+ {
+ // Singular case
+ //---------------
+ sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
+ return false;
+ }
+ // General case
+ //---------------
+ double u = (dx * dy2 - dy * dx2) / den;
+ double v = (dy * dx1 - dx * dy1) / den;
+ sx = q[2] - q[0] + u * q[2];
+ shy = q[3] - q[1] + u * q[3];
+ w0 = u;
+ shx = q[6] - q[0] + v * q[6];
+ sy = q[7] - q[1] + v * q[7];
+ w1 = v;
+ tx = q[0];
+ ty = q[1];
+ w2 = 1.0;
+ }
+ return true;
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::invert()
+ {
+ double d0 = sy * w2 - w1 * ty;
+ double d1 = w0 * ty - shy * w2;
+ double d2 = shy * w1 - w0 * sy;
+ double d = sx * d0 + shx * d1 + tx * d2;
+ if(d == 0.0)
+ {
+ sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
+ return false;
+ }
+ d = 1.0 / d;
+ trans_perspective a = *this;
+ sx = d * d0;
+ shy = d * d1;
+ w0 = d * d2;
+ shx = d * (a.w1 *a.tx - a.shx*a.w2);
+ sy = d * (a.sx *a.w2 - a.w0 *a.tx);
+ w1 = d * (a.w0 *a.shx - a.sx *a.w1);
+ tx = d * (a.shx*a.ty - a.sy *a.tx);
+ ty = d * (a.shy*a.tx - a.sx *a.ty);
+ w2 = d * (a.sx *a.sy - a.shy*a.shx);
+ return true;
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::quad_to_square(const double* q)
+ {
+ if(!square_to_quad(q)) return false;
+ invert();
+ return true;
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::quad_to_quad(const double* qs,
+ const double* qd)
+ {
+ trans_perspective p;
+ if(! quad_to_square(qs)) return false;
+ if(!p.square_to_quad(qd)) return false;
+ multiply(p);
+ return true;
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::rect_to_quad(double x1, double y1,
+ double x2, double y2,
+ const double* q)
+ {
+ double r[8];
+ r[0] = r[6] = x1;
+ r[2] = r[4] = x2;
+ r[1] = r[3] = y1;
+ r[5] = r[7] = y2;
+ return quad_to_quad(r, q);
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::quad_to_rect(const double* q,
+ double x1, double y1,
+ double x2, double y2)
+ {
+ double r[8];
+ r[0] = r[6] = x1;
+ r[2] = r[4] = x2;
+ r[1] = r[3] = y1;
+ r[5] = r[7] = y2;
+ return quad_to_quad(q, r);
+ }
+
+ //------------------------------------------------------------------------
+ inline trans_perspective::trans_perspective(double x1, double y1,
+ double x2, double y2,
+ const double* quad)
+ {
+ rect_to_quad(x1, y1, x2, y2, quad);
+ }
+
+ //------------------------------------------------------------------------
+ inline trans_perspective::trans_perspective(const double* quad,
+ double x1, double y1,
+ double x2, double y2)
+ {
+ quad_to_rect(quad, x1, y1, x2, y2);
+ }
+
+ //------------------------------------------------------------------------
+ inline trans_perspective::trans_perspective(const double* src,
+ const double* dst)
+ {
+ quad_to_quad(src, dst);
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective& trans_perspective::reset()
+ {
+ sx = 1; shy = 0; w0 = 0;
+ shx = 0; sy = 1; w1 = 0;
+ tx = 0; ty = 0; w2 = 1;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective&
+ trans_perspective::multiply(const trans_perspective& a)
+ {
+ trans_perspective b = *this;
+ sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
+ shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
+ tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
+ shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
+ sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
+ ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
+ w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
+ w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
+ w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective&
+ trans_perspective::multiply(const trans_affine& a)
+ {
+ trans_perspective b = *this;
+ sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
+ shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
+ tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
+ shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
+ sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
+ ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective&
+ trans_perspective::premultiply(const trans_perspective& b)
+ {
+ trans_perspective a = *this;
+ sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
+ shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
+ tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
+ shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
+ sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
+ ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
+ w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
+ w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
+ w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective&
+ trans_perspective::premultiply(const trans_affine& b)
+ {
+ trans_perspective a = *this;
+ sx = a.sx *b.sx + a.shx*b.shy;
+ shx = a.sx *b.shx + a.shx*b.sy;
+ tx = a.sx *b.tx + a.shx*b.ty + a.tx;
+ shy = a.shy*b.sx + a.sy *b.shy;
+ sy = a.shy*b.shx + a.sy *b.sy;
+ ty = a.shy*b.tx + a.sy *b.ty + a.ty;
+ w0 = a.w0 *b.sx + a.w1 *b.shy;
+ w1 = a.w0 *b.shx + a.w1 *b.sy;
+ w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ const trans_perspective&
+ trans_perspective::multiply_inv(const trans_perspective& m)
+ {
+ trans_perspective t = m;
+ t.invert();
+ return multiply(t);
+ }
+
+ //------------------------------------------------------------------------
+ const trans_perspective&
+ trans_perspective::multiply_inv(const trans_affine& m)
+ {
+ trans_affine t = m;
+ t.invert();
+ return multiply(t);
+ }
+
+ //------------------------------------------------------------------------
+ const trans_perspective&
+ trans_perspective::premultiply_inv(const trans_perspective& m)
+ {
+ trans_perspective t = m;
+ t.invert();
+ return *this = t.multiply(*this);
+ }
+
+ //------------------------------------------------------------------------
+ const trans_perspective&
+ trans_perspective::premultiply_inv(const trans_affine& m)
+ {
+ trans_perspective t(m);
+ t.invert();
+ return *this = t.multiply(*this);
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective&
+ trans_perspective::translate(double x, double y)
+ {
+ tx += x;
+ ty += y;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective& trans_perspective::rotate(double a)
+ {
+ multiply(trans_affine_rotation(a));
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective& trans_perspective::scale(double s)
+ {
+ multiply(trans_affine_scaling(s));
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective& trans_perspective::scale(double x, double y)
+ {
+ multiply(trans_affine_scaling(x, y));
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_perspective::transform(double* px, double* py) const
+ {
+ double x = *px;
+ double y = *py;
+ double m = 1.0 / (x*w0 + y*w1 + w2);
+ *px = m * (x*sx + y*shx + tx);
+ *py = m * (x*shy + y*sy + ty);
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_perspective::transform_affine(double* x, double* y) const
+ {
+ double tmp = *x;
+ *x = tmp * sx + *y * shx + tx;
+ *y = tmp * shy + *y * sy + ty;
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_perspective::transform_2x2(double* x, double* y) const
+ {
+ double tmp = *x;
+ *x = tmp * sx + *y * shx;
+ *y = tmp * shy + *y * sy;
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_perspective::inverse_transform(double* x, double* y) const
+ {
+ trans_perspective t(*this);
+ if(t.invert()) t.transform(x, y);
+ }
+
+ //------------------------------------------------------------------------
+ inline void trans_perspective::store_to(double* m) const
+ {
+ *m++ = sx; *m++ = shy; *m++ = w0;
+ *m++ = shx; *m++ = sy; *m++ = w1;
+ *m++ = tx; *m++ = ty; *m++ = w2;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective& trans_perspective::load_from(const double* m)
+ {
+ sx = *m++; shy = *m++; w0 = *m++;
+ shx = *m++; sy = *m++; w1 = *m++;
+ tx = *m++; ty = *m++; w2 = *m++;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline const trans_perspective&
+ trans_perspective::from_affine(const trans_affine& a)
+ {
+ sx = a.sx; shy = a.shy; w0 = 0;
+ shx = a.shx; sy = a.sy; w1 = 0;
+ tx = a.tx; ty = a.ty; w2 = 1;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ inline double trans_perspective::determinant() const
+ {
+ return sx * (sy * w2 - ty * w1) +
+ shx * (ty * w0 - shy * w2) +
+ tx * (shy * w1 - sy * w0);
+ }
+
+ //------------------------------------------------------------------------
+ inline double trans_perspective::determinant_reciprocal() const
+ {
+ return 1.0 / determinant();
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::is_valid(double epsilon) const
+ {
+ return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon;
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::is_identity(double epsilon) const
+ {
+ return is_equal_eps(sx, 1.0, epsilon) &&
+ is_equal_eps(shy, 0.0, epsilon) &&
+ is_equal_eps(w0, 0.0, epsilon) &&
+ is_equal_eps(shx, 0.0, epsilon) &&
+ is_equal_eps(sy, 1.0, epsilon) &&
+ is_equal_eps(w1, 0.0, epsilon) &&
+ is_equal_eps(tx, 0.0, epsilon) &&
+ is_equal_eps(ty, 0.0, epsilon) &&
+ is_equal_eps(w2, 1.0, epsilon);
+ }
+
+ //------------------------------------------------------------------------
+ inline bool trans_perspective::is_equal(const trans_perspective& m,
+ double epsilon) const
+ {
+ return is_equal_eps(sx, m.sx, epsilon) &&
+ is_equal_eps(shy, m.shy, epsilon) &&
+ is_equal_eps(w0, m.w0, epsilon) &&
+ is_equal_eps(shx, m.shx, epsilon) &&
+ is_equal_eps(sy, m.sy, epsilon) &&
+ is_equal_eps(w1, m.w1, epsilon) &&
+ is_equal_eps(tx, m.tx, epsilon) &&
+ is_equal_eps(ty, m.ty, epsilon) &&
+ is_equal_eps(w2, m.w2, epsilon);
+ }
+
+ //------------------------------------------------------------------------
+ inline double trans_perspective::scale() const
+ {
+ double x = 0.707106781 * sx + 0.707106781 * shx;
+ double y = 0.707106781 * shy + 0.707106781 * sy;
+ return sqrt(x*x + y*y);
+ }
+
+ //------------------------------------------------------------------------
+ inline double trans_perspective::rotation() const
+ {
+ double x1 = 0.0;
+ double y1 = 0.0;
+ double x2 = 1.0;
+ double y2 = 0.0;
+ transform(&x1, &y1);
+ transform(&x2, &y2);
+ return atan2(y2-y1, x2-x1);
+ }
+
+ //------------------------------------------------------------------------
+ void trans_perspective::translation(double* dx, double* dy) const
+ {
+ *dx = tx;
+ *dy = ty;
+ }
+
+ //------------------------------------------------------------------------
+ void trans_perspective::scaling(double* x, double* y) const
+ {
+ double x1 = 0.0;
+ double y1 = 0.0;
+ double x2 = 1.0;
+ double y2 = 1.0;
+ trans_perspective t(*this);
+ t *= trans_affine_rotation(-rotation());
+ t.transform(&x1, &y1);
+ t.transform(&x2, &y2);
+ *x = x2 - x1;
+ *y = y2 - y1;
+ }
+
+ //------------------------------------------------------------------------
+ void trans_perspective::scaling_abs(double* x, double* y) const
+ {
+ *x = sqrt(sx * sx + shx * shx);
+ *y = sqrt(shy * shy + sy * sy);
+ }
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_trans_single_path.h b/plugins/Clist_ng/AGG/include/agg_trans_single_path.h new file mode 100644 index 0000000000..479a1f1cfe --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_trans_single_path.h @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_TRANS_SINGLE_PATH_INCLUDED
+#define AGG_TRANS_SINGLE_PATH_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vertex_sequence.h"
+
+namespace agg
+{
+
+ // See also: agg_trans_single_path.cpp
+ //
+ //-------------------------------------------------------trans_single_path
+ class trans_single_path
+ {
+ enum status_e
+ {
+ initial,
+ making_path,
+ ready
+ };
+
+ public:
+ typedef vertex_sequence<vertex_dist, 6> vertex_storage;
+
+ trans_single_path();
+
+ //--------------------------------------------------------------------
+ void base_length(double v) { m_base_length = v; }
+ double base_length() const { return m_base_length; }
+
+ //--------------------------------------------------------------------
+ void preserve_x_scale(bool f) { m_preserve_x_scale = f; }
+ bool preserve_x_scale() const { return m_preserve_x_scale; }
+
+ //--------------------------------------------------------------------
+ void reset();
+ void move_to(double x, double y);
+ void line_to(double x, double y);
+ void finalize_path();
+
+ //--------------------------------------------------------------------
+ template<class VertexSource>
+ void add_path(VertexSource& vs, unsigned path_id=0)
+ {
+ double x;
+ double y;
+
+ unsigned cmd;
+ vs.rewind(path_id);
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ if(is_move_to(cmd))
+ {
+ move_to(x, y);
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ line_to(x, y);
+ }
+ }
+ }
+ finalize_path();
+ }
+
+ //--------------------------------------------------------------------
+ double total_length() const;
+ void transform(double *x, double *y) const;
+
+ private:
+ vertex_storage m_src_vertices;
+ double m_base_length;
+ double m_kindex;
+ status_e m_status;
+ bool m_preserve_x_scale;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_trans_viewport.h b/plugins/Clist_ng/AGG/include/agg_trans_viewport.h new file mode 100644 index 0000000000..a9d18b540b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_trans_viewport.h @@ -0,0 +1,312 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// Viewport transformer - simple orthogonal conversions from world coordinates
+// to screen (device) ones.
+//
+//----------------------------------------------------------------------------
+
+#ifndef AGG_TRANS_VIEWPORT_INCLUDED
+#define AGG_TRANS_VIEWPORT_INCLUDED
+
+#include <string.h>
+#include "agg_trans_affine.h"
+
+
+namespace agg
+{
+
+ enum aspect_ratio_e
+ {
+ aspect_ratio_stretch,
+ aspect_ratio_meet,
+ aspect_ratio_slice
+ };
+
+
+ //----------------------------------------------------------trans_viewport
+ class trans_viewport
+ {
+ public:
+ //-------------------------------------------------------------------
+ trans_viewport() :
+ m_world_x1(0.0),
+ m_world_y1(0.0),
+ m_world_x2(1.0),
+ m_world_y2(1.0),
+ m_device_x1(0.0),
+ m_device_y1(0.0),
+ m_device_x2(1.0),
+ m_device_y2(1.0),
+ m_aspect(aspect_ratio_stretch),
+ m_is_valid(true),
+ m_align_x(0.5),
+ m_align_y(0.5),
+ m_wx1(0.0),
+ m_wy1(0.0),
+ m_wx2(1.0),
+ m_wy2(1.0),
+ m_dx1(0.0),
+ m_dy1(0.0),
+ m_kx(1.0),
+ m_ky(1.0)
+ {}
+
+ //-------------------------------------------------------------------
+ void preserve_aspect_ratio(double alignx,
+ double aligny,
+ aspect_ratio_e aspect)
+ {
+ m_align_x = alignx;
+ m_align_y = aligny;
+ m_aspect = aspect;
+ update();
+ }
+
+ //-------------------------------------------------------------------
+ void device_viewport(double x1, double y1, double x2, double y2)
+ {
+ m_device_x1 = x1;
+ m_device_y1 = y1;
+ m_device_x2 = x2;
+ m_device_y2 = y2;
+ update();
+ }
+
+ //-------------------------------------------------------------------
+ void world_viewport(double x1, double y1, double x2, double y2)
+ {
+ m_world_x1 = x1;
+ m_world_y1 = y1;
+ m_world_x2 = x2;
+ m_world_y2 = y2;
+ update();
+ }
+
+ //-------------------------------------------------------------------
+ void device_viewport(double* x1, double* y1, double* x2, double* y2) const
+ {
+ *x1 = m_device_x1;
+ *y1 = m_device_y1;
+ *x2 = m_device_x2;
+ *y2 = m_device_y2;
+ }
+
+ //-------------------------------------------------------------------
+ void world_viewport(double* x1, double* y1, double* x2, double* y2) const
+ {
+ *x1 = m_world_x1;
+ *y1 = m_world_y1;
+ *x2 = m_world_x2;
+ *y2 = m_world_y2;
+ }
+
+ //-------------------------------------------------------------------
+ void world_viewport_actual(double* x1, double* y1,
+ double* x2, double* y2) const
+ {
+ *x1 = m_wx1;
+ *y1 = m_wy1;
+ *x2 = m_wx2;
+ *y2 = m_wy2;
+ }
+
+ //-------------------------------------------------------------------
+ bool is_valid() const { return m_is_valid; }
+ double align_x() const { return m_align_x; }
+ double align_y() const { return m_align_y; }
+ aspect_ratio_e aspect_ratio() const { return m_aspect; }
+
+ //-------------------------------------------------------------------
+ void transform(double* x, double* y) const
+ {
+ *x = (*x - m_wx1) * m_kx + m_dx1;
+ *y = (*y - m_wy1) * m_ky + m_dy1;
+ }
+
+ //-------------------------------------------------------------------
+ void transform_scale_only(double* x, double* y) const
+ {
+ *x *= m_kx;
+ *y *= m_ky;
+ }
+
+ //-------------------------------------------------------------------
+ void inverse_transform(double* x, double* y) const
+ {
+ *x = (*x - m_dx1) / m_kx + m_wx1;
+ *y = (*y - m_dy1) / m_ky + m_wy1;
+ }
+
+ //-------------------------------------------------------------------
+ void inverse_transform_scale_only(double* x, double* y) const
+ {
+ *x /= m_kx;
+ *y /= m_ky;
+ }
+
+ //-------------------------------------------------------------------
+ double device_dx() const { return m_dx1 - m_wx1 * m_kx; }
+ double device_dy() const { return m_dy1 - m_wy1 * m_ky; }
+
+ //-------------------------------------------------------------------
+ double scale_x() const
+ {
+ return m_kx;
+ }
+
+ //-------------------------------------------------------------------
+ double scale_y() const
+ {
+ return m_ky;
+ }
+
+ //-------------------------------------------------------------------
+ double scale() const
+ {
+ return (m_kx + m_ky) * 0.5;
+ }
+
+ //-------------------------------------------------------------------
+ trans_affine to_affine() const
+ {
+ trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1);
+ mtx *= trans_affine_scaling(m_kx, m_ky);
+ mtx *= trans_affine_translation(m_dx1, m_dy1);
+ return mtx;
+ }
+
+ //-------------------------------------------------------------------
+ trans_affine to_affine_scale_only() const
+ {
+ return trans_affine_scaling(m_kx, m_ky);
+ }
+
+ //-------------------------------------------------------------------
+ unsigned byte_size() const
+ {
+ return sizeof(*this);
+ }
+
+ void serialize(int8u* ptr) const
+ {
+ memcpy(ptr, this, sizeof(*this));
+ }
+
+ void deserialize(const int8u* ptr)
+ {
+ memcpy(this, ptr, sizeof(*this));
+ }
+
+ private:
+ void update();
+
+ double m_world_x1;
+ double m_world_y1;
+ double m_world_x2;
+ double m_world_y2;
+ double m_device_x1;
+ double m_device_y1;
+ double m_device_x2;
+ double m_device_y2;
+ aspect_ratio_e m_aspect;
+ bool m_is_valid;
+ double m_align_x;
+ double m_align_y;
+ double m_wx1;
+ double m_wy1;
+ double m_wx2;
+ double m_wy2;
+ double m_dx1;
+ double m_dy1;
+ double m_kx;
+ double m_ky;
+ };
+
+
+
+ //-----------------------------------------------------------------------
+ inline void trans_viewport::update()
+ {
+ const double epsilon = 1e-30;
+ if(fabs(m_world_x1 - m_world_x2) < epsilon ||
+ fabs(m_world_y1 - m_world_y2) < epsilon ||
+ fabs(m_device_x1 - m_device_x2) < epsilon ||
+ fabs(m_device_y1 - m_device_y2) < epsilon)
+ {
+ m_wx1 = m_world_x1;
+ m_wy1 = m_world_y1;
+ m_wx2 = m_world_x1 + 1.0;
+ m_wy2 = m_world_y2 + 1.0;
+ m_dx1 = m_device_x1;
+ m_dy1 = m_device_y1;
+ m_kx = 1.0;
+ m_ky = 1.0;
+ m_is_valid = false;
+ return;
+ }
+
+ double world_x1 = m_world_x1;
+ double world_y1 = m_world_y1;
+ double world_x2 = m_world_x2;
+ double world_y2 = m_world_y2;
+ double device_x1 = m_device_x1;
+ double device_y1 = m_device_y1;
+ double device_x2 = m_device_x2;
+ double device_y2 = m_device_y2;
+ if(m_aspect != aspect_ratio_stretch)
+ {
+ double d;
+ m_kx = (device_x2 - device_x1) / (world_x2 - world_x1);
+ m_ky = (device_y2 - device_y1) / (world_y2 - world_y1);
+
+ if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky))
+ {
+ d = (world_y2 - world_y1) * m_ky / m_kx;
+ world_y1 += (world_y2 - world_y1 - d) * m_align_y;
+ world_y2 = world_y1 + d;
+ }
+ else
+ {
+ d = (world_x2 - world_x1) * m_kx / m_ky;
+ world_x1 += (world_x2 - world_x1 - d) * m_align_x;
+ world_x2 = world_x1 + d;
+ }
+ }
+ m_wx1 = world_x1;
+ m_wy1 = world_y1;
+ m_wx2 = world_x2;
+ m_wy2 = world_y2;
+ m_dx1 = device_x1;
+ m_dy1 = device_y1;
+ m_kx = (device_x2 - device_x1) / (world_x2 - world_x1);
+ m_ky = (device_y2 - device_y1) / (world_y2 - world_y1);
+ m_is_valid = true;
+ }
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_trans_warp_magnifier.h b/plugins/Clist_ng/AGG/include/agg_trans_warp_magnifier.h new file mode 100644 index 0000000000..d80f71152d --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_trans_warp_magnifier.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_WARP_MAGNIFIER_INCLUDED
+#define AGG_WARP_MAGNIFIER_INCLUDED
+
+
+namespace agg
+{
+
+ //----------------------------------------------------trans_warp_magnifier
+ //
+ // See Inmplementation agg_trans_warp_magnifier.cpp
+ //
+ class trans_warp_magnifier
+ {
+ public:
+ trans_warp_magnifier() : m_xc(0.0), m_yc(0.0), m_magn(1.0), m_radius(1.0) {}
+
+ void center(double x, double y) { m_xc = x; m_yc = y; }
+ void magnification(double m) { m_magn = m; }
+ void radius(double r) { m_radius = r; }
+
+ double xc() const { return m_xc; }
+ double yc() const { return m_yc; }
+ double magnification() const { return m_magn; }
+ double radius() const { return m_radius; }
+
+ void transform(double* x, double* y) const;
+ void inverse_transform(double* x, double* y) const;
+
+ private:
+ double m_xc;
+ double m_yc;
+ double m_magn;
+ double m_radius;
+ };
+
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_vcgen_bspline.h b/plugins/Clist_ng/AGG/include/agg_vcgen_bspline.h new file mode 100644 index 0000000000..d55dd0657d --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vcgen_bspline.h @@ -0,0 +1,83 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VCGEN_BSPLINE_INCLUDED
+#define AGG_VCGEN_BSPLINE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_array.h"
+#include "agg_bspline.h"
+
+
+namespace agg
+{
+
+ //==========================================================vcgen_bspline
+ class vcgen_bspline
+ {
+ enum status_e
+ {
+ initial,
+ ready,
+ polygon,
+ end_poly,
+ stop
+ };
+
+ public:
+ typedef pod_bvector<point_d, 6> vertex_storage;
+
+ vcgen_bspline();
+
+ void interpolation_step(double v) { m_interpolation_step = v; }
+ double interpolation_step() const { return m_interpolation_step; }
+
+ // Vertex Generator Interface
+ void remove_all();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ vcgen_bspline(const vcgen_bspline&);
+ const vcgen_bspline& operator = (const vcgen_bspline&);
+
+ vertex_storage m_src_vertices;
+ bspline m_spline_x;
+ bspline m_spline_y;
+ double m_interpolation_step;
+ unsigned m_closed;
+ status_e m_status;
+ unsigned m_src_vertex;
+ double m_cur_abscissa;
+ double m_max_abscissa;
+ };
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_vcgen_contour.h b/plugins/Clist_ng/AGG/include/agg_vcgen_contour.h new file mode 100644 index 0000000000..85ca00e3c8 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vcgen_contour.h @@ -0,0 +1,103 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VCGEN_CONTOUR_INCLUDED
+#define AGG_VCGEN_CONTOUR_INCLUDED
+
+#include "agg_math_stroke.h"
+
+namespace agg
+{
+
+ //----------------------------------------------------------vcgen_contour
+ //
+ // See Implementation agg_vcgen_contour.cpp
+ //
+ class vcgen_contour
+ {
+ enum status_e
+ {
+ initial,
+ ready,
+ outline,
+ out_vertices,
+ end_poly,
+ stop
+ };
+
+ public:
+ typedef vertex_sequence<vertex_dist, 6> vertex_storage;
+ typedef pod_bvector<point_d, 6> coord_storage;
+
+ vcgen_contour();
+
+ void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
+ void line_join(line_join_e lj) { m_stroker.line_join(lj); }
+ void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
+
+ line_cap_e line_cap() const { return m_stroker.line_cap(); }
+ line_join_e line_join() const { return m_stroker.line_join(); }
+ inner_join_e inner_join() const { return m_stroker.inner_join(); }
+
+ void width(double w) { m_stroker.width(m_width = w); }
+ void miter_limit(double ml) { m_stroker.miter_limit(ml); }
+ void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
+ void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
+ void approximation_scale(double as) { m_stroker.approximation_scale(as); }
+
+ double width() const { return m_width; }
+ double miter_limit() const { return m_stroker.miter_limit(); }
+ double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
+ double approximation_scale() const { return m_stroker.approximation_scale(); }
+
+ void auto_detect_orientation(bool v) { m_auto_detect = v; }
+ bool auto_detect_orientation() const { return m_auto_detect; }
+
+ // Generator interface
+ void remove_all();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ vcgen_contour(const vcgen_contour&);
+ const vcgen_contour& operator = (const vcgen_contour&);
+
+ math_stroke<coord_storage> m_stroker;
+ double m_width;
+ vertex_storage m_src_vertices;
+ coord_storage m_out_vertices;
+ status_e m_status;
+ unsigned m_src_vertex;
+ unsigned m_out_vertex;
+ unsigned m_closed;
+ unsigned m_orientation;
+ bool m_auto_detect;
+ };
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vcgen_dash.h b/plugins/Clist_ng/AGG/include/agg_vcgen_dash.h new file mode 100644 index 0000000000..8f195a2306 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vcgen_dash.h @@ -0,0 +1,99 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VCGEN_DASH_INCLUDED
+#define AGG_VCGEN_DASH_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vertex_sequence.h"
+
+namespace agg
+{
+
+ //---------------------------------------------------------------vcgen_dash
+ //
+ // See Implementation agg_vcgen_dash.cpp
+ //
+ class vcgen_dash
+ {
+ enum max_dashes_e
+ {
+ max_dashes = 32
+ };
+
+ enum status_e
+ {
+ initial,
+ ready,
+ polyline,
+ stop
+ };
+
+ public:
+ typedef vertex_sequence<vertex_dist, 6> vertex_storage;
+
+ vcgen_dash();
+
+ void remove_all_dashes();
+ void add_dash(double dash_len, double gap_len);
+ void dash_start(double ds);
+
+ void shorten(double s) { m_shorten = s; }
+ double shorten() const { return m_shorten; }
+
+ // Vertex Generator Interface
+ void remove_all();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ vcgen_dash(const vcgen_dash&);
+ const vcgen_dash& operator = (const vcgen_dash&);
+
+ void calc_dash_start(double ds);
+
+ double m_dashes[max_dashes];
+ double m_total_dash_len;
+ unsigned m_num_dashes;
+ double m_dash_start;
+ double m_shorten;
+ double m_curr_dash_start;
+ unsigned m_curr_dash;
+ double m_curr_rest;
+ const vertex_dist* m_v1;
+ const vertex_dist* m_v2;
+
+ vertex_storage m_src_vertices;
+ unsigned m_closed;
+ status_e m_status;
+ unsigned m_src_vertex;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vcgen_markers_term.h b/plugins/Clist_ng/AGG/include/agg_vcgen_markers_term.h new file mode 100644 index 0000000000..b4abc22cad --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vcgen_markers_term.h @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VCGEN_MARKERS_TERM_INCLUDED
+#define AGG_VCGEN_MARKERS_TERM_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vertex_sequence.h"
+
+namespace agg
+{
+
+ //======================================================vcgen_markers_term
+ //
+ // See Implemantation agg_vcgen_markers_term.cpp
+ // Terminal markers generator (arrowhead/arrowtail)
+ //
+ //------------------------------------------------------------------------
+ class vcgen_markers_term
+ {
+ public:
+ vcgen_markers_term() : m_curr_id(0), m_curr_idx(0) {}
+
+ // Vertex Generator Interface
+ void remove_all();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ vcgen_markers_term(const vcgen_markers_term&);
+ const vcgen_markers_term& operator = (const vcgen_markers_term&);
+
+ struct coord_type
+ {
+ double x, y;
+
+ coord_type() {}
+ coord_type(double x_, double y_) : x(x_), y(y_) {}
+ };
+
+ typedef pod_bvector<coord_type, 6> coord_storage;
+
+ coord_storage m_markers;
+ unsigned m_curr_id;
+ unsigned m_curr_idx;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vcgen_smooth_poly1.h b/plugins/Clist_ng/AGG/include/agg_vcgen_smooth_poly1.h new file mode 100644 index 0000000000..8e10823a5e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vcgen_smooth_poly1.h @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VCGEN_SMOOTH_POLY1_INCLUDED
+#define AGG_VCGEN_SMOOTH_POLY1_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vertex_sequence.h"
+
+
+namespace agg
+{
+
+ //======================================================vcgen_smooth_poly1
+ //
+ // See Implementation agg_vcgen_smooth_poly1.cpp
+ // Smooth polygon generator
+ //
+ //------------------------------------------------------------------------
+ class vcgen_smooth_poly1
+ {
+ enum status_e
+ {
+ initial,
+ ready,
+ polygon,
+ ctrl_b,
+ ctrl_e,
+ ctrl1,
+ ctrl2,
+ end_poly,
+ stop
+ };
+
+ public:
+ typedef vertex_sequence<vertex_dist, 6> vertex_storage;
+
+ vcgen_smooth_poly1();
+
+ void smooth_value(double v) { m_smooth_value = v * 0.5; }
+ double smooth_value() const { return m_smooth_value * 2.0; }
+
+ // Vertex Generator Interface
+ void remove_all();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ vcgen_smooth_poly1(const vcgen_smooth_poly1&);
+ const vcgen_smooth_poly1& operator = (const vcgen_smooth_poly1&);
+
+ void calculate(const vertex_dist& v0,
+ const vertex_dist& v1,
+ const vertex_dist& v2,
+ const vertex_dist& v3);
+
+ vertex_storage m_src_vertices;
+ double m_smooth_value;
+ unsigned m_closed;
+ status_e m_status;
+ unsigned m_src_vertex;
+ double m_ctrl1_x;
+ double m_ctrl1_y;
+ double m_ctrl2_x;
+ double m_ctrl2_y;
+ };
+
+}
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/agg_vcgen_stroke.h b/plugins/Clist_ng/AGG/include/agg_vcgen_stroke.h new file mode 100644 index 0000000000..e39afb8d5d --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vcgen_stroke.h @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VCGEN_STROKE_INCLUDED
+#define AGG_VCGEN_STROKE_INCLUDED
+
+#include "agg_math_stroke.h"
+
+
+namespace agg
+{
+
+ //============================================================vcgen_stroke
+ //
+ // See Implementation agg_vcgen_stroke.cpp
+ // Stroke generator
+ //
+ //------------------------------------------------------------------------
+ class vcgen_stroke
+ {
+ enum status_e
+ {
+ initial,
+ ready,
+ cap1,
+ cap2,
+ outline1,
+ close_first,
+ outline2,
+ out_vertices,
+ end_poly1,
+ end_poly2,
+ stop
+ };
+
+ public:
+ typedef vertex_sequence<vertex_dist, 6> vertex_storage;
+ typedef pod_bvector<point_d, 6> coord_storage;
+
+ vcgen_stroke();
+
+ void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
+ void line_join(line_join_e lj) { m_stroker.line_join(lj); }
+ void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
+
+ line_cap_e line_cap() const { return m_stroker.line_cap(); }
+ line_join_e line_join() const { return m_stroker.line_join(); }
+ inner_join_e inner_join() const { return m_stroker.inner_join(); }
+
+ void width(double w) { m_stroker.width(w); }
+ void miter_limit(double ml) { m_stroker.miter_limit(ml); }
+ void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
+ void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
+ void approximation_scale(double as) { m_stroker.approximation_scale(as); }
+
+ double width() const { return m_stroker.width(); }
+ double miter_limit() const { return m_stroker.miter_limit(); }
+ double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
+ double approximation_scale() const { return m_stroker.approximation_scale(); }
+
+ void shorten(double s) { m_shorten = s; }
+ double shorten() const { return m_shorten; }
+
+ // Vertex Generator Interface
+ void remove_all();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ vcgen_stroke(const vcgen_stroke&);
+ const vcgen_stroke& operator = (const vcgen_stroke&);
+
+ math_stroke<coord_storage> m_stroker;
+ vertex_storage m_src_vertices;
+ coord_storage m_out_vertices;
+ double m_shorten;
+ unsigned m_closed;
+ status_e m_status;
+ status_e m_prev_status;
+ unsigned m_src_vertex;
+ unsigned m_out_vertex;
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vcgen_vertex_sequence.h b/plugins/Clist_ng/AGG/include/agg_vcgen_vertex_sequence.h new file mode 100644 index 0000000000..af94f046bc --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vcgen_vertex_sequence.h @@ -0,0 +1,144 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED
+#define AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_vertex_sequence.h"
+#include "agg_shorten_path.h"
+
+namespace agg
+{
+
+ //===================================================vcgen_vertex_sequence
+ class vcgen_vertex_sequence
+ {
+ public:
+ typedef vertex_dist_cmd vertex_type;
+ typedef vertex_sequence<vertex_type, 6> vertex_storage;
+
+ vcgen_vertex_sequence() :
+ m_flags(0),
+ m_cur_vertex(0),
+ m_shorten(0.0),
+ m_ready(false)
+ {
+ }
+
+ // Vertex Generator Interface
+ void remove_all();
+ void add_vertex(double x, double y, unsigned cmd);
+
+ // Vertex Source Interface
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ void shorten(double s) { m_shorten = s; }
+ double shorten() const { return m_shorten; }
+
+ private:
+ vcgen_vertex_sequence(const vcgen_vertex_sequence&);
+ const vcgen_vertex_sequence& operator = (const vcgen_vertex_sequence&);
+
+ vertex_storage m_src_vertices;
+ unsigned m_flags;
+ unsigned m_cur_vertex;
+ double m_shorten;
+ bool m_ready;
+ };
+
+
+ //------------------------------------------------------------------------
+ inline void vcgen_vertex_sequence::remove_all()
+ {
+ m_ready = false;
+ m_src_vertices.remove_all();
+ m_cur_vertex = 0;
+ m_flags = 0;
+ }
+
+ //------------------------------------------------------------------------
+ inline void vcgen_vertex_sequence::add_vertex(double x, double y, unsigned cmd)
+ {
+ m_ready = false;
+ if(is_move_to(cmd))
+ {
+ m_src_vertices.modify_last(vertex_dist_cmd(x, y, cmd));
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ m_src_vertices.add(vertex_dist_cmd(x, y, cmd));
+ }
+ else
+ {
+ m_flags = cmd & path_flags_mask;
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ inline void vcgen_vertex_sequence::rewind(unsigned)
+ {
+ if(!m_ready)
+ {
+ m_src_vertices.close(is_closed(m_flags));
+ shorten_path(m_src_vertices, m_shorten, get_close_flag(m_flags));
+ }
+ m_ready = true;
+ m_cur_vertex = 0;
+ }
+
+ //------------------------------------------------------------------------
+ inline unsigned vcgen_vertex_sequence::vertex(double* x, double* y)
+ {
+ if(!m_ready)
+ {
+ rewind(0);
+ }
+
+ if(m_cur_vertex == m_src_vertices.size())
+ {
+ ++m_cur_vertex;
+ return path_cmd_end_poly | m_flags;
+ }
+
+ if(m_cur_vertex > m_src_vertices.size())
+ {
+ return path_cmd_stop;
+ }
+
+ vertex_type& v = m_src_vertices[m_cur_vertex++];
+ *x = v.x;
+ *y = v.y;
+ return v.cmd;
+ }
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vertex_sequence.h b/plugins/Clist_ng/AGG/include/agg_vertex_sequence.h new file mode 100644 index 0000000000..9125577de4 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vertex_sequence.h @@ -0,0 +1,178 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VERTEX_SEQUENCE_INCLUDED
+#define AGG_VERTEX_SEQUENCE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_array.h"
+#include "agg_math.h"
+
+namespace agg
+{
+
+ //----------------------------------------------------------vertex_sequence
+ // Modified agg::pod_bvector. The data is interpreted as a sequence
+ // of vertices. It means that the type T must expose:
+ //
+ // bool T::operator() (const T& val)
+ //
+ // that is called every time new vertex is being added. The main purpose
+ // of this operator is the possibility to calculate some values during
+ // adding and to return true if the vertex fits some criteria or false if
+ // it doesn't. In the last case the new vertex is not added.
+ //
+ // The simple example is filtering coinciding vertices with calculation
+ // of the distance between the current and previous ones:
+ //
+ // struct vertex_dist
+ // {
+ // double x;
+ // double y;
+ // double dist;
+ //
+ // vertex_dist() {}
+ // vertex_dist(double x_, double y_) :
+ // x(x_),
+ // y(y_),
+ // dist(0.0)
+ // {
+ // }
+ //
+ // bool operator () (const vertex_dist& val)
+ // {
+ // return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON;
+ // }
+ // };
+ //
+ // Function close() calls this operator and removes the last vertex if
+ // necessary.
+ //------------------------------------------------------------------------
+ template<class T, unsigned S=6>
+ class vertex_sequence : public pod_bvector<T, S>
+ {
+ public:
+ typedef pod_bvector<T, S> base_type;
+
+ void add(const T& val);
+ void modify_last(const T& val);
+ void close(bool remove_flag);
+ };
+
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void vertex_sequence<T, S>::add(const T& val)
+ {
+ if(base_type::size() > 1)
+ {
+ if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1]))
+ {
+ base_type::remove_last();
+ }
+ }
+ base_type::add(val);
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void vertex_sequence<T, S>::modify_last(const T& val)
+ {
+ base_type::remove_last();
+ add(val);
+ }
+
+
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S>
+ void vertex_sequence<T, S>::close(bool closed)
+ {
+ while(base_type::size() > 1)
+ {
+ if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break;
+ T t = (*this)[base_type::size() - 1];
+ base_type::remove_last();
+ modify_last(t);
+ }
+
+ if(closed)
+ {
+ while(base_type::size() > 1)
+ {
+ if((*this)[base_type::size() - 1]((*this)[0])) break;
+ base_type::remove_last();
+ }
+ }
+ }
+
+
+ //-------------------------------------------------------------vertex_dist
+ // Vertex (x, y) with the distance to the next one. The last vertex has
+ // distance between the last and the first points if the polygon is closed
+ // and 0.0 if it's a polyline.
+ struct vertex_dist
+ {
+ double x;
+ double y;
+ double dist;
+
+ vertex_dist() {}
+ vertex_dist(double x_, double y_) :
+ x(x_),
+ y(y_),
+ dist(0.0)
+ {
+ }
+
+ bool operator () (const vertex_dist& val)
+ {
+ bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon;
+ if(!ret) dist = 1.0 / vertex_dist_epsilon;
+ return ret;
+ }
+ };
+
+
+
+ //--------------------------------------------------------vertex_dist_cmd
+ // Save as the above but with additional "command" value
+ struct vertex_dist_cmd : public vertex_dist
+ {
+ unsigned cmd;
+
+ vertex_dist_cmd() {}
+ vertex_dist_cmd(double x_, double y_, unsigned cmd_) :
+ vertex_dist(x_, y_),
+ cmd(cmd_)
+ {
+ }
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vpgen_clip_polygon.h b/plugins/Clist_ng/AGG/include/agg_vpgen_clip_polygon.h new file mode 100644 index 0000000000..f5e791ebca --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vpgen_clip_polygon.h @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VPGEN_CLIP_POLYGON_INCLUDED
+#define AGG_VPGEN_CLIP_POLYGON_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //======================================================vpgen_clip_polygon
+ //
+ // See Implementation agg_vpgen_clip_polygon.cpp
+ //
+ class vpgen_clip_polygon
+ {
+ public:
+ vpgen_clip_polygon() :
+ m_clip_box(0, 0, 1, 1),
+ m_x1(0),
+ m_y1(0),
+ m_clip_flags(0),
+ m_num_vertices(0),
+ m_vertex(0),
+ m_cmd(path_cmd_move_to)
+ {
+ }
+
+ void clip_box(double x1, double y1, double x2, double y2)
+ {
+ m_clip_box.x1 = x1;
+ m_clip_box.y1 = y1;
+ m_clip_box.x2 = x2;
+ m_clip_box.y2 = y2;
+ m_clip_box.normalize();
+ }
+
+
+ double x1() const { return m_clip_box.x1; }
+ double y1() const { return m_clip_box.y1; }
+ double x2() const { return m_clip_box.x2; }
+ double y2() const { return m_clip_box.y2; }
+
+ static bool auto_close() { return true; }
+ static bool auto_unclose() { return false; }
+
+ void reset();
+ void move_to(double x, double y);
+ void line_to(double x, double y);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ unsigned clipping_flags(double x, double y);
+
+ private:
+ rect_d m_clip_box;
+ double m_x1;
+ double m_y1;
+ unsigned m_clip_flags;
+ double m_x[4];
+ double m_y[4];
+ unsigned m_num_vertices;
+ unsigned m_vertex;
+ unsigned m_cmd;
+ };
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vpgen_clip_polyline.h b/plugins/Clist_ng/AGG/include/agg_vpgen_clip_polyline.h new file mode 100644 index 0000000000..31ab16e101 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vpgen_clip_polyline.h @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VPGEN_CLIP_POLYLINE_INCLUDED
+#define AGG_VPGEN_CLIP_POLYLINE_INCLUDED
+
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //======================================================vpgen_clip_polyline
+ //
+ // See Implementation agg_vpgen_clip_polyline.cpp
+ //
+ class vpgen_clip_polyline
+ {
+ public:
+ vpgen_clip_polyline() :
+ m_clip_box(0, 0, 1, 1),
+ m_x1(0),
+ m_y1(0),
+ m_num_vertices(0),
+ m_vertex(0),
+ m_move_to(false)
+ {
+ }
+
+ void clip_box(double x1, double y1, double x2, double y2)
+ {
+ m_clip_box.x1 = x1;
+ m_clip_box.y1 = y1;
+ m_clip_box.x2 = x2;
+ m_clip_box.y2 = y2;
+ m_clip_box.normalize();
+ }
+
+ double x1() const { return m_clip_box.x1; }
+ double y1() const { return m_clip_box.y1; }
+ double x2() const { return m_clip_box.x2; }
+ double y2() const { return m_clip_box.y2; }
+
+ static bool auto_close() { return false; }
+ static bool auto_unclose() { return true; }
+
+ void reset();
+ void move_to(double x, double y);
+ void line_to(double x, double y);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ rect_d m_clip_box;
+ double m_x1;
+ double m_y1;
+ double m_x[2];
+ double m_y[2];
+ unsigned m_cmd[2];
+ unsigned m_num_vertices;
+ unsigned m_vertex;
+ bool m_move_to;
+ };
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/agg_vpgen_segmentator.h b/plugins/Clist_ng/AGG/include/agg_vpgen_segmentator.h new file mode 100644 index 0000000000..eba6052a67 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/agg_vpgen_segmentator.h @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_VPGEN_SEGMENTATOR_INCLUDED
+#define AGG_VPGEN_SEGMENTATOR_INCLUDED
+
+#include <math.h>
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //=======================================================vpgen_segmentator
+ //
+ // See Implementation agg_vpgen_segmentator.cpp
+ //
+ class vpgen_segmentator
+ {
+ public:
+ vpgen_segmentator() : m_approximation_scale(1.0) {}
+
+ void approximation_scale(double s) { m_approximation_scale = s; }
+ double approximation_scale() const { return m_approximation_scale; }
+
+ static bool auto_close() { return false; }
+ static bool auto_unclose() { return false; }
+
+ void reset() { m_cmd = path_cmd_stop; }
+ void move_to(double x, double y);
+ void line_to(double x, double y);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ double m_approximation_scale;
+ double m_x1;
+ double m_y1;
+ double m_dx;
+ double m_dy;
+ double m_dl;
+ double m_ddl;
+ unsigned m_cmd;
+ };
+
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_bezier_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_bezier_ctrl.h new file mode 100644 index 0000000000..f4598e5710 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_bezier_ctrl.h @@ -0,0 +1,201 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_BEZIER_CTRL_INCLUDED
+#define AGG_BEZIER_CTRL_INCLUDED
+
+#include "agg_math.h"
+#include "agg_ellipse.h"
+#include "agg_trans_affine.h"
+#include "agg_color_rgba.h"
+#include "agg_conv_stroke.h"
+#include "agg_conv_curve.h"
+#include "agg_polygon_ctrl.h"
+
+
+namespace agg
+{
+
+ //--------------------------------------------------------bezier_ctrl_impl
+ class bezier_ctrl_impl : public ctrl
+ {
+ public:
+ bezier_ctrl_impl();
+
+ void curve(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4);
+ curve4& curve();
+
+ double x1() const { return m_poly.xn(0); }
+ double y1() const { return m_poly.yn(0); }
+ double x2() const { return m_poly.xn(1); }
+ double y2() const { return m_poly.yn(1); }
+ double x3() const { return m_poly.xn(2); }
+ double y3() const { return m_poly.yn(2); }
+ double x4() const { return m_poly.xn(3); }
+ double y4() const { return m_poly.yn(3); }
+
+ void x1(double x) { m_poly.xn(0) = x; }
+ void y1(double y) { m_poly.yn(0) = y; }
+ void x2(double x) { m_poly.xn(1) = x; }
+ void y2(double y) { m_poly.yn(1) = y; }
+ void x3(double x) { m_poly.xn(2) = x; }
+ void y3(double y) { m_poly.yn(2) = y; }
+ void x4(double x) { m_poly.xn(3) = x; }
+ void y4(double y) { m_poly.yn(3) = y; }
+
+ void line_width(double w) { m_stroke.width(w); }
+ double line_width() const { return m_stroke.width(); }
+
+ void point_radius(double r) { m_poly.point_radius(r); }
+ double point_radius() const { return m_poly.point_radius(); }
+
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ // Vertex source interface
+ unsigned num_paths() { return 7; };
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+
+ private:
+ curve4 m_curve;
+ ellipse m_ellipse;
+ conv_stroke<curve4> m_stroke;
+ polygon_ctrl_impl m_poly;
+ unsigned m_idx;
+ };
+
+
+
+ //----------------------------------------------------------bezier_ctrl
+ template<class ColorT> class bezier_ctrl : public bezier_ctrl_impl
+ {
+ public:
+ bezier_ctrl() :
+ m_color(rgba(0.0, 0.0, 0.0))
+ {
+ }
+
+ void line_color(const ColorT& c) { m_color = c; }
+ const ColorT& color(unsigned i) const { return m_color; }
+
+ private:
+ bezier_ctrl(const bezier_ctrl<ColorT>&);
+ const bezier_ctrl<ColorT>& operator = (const bezier_ctrl<ColorT>&);
+
+ ColorT m_color;
+ };
+
+
+
+
+
+ //--------------------------------------------------------curve3_ctrl_impl
+ class curve3_ctrl_impl : public ctrl
+ {
+ public:
+ curve3_ctrl_impl();
+
+ void curve(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3);
+ curve3& curve();
+
+ double x1() const { return m_poly.xn(0); }
+ double y1() const { return m_poly.yn(0); }
+ double x2() const { return m_poly.xn(1); }
+ double y2() const { return m_poly.yn(1); }
+ double x3() const { return m_poly.xn(2); }
+ double y3() const { return m_poly.yn(2); }
+
+ void x1(double x) { m_poly.xn(0) = x; }
+ void y1(double y) { m_poly.yn(0) = y; }
+ void x2(double x) { m_poly.xn(1) = x; }
+ void y2(double y) { m_poly.yn(1) = y; }
+ void x3(double x) { m_poly.xn(2) = x; }
+ void y3(double y) { m_poly.yn(2) = y; }
+
+ void line_width(double w) { m_stroke.width(w); }
+ double line_width() const { return m_stroke.width(); }
+
+ void point_radius(double r) { m_poly.point_radius(r); }
+ double point_radius() const { return m_poly.point_radius(); }
+
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ // Vertex source interface
+ unsigned num_paths() { return 6; };
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+
+ private:
+ curve3 m_curve;
+ ellipse m_ellipse;
+ conv_stroke<curve3> m_stroke;
+ polygon_ctrl_impl m_poly;
+ unsigned m_idx;
+ };
+
+
+
+ //----------------------------------------------------------curve3_ctrl
+ template<class ColorT> class curve3_ctrl : public curve3_ctrl_impl
+ {
+ public:
+ curve3_ctrl() :
+ m_color(rgba(0.0, 0.0, 0.0))
+ {
+ }
+
+ void line_color(const ColorT& c) { m_color = c; }
+ const ColorT& color(unsigned i) const { return m_color; }
+
+ private:
+ curve3_ctrl(const curve3_ctrl<ColorT>&);
+ const curve3_ctrl<ColorT>& operator = (const curve3_ctrl<ColorT>&);
+
+ ColorT m_color;
+ };
+
+
+
+
+}
+
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_cbox_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_cbox_ctrl.h new file mode 100644 index 0000000000..67b1228ddb --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_cbox_ctrl.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CBOX_CTRL_INCLUDED
+#define AGG_CBOX_CTRL_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_conv_stroke.h"
+#include "agg_gsv_text.h"
+#include "agg_trans_affine.h"
+#include "agg_color_rgba.h"
+#include "agg_ctrl.h"
+
+
+
+namespace agg
+{
+
+ //----------------------------------------------------------cbox_ctrl_impl
+ class cbox_ctrl_impl : public ctrl
+ {
+ public:
+ cbox_ctrl_impl(double x, double y, const char* label, bool flip_y=false);
+
+ void text_thickness(double t) { m_text_thickness = t; }
+ void text_size(double h, double w=0.0);
+
+ const char* label() { return m_label; }
+ void label(const char* l);
+
+ bool status() const { return m_status; }
+ void status(bool st) { m_status = st; }
+
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ // Vertex soutce interface
+ unsigned num_paths() { return 3; };
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ double m_text_thickness;
+ double m_text_height;
+ double m_text_width;
+ char m_label[128];
+ bool m_status;
+ double m_vx[32];
+ double m_vy[32];
+
+ gsv_text m_text;
+ conv_stroke<gsv_text> m_text_poly;
+
+ unsigned m_idx;
+ unsigned m_vertex;
+ };
+
+
+ //----------------------------------------------------------cbox_ctrl_impl
+ template<class ColorT> class cbox_ctrl : public cbox_ctrl_impl
+ {
+ public:
+ cbox_ctrl(double x, double y, const char* label, bool flip_y=false) :
+ cbox_ctrl_impl(x, y, label, flip_y),
+ m_text_color(rgba(0.0, 0.0, 0.0)),
+ m_inactive_color(rgba(0.0, 0.0, 0.0)),
+ m_active_color(rgba(0.4, 0.0, 0.0))
+ {
+ m_colors[0] = &m_inactive_color;
+ m_colors[1] = &m_text_color;
+ m_colors[2] = &m_active_color;
+ }
+
+ void text_color(const ColorT& c) { m_text_color = c; }
+ void inactive_color(const ColorT& c) { m_inactive_color = c; }
+ void active_color(const ColorT& c) { m_active_color = c; }
+
+ const ColorT& color(unsigned i) const { return *m_colors[i]; }
+
+ private:
+ cbox_ctrl(const cbox_ctrl<ColorT>&);
+ const cbox_ctrl<ColorT>& operator = (const cbox_ctrl<ColorT>&);
+
+ ColorT m_text_color;
+ ColorT m_inactive_color;
+ ColorT m_active_color;
+ ColorT* m_colors[3];
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_ctrl.h new file mode 100644 index 0000000000..fff2cb021b --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_ctrl.h @@ -0,0 +1,123 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_CTRL_INCLUDED
+#define AGG_CTRL_INCLUDED
+
+#include "agg_trans_affine.h"
+#include "agg_renderer_scanline.h"
+
+namespace agg
+{
+
+ //--------------------------------------------------------------------ctrl
+ class ctrl
+ {
+ public:
+ //--------------------------------------------------------------------
+ virtual ~ctrl() {}
+ ctrl(double x1, double y1, double x2, double y2, bool flip_y) :
+ m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2),
+ m_flip_y(flip_y),
+ m_mtx(0)
+ {
+ }
+
+ //--------------------------------------------------------------------
+ virtual bool in_rect(double x, double y) const = 0;
+ virtual bool on_mouse_button_down(double x, double y) = 0;
+ virtual bool on_mouse_button_up(double x, double y) = 0;
+ virtual bool on_mouse_move(double x, double y, bool button_flag) = 0;
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up) = 0;
+
+ //--------------------------------------------------------------------
+ void transform(const trans_affine& mtx) { m_mtx = &mtx; }
+ void no_transform() { m_mtx = 0; }
+
+ //--------------------------------------------------------------------
+ void transform_xy(double* x, double* y) const
+ {
+ if(m_flip_y) *y = m_y1 + m_y2 - *y;
+ if(m_mtx) m_mtx->transform(x, y);
+ }
+
+ //--------------------------------------------------------------------
+ void inverse_transform_xy(double* x, double* y) const
+ {
+ if(m_mtx) m_mtx->inverse_transform(x, y);
+ if(m_flip_y) *y = m_y1 + m_y2 - *y;
+ }
+
+ //--------------------------------------------------------------------
+ double scale() const { return m_mtx ? m_mtx->scale() : 1.0; }
+
+ private:
+ ctrl(const ctrl&);
+ const ctrl& operator = (const ctrl&);
+
+ protected:
+ double m_x1;
+ double m_y1;
+ double m_x2;
+ double m_y2;
+
+ private:
+ bool m_flip_y;
+ const trans_affine* m_mtx;
+ };
+
+
+ //--------------------------------------------------------------------
+ template<class Rasterizer, class Scanline, class Renderer, class Ctrl>
+ void render_ctrl(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c)
+ {
+ unsigned i;
+ for(i = 0; i < c.num_paths(); i++)
+ {
+ ras.reset();
+ ras.add_path(c, i);
+ render_scanlines_aa_solid(ras, sl, r, c.color(i));
+ }
+ }
+
+
+ //--------------------------------------------------------------------
+ template<class Rasterizer, class Scanline, class Renderer, class Ctrl>
+ void render_ctrl_rs(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c)
+ {
+ unsigned i;
+ for(i = 0; i < c.num_paths(); i++)
+ {
+ ras.reset();
+ ras.add_path(c, i);
+ r.color(c.color(i));
+ render_scanlines(ras, sl, r);
+ }
+ }
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_gamma_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_gamma_ctrl.h new file mode 100644 index 0000000000..58b2130ac1 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_gamma_ctrl.h @@ -0,0 +1,175 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_GAMMA_CTRL_INCLUDED
+#define AGG_GAMMA_CTRL_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_gamma_spline.h"
+#include "agg_ellipse.h"
+#include "agg_conv_stroke.h"
+#include "agg_gsv_text.h"
+#include "agg_trans_affine.h"
+#include "agg_color_rgba.h"
+#include "agg_ctrl.h"
+
+namespace agg
+{
+ //------------------------------------------------------------------------
+ // Class that can be used to create an interactive control to set up
+ // gamma arrays.
+ //------------------------------------------------------------------------
+ class gamma_ctrl_impl : public ctrl
+ {
+ public:
+ gamma_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false);
+
+ // Set other parameters
+ void border_width(double t, double extra=0.0);
+ void curve_width(double t) { m_curve_width = t; }
+ void grid_width(double t) { m_grid_width = t; }
+ void text_thickness(double t) { m_text_thickness = t; }
+ void text_size(double h, double w=0.0);
+ void point_size(double s) { m_point_size = s; }
+
+ // Event handlers. Just call them if the respective events
+ // in your system occure. The functions return true if redrawing
+ // is required.
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ void change_active_point();
+
+ // A copy of agg::gamma_spline interface
+ void values(double kx1, double ky1, double kx2, double ky2);
+ void values(double* kx1, double* ky1, double* kx2, double* ky2) const;
+ const unsigned char* gamma() const { return m_gamma_spline.gamma(); }
+ double y(double x) const { return m_gamma_spline.y(x); }
+ double operator() (double x) const { return m_gamma_spline.y(x); }
+ const gamma_spline& get_gamma_spline() const { return m_gamma_spline; }
+
+ // Vertex soutce interface
+ unsigned num_paths() { return 7; }
+ void rewind(unsigned idx);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ void calc_spline_box();
+ void calc_points();
+ void calc_values();
+
+ gamma_spline m_gamma_spline;
+ double m_border_width;
+ double m_border_extra;
+ double m_curve_width;
+ double m_grid_width;
+ double m_text_thickness;
+ double m_point_size;
+ double m_text_height;
+ double m_text_width;
+ double m_xc1;
+ double m_yc1;
+ double m_xc2;
+ double m_yc2;
+ double m_xs1;
+ double m_ys1;
+ double m_xs2;
+ double m_ys2;
+ double m_xt1;
+ double m_yt1;
+ double m_xt2;
+ double m_yt2;
+ conv_stroke<gamma_spline> m_curve_poly;
+ ellipse m_ellipse;
+ gsv_text m_text;
+ conv_stroke<gsv_text> m_text_poly;
+ unsigned m_idx;
+ unsigned m_vertex;
+ double m_vx[32];
+ double m_vy[32];
+ double m_xp1;
+ double m_yp1;
+ double m_xp2;
+ double m_yp2;
+ bool m_p1_active;
+ unsigned m_mouse_point;
+ double m_pdx;
+ double m_pdy;
+ };
+
+
+
+ template<class ColorT> class gamma_ctrl : public gamma_ctrl_impl
+ {
+ public:
+ gamma_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) :
+ gamma_ctrl_impl(x1, y1, x2, y2, flip_y),
+ m_background_color(rgba(1.0, 1.0, 0.9)),
+ m_border_color(rgba(0.0, 0.0, 0.0)),
+ m_curve_color(rgba(0.0, 0.0, 0.0)),
+ m_grid_color(rgba(0.2, 0.2, 0.0)),
+ m_inactive_pnt_color(rgba(0.0, 0.0, 0.0)),
+ m_active_pnt_color(rgba(1.0, 0.0, 0.0)),
+ m_text_color(rgba(0.0, 0.0, 0.0))
+ {
+ m_colors[0] = &m_background_color;
+ m_colors[1] = &m_border_color;
+ m_colors[2] = &m_curve_color;
+ m_colors[3] = &m_grid_color;
+ m_colors[4] = &m_inactive_pnt_color;
+ m_colors[5] = &m_active_pnt_color;
+ m_colors[6] = &m_text_color;
+ }
+
+ // Set colors
+ void background_color(const ColorT& c) { m_background_color = c; }
+ void border_color(const ColorT& c) { m_border_color = c; }
+ void curve_color(const ColorT& c) { m_curve_color = c; }
+ void grid_color(const ColorT& c) { m_grid_color = c; }
+ void inactive_pnt_color(const ColorT& c) { m_inactive_pnt_color = c; }
+ void active_pnt_color(const ColorT& c) { m_active_pnt_color = c; }
+ void text_color(const ColorT& c) { m_text_color = c; }
+ const ColorT& color(unsigned i) const { return *m_colors[i]; }
+
+ private:
+ gamma_ctrl(const gamma_ctrl<ColorT>&);
+ const gamma_ctrl<ColorT>& operator = (const gamma_ctrl<ColorT>&);
+
+ ColorT m_background_color;
+ ColorT m_border_color;
+ ColorT m_curve_color;
+ ColorT m_grid_color;
+ ColorT m_inactive_pnt_color;
+ ColorT m_active_pnt_color;
+ ColorT m_text_color;
+ ColorT* m_colors[7];
+ };
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_gamma_spline.h b/plugins/Clist_ng/AGG/include/ctrl/agg_gamma_spline.h new file mode 100644 index 0000000000..db5d8ee027 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_gamma_spline.h @@ -0,0 +1,100 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_GAMMA_SPLINE_INCLUDED
+#define AGG_GAMMA_SPLINE_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_bspline.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ // Class-helper for calculation gamma-correction arrays. A gamma-correction
+ // array is an array of 256 unsigned chars that determine the actual values
+ // of Anti-Aliasing for each pixel coverage value from 0 to 255. If all the
+ // values in the array are equal to its index, i.e. 0,1,2,3,... there's
+ // no gamma-correction. Class agg::polyfill allows you to use custom
+ // gamma-correction arrays. You can calculate it using any approach, and
+ // class gamma_spline allows you to calculate almost any reasonable shape
+ // of the gamma-curve with using only 4 values - kx1, ky1, kx2, ky2.
+ //
+ // kx2
+ // +----------------------------------+
+ // | | | . |
+ // | | | . | ky2
+ // | | . ------|
+ // | | . |
+ // | | . |
+ // |----------------.|----------------|
+ // | . | |
+ // | . | |
+ // |-------. | |
+ // ky1 | . | | |
+ // | . | | |
+ // +----------------------------------+
+ // kx1
+ //
+ // Each value can be in range [0...2]. Value 1.0 means one quarter of the
+ // bounding rectangle. Function values() calculates the curve by these
+ // 4 values. After calling it one can get the gamma-array with call gamma().
+ // Class also supports the vertex source interface, i.e rewind() and
+ // vertex(). It's made for convinience and used in class gamma_ctrl.
+ // Before calling rewind/vertex one must set the bounding box
+ // box() using pixel coordinates.
+ //------------------------------------------------------------------------
+
+ class gamma_spline
+ {
+ public:
+ gamma_spline();
+
+ void values(double kx1, double ky1, double kx2, double ky2);
+ const unsigned char* gamma() const { return m_gamma; }
+ double y(double x) const;
+ void values(double* kx1, double* ky1, double* kx2, double* ky2) const;
+ void box(double x1, double y1, double x2, double y2);
+
+ void rewind(unsigned);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ unsigned char m_gamma[256];
+ double m_x[4];
+ double m_y[4];
+ bspline m_spline;
+ double m_x1;
+ double m_y1;
+ double m_x2;
+ double m_y2;
+ double m_cur_x;
+ };
+
+
+
+
+}
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_polygon_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_polygon_ctrl.h new file mode 100644 index 0000000000..f23e094524 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_polygon_ctrl.h @@ -0,0 +1,171 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef POLYGON_CTRL_INCLUDED
+#define POLYGON_CTRL_INCLUDED
+
+#include "agg_array.h"
+#include "agg_conv_stroke.h"
+#include "agg_ellipse.h"
+#include "agg_color_rgba.h"
+#include "agg_ctrl.h"
+
+namespace agg
+{
+ class simple_polygon_vertex_source
+ {
+ public:
+ simple_polygon_vertex_source(const double* polygon, unsigned np,
+ bool roundoff = false,
+ bool close = true) :
+ m_polygon(polygon),
+ m_num_points(np),
+ m_vertex(0),
+ m_roundoff(roundoff),
+ m_close(close)
+ {
+ }
+
+ void close(bool f) { m_close = f; }
+ bool close() const { return m_close; }
+
+ void rewind(unsigned)
+ {
+ m_vertex = 0;
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_vertex > m_num_points) return path_cmd_stop;
+ if(m_vertex == m_num_points)
+ {
+ ++m_vertex;
+ return path_cmd_end_poly | (m_close ? path_flags_close : 0);
+ }
+ *x = m_polygon[m_vertex * 2];
+ *y = m_polygon[m_vertex * 2 + 1];
+ if(m_roundoff)
+ {
+ *x = floor(*x) + 0.5;
+ *y = floor(*y) + 0.5;
+ }
+ ++m_vertex;
+ return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to;
+ }
+
+ private:
+ const double* m_polygon;
+ unsigned m_num_points;
+ unsigned m_vertex;
+ bool m_roundoff;
+ bool m_close;
+ };
+
+
+
+
+ class polygon_ctrl_impl : public ctrl
+ {
+ public:
+ polygon_ctrl_impl(unsigned np, double point_radius=5);
+
+ unsigned num_points() const { return m_num_points; }
+ double xn(unsigned n) const { return m_polygon[n * 2]; }
+ double yn(unsigned n) const { return m_polygon[n * 2 + 1]; }
+ double& xn(unsigned n) { return m_polygon[n * 2]; }
+ double& yn(unsigned n) { return m_polygon[n * 2 + 1]; }
+
+ const double* polygon() const { return &m_polygon[0]; }
+
+ void line_width(double w) { m_stroke.width(w); }
+ double line_width() const { return m_stroke.width(); }
+
+ void point_radius(double r) { m_point_radius = r; }
+ double point_radius() const { return m_point_radius; }
+
+ void in_polygon_check(bool f) { m_in_polygon_check = f; }
+ bool in_polygon_check() const { return m_in_polygon_check; }
+
+ void close(bool f) { m_vs.close(f); }
+ bool close() const { return m_vs.close(); }
+
+ // Vertex source interface
+ unsigned num_paths() { return 1; }
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+
+ private:
+ bool check_edge(unsigned i, double x, double y) const;
+ bool point_in_polygon(double x, double y) const;
+
+ pod_array<double> m_polygon;
+ unsigned m_num_points;
+ int m_node;
+ int m_edge;
+ simple_polygon_vertex_source m_vs;
+ conv_stroke<simple_polygon_vertex_source> m_stroke;
+ ellipse m_ellipse;
+ double m_point_radius;
+ unsigned m_status;
+ double m_dx;
+ double m_dy;
+ bool m_in_polygon_check;
+ };
+
+
+
+ //----------------------------------------------------------polygon_ctrl
+ template<class ColorT> class polygon_ctrl : public polygon_ctrl_impl
+ {
+ public:
+ polygon_ctrl(unsigned np, double point_radius=5) :
+ polygon_ctrl_impl(np, point_radius),
+ m_color(rgba(0.0, 0.0, 0.0))
+ {
+ }
+
+ void line_color(const ColorT& c) { m_color = c; }
+ const ColorT& color(unsigned i) const { return m_color; }
+
+ private:
+ polygon_ctrl(const polygon_ctrl<ColorT>&);
+ const polygon_ctrl<ColorT>& operator = (const polygon_ctrl<ColorT>&);
+
+ ColorT m_color;
+ };
+
+
+
+
+}
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_rbox_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_rbox_ctrl.h new file mode 100644 index 0000000000..c1c4066130 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_rbox_ctrl.h @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_RBOX_CTRL_INCLUDED
+#define AGG_RBOX_CTRL_INCLUDED
+
+#include "agg_array.h"
+#include "agg_ellipse.h"
+#include "agg_conv_stroke.h"
+#include "agg_gsv_text.h"
+#include "agg_trans_affine.h"
+#include "agg_color_rgba.h"
+#include "agg_ctrl.h"
+
+
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ class rbox_ctrl_impl : public ctrl
+ {
+ public:
+ rbox_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false);
+
+ void border_width(double t, double extra=0.0);
+ void text_thickness(double t) { m_text_thickness = t; }
+ void text_size(double h, double w=0.0);
+
+ void add_item(const char* text);
+ int cur_item() const { return m_cur_item; }
+ void cur_item(int i) { m_cur_item = i; }
+
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ // Vertex soutce interface
+ unsigned num_paths() { return 5; };
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ void calc_rbox();
+
+ double m_border_width;
+ double m_border_extra;
+ double m_text_thickness;
+ double m_text_height;
+ double m_text_width;
+ pod_array<char> m_items[32];
+ unsigned m_num_items;
+ int m_cur_item;
+
+ double m_xs1;
+ double m_ys1;
+ double m_xs2;
+ double m_ys2;
+
+ double m_vx[32];
+ double m_vy[32];
+ unsigned m_draw_item;
+ double m_dy;
+
+ ellipse m_ellipse;
+ conv_stroke<ellipse> m_ellipse_poly;
+ gsv_text m_text;
+ conv_stroke<gsv_text> m_text_poly;
+
+ unsigned m_idx;
+ unsigned m_vertex;
+ };
+
+
+
+ //------------------------------------------------------------------------
+ template<class ColorT> class rbox_ctrl : public rbox_ctrl_impl
+ {
+ public:
+ rbox_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) :
+ rbox_ctrl_impl(x1, y1, x2, y2, flip_y),
+ m_background_color(rgba(1.0, 1.0, 0.9)),
+ m_border_color(rgba(0.0, 0.0, 0.0)),
+ m_text_color(rgba(0.0, 0.0, 0.0)),
+ m_inactive_color(rgba(0.0, 0.0, 0.0)),
+ m_active_color(rgba(0.4, 0.0, 0.0))
+ {
+ m_colors[0] = &m_background_color;
+ m_colors[1] = &m_border_color;
+ m_colors[2] = &m_text_color;
+ m_colors[3] = &m_inactive_color;
+ m_colors[4] = &m_active_color;
+ }
+
+
+ void background_color(const ColorT& c) { m_background_color = c; }
+ void border_color(const ColorT& c) { m_border_color = c; }
+ void text_color(const ColorT& c) { m_text_color = c; }
+ void inactive_color(const ColorT& c) { m_inactive_color = c; }
+ void active_color(const ColorT& c) { m_active_color = c; }
+
+ const ColorT& color(unsigned i) const { return *m_colors[i]; }
+
+ private:
+ rbox_ctrl(const rbox_ctrl<ColorT>&);
+ const rbox_ctrl<ColorT>& operator = (const rbox_ctrl<ColorT>&);
+
+ ColorT m_background_color;
+ ColorT m_border_color;
+ ColorT m_text_color;
+ ColorT m_inactive_color;
+ ColorT m_active_color;
+ ColorT* m_colors[5];
+ };
+
+
+
+}
+
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_scale_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_scale_ctrl.h new file mode 100644 index 0000000000..40f95f9982 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_scale_ctrl.h @@ -0,0 +1,151 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SCALE_CTRL_INCLUDED
+#define AGG_SCALE_CTRL_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_math.h"
+#include "agg_ellipse.h"
+#include "agg_trans_affine.h"
+#include "agg_color_rgba.h"
+#include "agg_ctrl.h"
+
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ class scale_ctrl_impl : public ctrl
+ {
+ enum move_e
+ {
+ move_nothing,
+ move_value1,
+ move_value2,
+ move_slider
+ };
+
+ public:
+ scale_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false);
+
+ void border_thickness(double t, double extra=0.0);
+ void resize(double x1, double y1, double x2, double y2);
+
+ double min_delta() const { return m_min_d; }
+ void min_delta(double d) { m_min_d = d; }
+
+ double value1() const { return m_value1; }
+ void value1(double value);
+
+ double value2() const { return m_value2; }
+ void value2(double value);
+
+ void move(double d);
+
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ // Vertex soutce interface
+ unsigned num_paths() { return 5; };
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ void calc_box();
+
+ double m_border_thickness;
+ double m_border_extra;
+ double m_value1;
+ double m_value2;
+ double m_min_d;
+ double m_xs1;
+ double m_ys1;
+ double m_xs2;
+ double m_ys2;
+ double m_pdx;
+ double m_pdy;
+ move_e m_move_what;
+ double m_vx[32];
+ double m_vy[32];
+
+ ellipse m_ellipse;
+
+ unsigned m_idx;
+ unsigned m_vertex;
+
+ };
+
+
+
+ //------------------------------------------------------------------------
+ template<class ColorT> class scale_ctrl : public scale_ctrl_impl
+ {
+ public:
+ scale_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) :
+ scale_ctrl_impl(x1, y1, x2, y2, flip_y),
+ m_background_color(rgba(1.0, 0.9, 0.8)),
+ m_border_color(rgba(0.0, 0.0, 0.0)),
+ m_pointers_color(rgba(0.8, 0.0, 0.0, 0.8)),
+ m_slider_color(rgba(0.2, 0.1, 0.0, 0.6))
+ {
+ m_colors[0] = &m_background_color;
+ m_colors[1] = &m_border_color;
+ m_colors[2] = &m_pointers_color;
+ m_colors[3] = &m_pointers_color;
+ m_colors[4] = &m_slider_color;
+ }
+
+
+ void background_color(const ColorT& c) { m_background_color = c; }
+ void border_color(const ColorT& c) { m_border_color = c; }
+ void pointers_color(const ColorT& c) { m_pointers_color = c; }
+ void slider_color(const ColorT& c) { m_slider_color = c; }
+
+ const ColorT& color(unsigned i) const { return *m_colors[i]; }
+
+ private:
+ scale_ctrl(const scale_ctrl<ColorT>&);
+ const scale_ctrl<ColorT>& operator = (const scale_ctrl<ColorT>&);
+
+ ColorT m_background_color;
+ ColorT m_border_color;
+ ColorT m_pointers_color;
+ ColorT m_slider_color;
+ ColorT* m_colors[5];
+ };
+
+
+
+
+
+}
+
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_slider_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_slider_ctrl.h new file mode 100644 index 0000000000..54f45caa24 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_slider_ctrl.h @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SLIDER_CTRL_INCLUDED
+#define AGG_SLIDER_CTRL_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_math.h"
+#include "agg_ellipse.h"
+#include "agg_trans_affine.h"
+#include "agg_color_rgba.h"
+#include "agg_gsv_text.h"
+#include "agg_conv_stroke.h"
+#include "agg_path_storage.h"
+#include "agg_ctrl.h"
+
+
+namespace agg
+{
+
+ //--------------------------------------------------------slider_ctrl_impl
+ class slider_ctrl_impl : public ctrl
+ {
+ public:
+ slider_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false);
+
+ void border_width(double t, double extra=0.0);
+
+ void range(double min, double max) { m_min = min; m_max = max; }
+ void num_steps(unsigned num) { m_num_steps = num; }
+ void label(const char* fmt);
+ void text_thickness(double t) { m_text_thickness = t; }
+
+ bool descending() const { return m_descending; }
+ void descending(bool v) { m_descending = v; }
+
+ double value() const { return m_value * (m_max - m_min) + m_min; }
+ void value(double value);
+
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ // Vertex source interface
+ unsigned num_paths() { return 6; };
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ void calc_box();
+ bool normalize_value(bool preview_value_flag);
+
+ double m_border_width;
+ double m_border_extra;
+ double m_text_thickness;
+ double m_value;
+ double m_preview_value;
+ double m_min;
+ double m_max;
+ unsigned m_num_steps;
+ bool m_descending;
+ char m_label[64];
+ double m_xs1;
+ double m_ys1;
+ double m_xs2;
+ double m_ys2;
+ double m_pdx;
+ bool m_mouse_move;
+ double m_vx[32];
+ double m_vy[32];
+
+ ellipse m_ellipse;
+
+ unsigned m_idx;
+ unsigned m_vertex;
+
+ gsv_text m_text;
+ conv_stroke<gsv_text> m_text_poly;
+ path_storage m_storage;
+
+ };
+
+
+
+ //----------------------------------------------------------slider_ctrl
+ template<class ColorT> class slider_ctrl : public slider_ctrl_impl
+ {
+ public:
+ slider_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) :
+ slider_ctrl_impl(x1, y1, x2, y2, flip_y),
+ m_background_color(rgba(1.0, 0.9, 0.8)),
+ m_triangle_color(rgba(0.7, 0.6, 0.6)),
+ m_text_color(rgba(0.0, 0.0, 0.0)),
+ m_pointer_preview_color(rgba(0.6, 0.4, 0.4, 0.4)),
+ m_pointer_color(rgba(0.8, 0.0, 0.0, 0.6))
+ {
+ m_colors[0] = &m_background_color;
+ m_colors[1] = &m_triangle_color;
+ m_colors[2] = &m_text_color;
+ m_colors[3] = &m_pointer_preview_color;
+ m_colors[4] = &m_pointer_color;
+ m_colors[5] = &m_text_color;
+ }
+
+
+ void background_color(const ColorT& c) { m_background_color = c; }
+ void pointer_color(const ColorT& c) { m_pointer_color = c; }
+
+ const ColorT& color(unsigned i) const { return *m_colors[i]; }
+
+ private:
+ slider_ctrl(const slider_ctrl<ColorT>&);
+ const slider_ctrl<ColorT>& operator = (const slider_ctrl<ColorT>&);
+
+ ColorT m_background_color;
+ ColorT m_triangle_color;
+ ColorT m_text_color;
+ ColorT m_pointer_preview_color;
+ ColorT m_pointer_color;
+ ColorT* m_colors[6];
+ };
+
+
+
+
+
+}
+
+
+
+#endif
+
diff --git a/plugins/Clist_ng/AGG/include/ctrl/agg_spline_ctrl.h b/plugins/Clist_ng/AGG/include/ctrl/agg_spline_ctrl.h new file mode 100644 index 0000000000..31591fd299 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/ctrl/agg_spline_ctrl.h @@ -0,0 +1,164 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_SPLINE_CTRL_INCLUDED
+#define AGG_SPLINE_CTRL_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_ellipse.h"
+#include "agg_bspline.h"
+#include "agg_conv_stroke.h"
+#include "agg_path_storage.h"
+#include "agg_trans_affine.h"
+#include "agg_color_rgba.h"
+#include "agg_ctrl.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ // Class that can be used to create an interactive control to set up
+ // gamma arrays.
+ //------------------------------------------------------------------------
+ class spline_ctrl_impl : public ctrl
+ {
+ public:
+ spline_ctrl_impl(double x1, double y1, double x2, double y2,
+ unsigned num_pnt, bool flip_y=false);
+
+ // Set other parameters
+ void border_width(double t, double extra=0.0);
+ void curve_width(double t) { m_curve_width = t; }
+ void point_size(double s) { m_point_size = s; }
+
+ // Event handlers. Just call them if the respective events
+ // in your system occure. The functions return true if redrawing
+ // is required.
+ virtual bool in_rect(double x, double y) const;
+ virtual bool on_mouse_button_down(double x, double y);
+ virtual bool on_mouse_button_up(double x, double y);
+ virtual bool on_mouse_move(double x, double y, bool button_flag);
+ virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
+
+ void active_point(int i);
+
+ const double* spline() const { return m_spline_values; }
+ const int8u* spline8() const { return m_spline_values8; }
+ double value(double x) const;
+ void value(unsigned idx, double y);
+ void point(unsigned idx, double x, double y);
+ void x(unsigned idx, double x) { m_xp[idx] = x; }
+ void y(unsigned idx, double y) { m_yp[idx] = y; }
+ double x(unsigned idx) const { return m_xp[idx]; }
+ double y(unsigned idx) const { return m_yp[idx]; }
+ void update_spline();
+
+ // Vertex soutce interface
+ unsigned num_paths() { return 5; }
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ private:
+ void calc_spline_box();
+ void calc_curve();
+ double calc_xp(unsigned idx);
+ double calc_yp(unsigned idx);
+ void set_xp(unsigned idx, double val);
+ void set_yp(unsigned idx, double val);
+
+ unsigned m_num_pnt;
+ double m_xp[32];
+ double m_yp[32];
+ bspline m_spline;
+ double m_spline_values[256];
+ int8u m_spline_values8[256];
+ double m_border_width;
+ double m_border_extra;
+ double m_curve_width;
+ double m_point_size;
+ double m_xs1;
+ double m_ys1;
+ double m_xs2;
+ double m_ys2;
+ path_storage m_curve_pnt;
+ conv_stroke<path_storage> m_curve_poly;
+ ellipse m_ellipse;
+ unsigned m_idx;
+ unsigned m_vertex;
+ double m_vx[32];
+ double m_vy[32];
+ int m_active_pnt;
+ int m_move_pnt;
+ double m_pdx;
+ double m_pdy;
+ const trans_affine* m_mtx;
+ };
+
+
+ template<class ColorT> class spline_ctrl : public spline_ctrl_impl
+ {
+ public:
+ spline_ctrl(double x1, double y1, double x2, double y2,
+ unsigned num_pnt, bool flip_y=false) :
+ spline_ctrl_impl(x1, y1, x2, y2, num_pnt, flip_y),
+ m_background_color(rgba(1.0, 1.0, 0.9)),
+ m_border_color(rgba(0.0, 0.0, 0.0)),
+ m_curve_color(rgba(0.0, 0.0, 0.0)),
+ m_inactive_pnt_color(rgba(0.0, 0.0, 0.0)),
+ m_active_pnt_color(rgba(1.0, 0.0, 0.0))
+ {
+ m_colors[0] = &m_background_color;
+ m_colors[1] = &m_border_color;
+ m_colors[2] = &m_curve_color;
+ m_colors[3] = &m_inactive_pnt_color;
+ m_colors[4] = &m_active_pnt_color;
+ }
+
+ // Set colors
+ void background_color(const ColorT& c) { m_background_color = c; }
+ void border_color(const ColorT& c) { m_border_color = c; }
+ void curve_color(const ColorT& c) { m_curve_color = c; }
+ void inactive_pnt_color(const ColorT& c) { m_inactive_pnt_color = c; }
+ void active_pnt_color(const ColorT& c) { m_active_pnt_color = c; }
+ const ColorT& color(unsigned i) const { return *m_colors[i]; }
+
+ private:
+ spline_ctrl(const spline_ctrl<ColorT>&);
+ const spline_ctrl<ColorT>& operator = (const spline_ctrl<ColorT>&);
+
+ ColorT m_background_color;
+ ColorT m_border_color;
+ ColorT m_curve_color;
+ ColorT m_inactive_pnt_color;
+ ColorT m_active_pnt_color;
+ ColorT* m_colors[5];
+ };
+
+
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/util/Makefile.am b/plugins/Clist_ng/AGG/include/util/Makefile.am new file mode 100644 index 0000000000..47854a5087 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/util/Makefile.am @@ -0,0 +1,2 @@ +myincludedir = $(includedir)/agg2/util
+myinclude_HEADERS = agg_color_conv.h agg_color_conv_rgb8.h agg_color_conv_rgb16.h
diff --git a/plugins/Clist_ng/AGG/include/util/agg_color_conv.h b/plugins/Clist_ng/AGG/include/util/agg_color_conv.h new file mode 100644 index 0000000000..940d7d1557 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/util/agg_color_conv.h @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#ifndef AGG_COLOR_CONV_INCLUDED
+#define AGG_COLOR_CONV_INCLUDED
+
+#include <string.h>
+#include "agg_basics.h"
+#include "agg_rendering_buffer.h"
+
+
+
+
+namespace agg
+{
+
+ //--------------------------------------------------------------color_conv
+ template<class RenBuf, class CopyRow>
+ void color_conv(RenBuf* dst, const RenBuf* src, CopyRow copy_row_functor)
+ {
+ unsigned width = src->width();
+ unsigned height = src->height();
+
+ if(dst->width() < width) width = dst->width();
+ if(dst->height() < height) height = dst->height();
+
+ if(width)
+ {
+ unsigned y;
+ for(y = 0; y < height; y++)
+ {
+ copy_row_functor(dst->row_ptr(0, y, width),
+ src->row_ptr(y),
+ width);
+ }
+ }
+ }
+
+
+ //---------------------------------------------------------color_conv_row
+ template<class CopyRow>
+ void color_conv_row(int8u* dst,
+ const int8u* src,
+ unsigned width,
+ CopyRow copy_row_functor)
+ {
+ copy_row_functor(dst, src, width);
+ }
+
+
+ //---------------------------------------------------------color_conv_same
+ template<int BPP> class color_conv_same
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ memmove(dst, src, width*BPP);
+ }
+ };
+
+
+}
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/util/agg_color_conv_rgb16.h b/plugins/Clist_ng/AGG/include/util/agg_color_conv_rgb16.h new file mode 100644 index 0000000000..4b780a3823 --- /dev/null +++ b/plugins/Clist_ng/AGG/include/util/agg_color_conv_rgb16.h @@ -0,0 +1,294 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// This part of the library has been sponsored by
+// Liberty Technology Systems, Inc., visit http://lib-sys.com
+//
+// Liberty Technology Systems, Inc. is the provider of
+// PostScript and PDF technology for software developers.
+//
+//----------------------------------------------------------------------------
+//
+// A set of functors used with color_conv(). See file agg_color_conv.h
+// These functors can convert images with up to 8 bits per component.
+// Use convertors in the following way:
+//
+// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY());
+//----------------------------------------------------------------------------
+
+#ifndef AGG_COLOR_CONV_RGB16_INCLUDED
+#define AGG_COLOR_CONV_RGB16_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_conv.h"
+
+namespace agg
+{
+
+ //-------------------------------------------------color_conv_gray16_to_gray8
+ class color_conv_gray16_to_gray8
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ int16u* s = (int16u*)src;
+ do
+ {
+ *dst++ = *s++ >> 8;
+ }
+ while(--width);
+ }
+ };
+
+
+ //-----------------------------------------------------color_conv_rgb24_rgb48
+ template<int I1, int I3> class color_conv_rgb24_rgb48
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ int16u* d = (int16u*)dst;
+ do
+ {
+ *d++ = (src[I1] << 8) | src[I1];
+ *d++ = (src[1] << 8) | src[1] ;
+ *d++ = (src[I3] << 8) | src[I3];
+ src += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_rgb24_rgb48<0,2> color_conv_rgb24_to_rgb48;
+ typedef color_conv_rgb24_rgb48<0,2> color_conv_bgr24_to_bgr48;
+ typedef color_conv_rgb24_rgb48<2,0> color_conv_rgb24_to_bgr48;
+ typedef color_conv_rgb24_rgb48<2,0> color_conv_bgr24_to_rgb48;
+
+
+ //-----------------------------------------------------color_conv_rgb24_rgb48
+ template<int I1, int I3> class color_conv_rgb48_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ const int16u* s = (const int16u*)src;
+ do
+ {
+ *dst++ = s[I1] >> 8;
+ *dst++ = s[1] >> 8;
+ *dst++ = s[I3] >> 8;
+ s += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_rgb48_rgb24<0,2> color_conv_rgb48_to_rgb24;
+ typedef color_conv_rgb48_rgb24<0,2> color_conv_bgr48_to_bgr24;
+ typedef color_conv_rgb48_rgb24<2,0> color_conv_rgb48_to_bgr24;
+ typedef color_conv_rgb48_rgb24<2,0> color_conv_bgr48_to_rgb24;
+
+
+ //----------------------------------------------color_conv_rgbAAA_rgb24
+ template<int R, int B> class color_conv_rgbAAA_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ int32u rgb = *(int32u*)src;
+ dst[R] = int8u(rgb >> 22);
+ dst[1] = int8u(rgb >> 12);
+ dst[B] = int8u(rgb >> 2);
+ src += 4;
+ dst += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_rgbAAA_rgb24<0,2> color_conv_rgbAAA_to_rgb24;
+ typedef color_conv_rgbAAA_rgb24<2,0> color_conv_rgbAAA_to_bgr24;
+ typedef color_conv_rgbAAA_rgb24<2,0> color_conv_bgrAAA_to_rgb24;
+ typedef color_conv_rgbAAA_rgb24<0,2> color_conv_bgrAAA_to_bgr24;
+
+
+ //----------------------------------------------color_conv_rgbBBA_rgb24
+ template<int R, int B> class color_conv_rgbBBA_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ int32u rgb = *(int32u*)src;
+ dst[R] = int8u(rgb >> 24);
+ dst[1] = int8u(rgb >> 13);
+ dst[B] = int8u(rgb >> 2);
+ src += 4;
+ dst += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_rgbBBA_rgb24<0,2> color_conv_rgbBBA_to_rgb24;
+ typedef color_conv_rgbBBA_rgb24<2,0> color_conv_rgbBBA_to_bgr24;
+
+
+ //----------------------------------------------color_conv_bgrABB_rgb24
+ template<int B, int R> class color_conv_bgrABB_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ int32u bgr = *(int32u*)src;
+ dst[R] = int8u(bgr >> 3);
+ dst[1] = int8u(bgr >> 14);
+ dst[B] = int8u(bgr >> 24);
+ src += 4;
+ dst += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_bgrABB_rgb24<2,0> color_conv_bgrABB_to_rgb24;
+ typedef color_conv_bgrABB_rgb24<0,2> color_conv_bgrABB_to_bgr24;
+
+
+ //-------------------------------------------------color_conv_rgba64_rgba32
+ template<int I1, int I2, int I3, int I4> class color_conv_rgba64_rgba32
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *dst++ = int8u(((int16u*)src)[I1] >> 8);
+ *dst++ = int8u(((int16u*)src)[I2] >> 8);
+ *dst++ = int8u(((int16u*)src)[I3] >> 8);
+ *dst++ = int8u(((int16u*)src)[I4] >> 8);
+ src += 8;
+ }
+ while(--width);
+ }
+ };
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_rgba64_to_rgba32; //----color_conv_rgba64_to_rgba32
+ typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_argb64_to_argb32; //----color_conv_argb64_to_argb32
+ typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_bgra64_to_bgra32; //----color_conv_bgra64_to_bgra32
+ typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_abgr64_to_abgr32; //----color_conv_abgr64_to_abgr32
+ typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_argb64_to_abgr32; //----color_conv_argb64_to_abgr32
+ typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_argb64_to_bgra32; //----color_conv_argb64_to_bgra32
+ typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_argb64_to_rgba32; //----color_conv_argb64_to_rgba32
+ typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_bgra64_to_abgr32; //----color_conv_bgra64_to_abgr32
+ typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_bgra64_to_argb32; //----color_conv_bgra64_to_argb32
+ typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_bgra64_to_rgba32; //----color_conv_bgra64_to_rgba32
+ typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_rgba64_to_abgr32; //----color_conv_rgba64_to_abgr32
+ typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_rgba64_to_argb32; //----color_conv_rgba64_to_argb32
+ typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_rgba64_to_bgra32; //----color_conv_rgba64_to_bgra32
+ typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_abgr64_to_argb32; //----color_conv_abgr64_to_argb32
+ typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_abgr64_to_bgra32; //----color_conv_abgr64_to_bgra32
+ typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_abgr64_to_rgba32; //----color_conv_abgr64_to_rgba32
+
+
+
+ //--------------------------------------------color_conv_rgb24_rgba64
+ template<int I1, int I2, int I3, int A> class color_conv_rgb24_rgba64
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ int16u* d = (int16u*)dst;
+ do
+ {
+ d[I1] = (src[0] << 8) | src[0];
+ d[I2] = (src[1] << 8) | src[1];
+ d[I3] = (src[2] << 8) | src[2];
+ d[A] = 65535;
+ d += 4;
+ src += 3;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_rgb24_to_argb64; //----color_conv_rgb24_to_argb64
+ typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_rgb24_to_abgr64; //----color_conv_rgb24_to_abgr64
+ typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_rgb24_to_bgra64; //----color_conv_rgb24_to_bgra64
+ typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_rgb24_to_rgba64; //----color_conv_rgb24_to_rgba64
+ typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_bgr24_to_argb64; //----color_conv_bgr24_to_argb64
+ typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_bgr24_to_abgr64; //----color_conv_bgr24_to_abgr64
+ typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_bgr24_to_bgra64; //----color_conv_bgr24_to_bgra64
+ typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_bgr24_to_rgba64; //----color_conv_bgr24_to_rgba64
+
+
+ template<int R, int B> class color_conv_rgb24_gray16
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ int16u* d = (int16u*)dst;
+ do
+ {
+ *d++ = src[R]*77 + src[1]*150 + src[B]*29;
+ src += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_rgb24_gray16<0,2> color_conv_rgb24_to_gray16;
+ typedef color_conv_rgb24_gray16<2,0> color_conv_bgr24_to_gray16;
+
+
+}
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/include/util/agg_color_conv_rgb8.h b/plugins/Clist_ng/AGG/include/util/agg_color_conv_rgb8.h new file mode 100644 index 0000000000..6a7525cf5e --- /dev/null +++ b/plugins/Clist_ng/AGG/include/util/agg_color_conv_rgb8.h @@ -0,0 +1,478 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+//
+// A set of functors used with color_conv(). See file agg_color_conv.h
+// These functors can convert images with up to 8 bits per component.
+// Use convertors in the following way:
+//
+// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY());
+// whare XXXX and YYYY can be any of:
+// rgb24
+// bgr24
+// rgba32
+// abgr32
+// argb32
+// bgra32
+// rgb555
+// rgb565
+//----------------------------------------------------------------------------
+
+#ifndef AGG_COLOR_CONV_RGB8_INCLUDED
+#define AGG_COLOR_CONV_RGB8_INCLUDED
+
+#include "agg_basics.h"
+#include "agg_color_conv.h"
+
+namespace agg
+{
+
+ //-----------------------------------------------------color_conv_rgb24
+ class color_conv_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *dst++ = src[2];
+ *dst++ = src[1];
+ *dst++ = src[0];
+ src += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_rgb24 color_conv_rgb24_to_bgr24;
+ typedef color_conv_rgb24 color_conv_bgr24_to_rgb24;
+
+ typedef color_conv_same<3> color_conv_bgr24_to_bgr24;
+ typedef color_conv_same<3> color_conv_rgb24_to_rgb24;
+
+
+
+ //------------------------------------------------------color_conv_rgba32
+ template<int I1, int I2, int I3, int I4> class color_conv_rgba32
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *dst++ = src[I1];
+ *dst++ = src[I2];
+ *dst++ = src[I3];
+ *dst++ = src[I4];
+ src += 4;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgba32<0,3,2,1> color_conv_argb32_to_abgr32; //----color_conv_argb32_to_abgr32
+ typedef color_conv_rgba32<3,2,1,0> color_conv_argb32_to_bgra32; //----color_conv_argb32_to_bgra32
+ typedef color_conv_rgba32<1,2,3,0> color_conv_argb32_to_rgba32; //----color_conv_argb32_to_rgba32
+ typedef color_conv_rgba32<3,0,1,2> color_conv_bgra32_to_abgr32; //----color_conv_bgra32_to_abgr32
+ typedef color_conv_rgba32<3,2,1,0> color_conv_bgra32_to_argb32; //----color_conv_bgra32_to_argb32
+ typedef color_conv_rgba32<2,1,0,3> color_conv_bgra32_to_rgba32; //----color_conv_bgra32_to_rgba32
+ typedef color_conv_rgba32<3,2,1,0> color_conv_rgba32_to_abgr32; //----color_conv_rgba32_to_abgr32
+ typedef color_conv_rgba32<3,0,1,2> color_conv_rgba32_to_argb32; //----color_conv_rgba32_to_argb32
+ typedef color_conv_rgba32<2,1,0,3> color_conv_rgba32_to_bgra32; //----color_conv_rgba32_to_bgra32
+ typedef color_conv_rgba32<0,3,2,1> color_conv_abgr32_to_argb32; //----color_conv_abgr32_to_argb32
+ typedef color_conv_rgba32<1,2,3,0> color_conv_abgr32_to_bgra32; //----color_conv_abgr32_to_bgra32
+ typedef color_conv_rgba32<3,2,1,0> color_conv_abgr32_to_rgba32; //----color_conv_abgr32_to_rgba32
+
+ //------------------------------------------------------------------------
+ typedef color_conv_same<4> color_conv_rgba32_to_rgba32; //----color_conv_rgba32_to_rgba32
+ typedef color_conv_same<4> color_conv_argb32_to_argb32; //----color_conv_argb32_to_argb32
+ typedef color_conv_same<4> color_conv_bgra32_to_bgra32; //----color_conv_bgra32_to_bgra32
+ typedef color_conv_same<4> color_conv_abgr32_to_abgr32; //----color_conv_abgr32_to_abgr32
+
+
+ //--------------------------------------------color_conv_rgb24_rgba32
+ template<int I1, int I2, int I3, int A> class color_conv_rgb24_rgba32
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ dst[I1] = *src++;
+ dst[I2] = *src++;
+ dst[I3] = *src++;
+ dst[A] = 255;
+ dst += 4;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_rgb24_to_argb32; //----color_conv_rgb24_to_argb32
+ typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_rgb24_to_abgr32; //----color_conv_rgb24_to_abgr32
+ typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_rgb24_to_bgra32; //----color_conv_rgb24_to_bgra32
+ typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_rgb24_to_rgba32; //----color_conv_rgb24_to_rgba32
+ typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_bgr24_to_argb32; //----color_conv_bgr24_to_argb32
+ typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_bgr24_to_abgr32; //----color_conv_bgr24_to_abgr32
+ typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_bgr24_to_bgra32; //----color_conv_bgr24_to_bgra32
+ typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_bgr24_to_rgba32; //----color_conv_bgr24_to_rgba32
+
+
+
+ //-------------------------------------------------color_conv_rgba32_rgb24
+ template<int I1, int I2, int I3> class color_conv_rgba32_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *dst++ = src[I1];
+ *dst++ = src[I2];
+ *dst++ = src[I3];
+ src += 4;
+ }
+ while(--width);
+ }
+ };
+
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgba32_rgb24<1,2,3> color_conv_argb32_to_rgb24; //----color_conv_argb32_to_rgb24
+ typedef color_conv_rgba32_rgb24<3,2,1> color_conv_abgr32_to_rgb24; //----color_conv_abgr32_to_rgb24
+ typedef color_conv_rgba32_rgb24<2,1,0> color_conv_bgra32_to_rgb24; //----color_conv_bgra32_to_rgb24
+ typedef color_conv_rgba32_rgb24<0,1,2> color_conv_rgba32_to_rgb24; //----color_conv_rgba32_to_rgb24
+ typedef color_conv_rgba32_rgb24<3,2,1> color_conv_argb32_to_bgr24; //----color_conv_argb32_to_bgr24
+ typedef color_conv_rgba32_rgb24<1,2,3> color_conv_abgr32_to_bgr24; //----color_conv_abgr32_to_bgr24
+ typedef color_conv_rgba32_rgb24<0,1,2> color_conv_bgra32_to_bgr24; //----color_conv_bgra32_to_bgr24
+ typedef color_conv_rgba32_rgb24<2,1,0> color_conv_rgba32_to_bgr24; //----color_conv_rgba32_to_bgr24
+
+
+ //------------------------------------------------color_conv_rgb555_rgb24
+ template<int R, int B> class color_conv_rgb555_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ unsigned rgb = *(int16u*)src;
+ dst[R] = (int8u)((rgb >> 7) & 0xF8);
+ dst[1] = (int8u)((rgb >> 2) & 0xF8);
+ dst[B] = (int8u)((rgb << 3) & 0xF8);
+ src += 2;
+ dst += 3;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb555_rgb24<2,0> color_conv_rgb555_to_bgr24; //----color_conv_rgb555_to_bgr24
+ typedef color_conv_rgb555_rgb24<0,2> color_conv_rgb555_to_rgb24; //----color_conv_rgb555_to_rgb24
+
+
+ //-------------------------------------------------color_conv_rgb24_rgb555
+ template<int R, int B> class color_conv_rgb24_rgb555
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) |
+ ((unsigned(src[1]) << 2) & 0x3E0) |
+ ((unsigned(src[B]) >> 3)));
+ src += 3;
+ dst += 2;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb24_rgb555<2,0> color_conv_bgr24_to_rgb555; //----color_conv_bgr24_to_rgb555
+ typedef color_conv_rgb24_rgb555<0,2> color_conv_rgb24_to_rgb555; //----color_conv_rgb24_to_rgb555
+
+
+ //-------------------------------------------------color_conv_rgb565_rgb24
+ template<int R, int B> class color_conv_rgb565_rgb24
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ unsigned rgb = *(int16u*)src;
+ dst[R] = (rgb >> 8) & 0xF8;
+ dst[1] = (rgb >> 3) & 0xFC;
+ dst[B] = (rgb << 3) & 0xF8;
+ src += 2;
+ dst += 3;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb565_rgb24<2,0> color_conv_rgb565_to_bgr24; //----color_conv_rgb565_to_bgr24
+ typedef color_conv_rgb565_rgb24<0,2> color_conv_rgb565_to_rgb24; //----color_conv_rgb565_to_rgb24
+
+
+ //-------------------------------------------------color_conv_rgb24_rgb565
+ template<int R, int B> class color_conv_rgb24_rgb565
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) |
+ ((unsigned(src[1]) << 3) & 0x7E0) |
+ ((unsigned(src[B]) >> 3)));
+ src += 3;
+ dst += 2;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb24_rgb565<2,0> color_conv_bgr24_to_rgb565; //----color_conv_bgr24_to_rgb565
+ typedef color_conv_rgb24_rgb565<0,2> color_conv_rgb24_to_rgb565; //----color_conv_rgb24_to_rgb565
+
+
+
+ //-------------------------------------------------color_conv_rgb555_rgba32
+ template<int R, int G, int B, int A> class color_conv_rgb555_rgba32
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ int rgb = *(int16*)src;
+ dst[R] = (int8u)((rgb >> 7) & 0xF8);
+ dst[G] = (int8u)((rgb >> 2) & 0xF8);
+ dst[B] = (int8u)((rgb << 3) & 0xF8);
+ dst[A] = (int8u)(rgb >> 15);
+ src += 2;
+ dst += 4;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb555_rgba32<1,2,3,0> color_conv_rgb555_to_argb32; //----color_conv_rgb555_to_argb32
+ typedef color_conv_rgb555_rgba32<3,2,1,0> color_conv_rgb555_to_abgr32; //----color_conv_rgb555_to_abgr32
+ typedef color_conv_rgb555_rgba32<2,1,0,3> color_conv_rgb555_to_bgra32; //----color_conv_rgb555_to_bgra32
+ typedef color_conv_rgb555_rgba32<0,1,2,3> color_conv_rgb555_to_rgba32; //----color_conv_rgb555_to_rgba32
+
+
+ //------------------------------------------------color_conv_rgba32_rgb555
+ template<int R, int G, int B, int A> class color_conv_rgba32_rgb555
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) |
+ ((unsigned(src[G]) << 2) & 0x3E0) |
+ ((unsigned(src[B]) >> 3)) |
+ ((unsigned(src[A]) << 8) & 0x8000));
+ src += 4;
+ dst += 2;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgba32_rgb555<1,2,3,0> color_conv_argb32_to_rgb555; //----color_conv_argb32_to_rgb555
+ typedef color_conv_rgba32_rgb555<3,2,1,0> color_conv_abgr32_to_rgb555; //----color_conv_abgr32_to_rgb555
+ typedef color_conv_rgba32_rgb555<2,1,0,3> color_conv_bgra32_to_rgb555; //----color_conv_bgra32_to_rgb555
+ typedef color_conv_rgba32_rgb555<0,1,2,3> color_conv_rgba32_to_rgb555; //----color_conv_rgba32_to_rgb555
+
+
+
+ //------------------------------------------------color_conv_rgb565_rgba32
+ template<int R, int G, int B, int A> class color_conv_rgb565_rgba32
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ int rgb = *(int16*)src;
+ dst[R] = (rgb >> 8) & 0xF8;
+ dst[G] = (rgb >> 3) & 0xFC;
+ dst[B] = (rgb << 3) & 0xF8;
+ dst[A] = 255;
+ src += 2;
+ dst += 4;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgb565_rgba32<1,2,3,0> color_conv_rgb565_to_argb32; //----color_conv_rgb565_to_argb32
+ typedef color_conv_rgb565_rgba32<3,2,1,0> color_conv_rgb565_to_abgr32; //----color_conv_rgb565_to_abgr32
+ typedef color_conv_rgb565_rgba32<2,1,0,3> color_conv_rgb565_to_bgra32; //----color_conv_rgb565_to_bgra32
+ typedef color_conv_rgb565_rgba32<0,1,2,3> color_conv_rgb565_to_rgba32; //----color_conv_rgb565_to_rgba32
+
+
+ //------------------------------------------------color_conv_rgba32_rgb565
+ template<int R, int G, int B> class color_conv_rgba32_rgb565
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) |
+ ((unsigned(src[G]) << 3) & 0x7E0) |
+ ((unsigned(src[B]) >> 3)));
+ src += 4;
+ dst += 2;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_rgba32_rgb565<1,2,3> color_conv_argb32_to_rgb565; //----color_conv_argb32_to_rgb565
+ typedef color_conv_rgba32_rgb565<3,2,1> color_conv_abgr32_to_rgb565; //----color_conv_abgr32_to_rgb565
+ typedef color_conv_rgba32_rgb565<2,1,0> color_conv_bgra32_to_rgb565; //----color_conv_bgra32_to_rgb565
+ typedef color_conv_rgba32_rgb565<0,1,2> color_conv_rgba32_to_rgb565; //----color_conv_rgba32_to_rgb565
+
+
+ //---------------------------------------------color_conv_rgb555_to_rgb565
+ class color_conv_rgb555_to_rgb565
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ unsigned rgb = *(int16u*)src;
+ *(int16u*)dst = (int16u)(((rgb << 1) & 0xFFC0) | (rgb & 0x1F));
+ src += 2;
+ dst += 2;
+ }
+ while(--width);
+ }
+ };
+
+
+ //----------------------------------------------color_conv_rgb565_to_rgb555
+ class color_conv_rgb565_to_rgb555
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ unsigned rgb = *(int16u*)src;
+ *(int16u*)dst = (int16u)(((rgb >> 1) & 0x7FE0) | (rgb & 0x1F));
+ src += 2;
+ dst += 2;
+ }
+ while(--width);
+ }
+ };
+
+
+ //------------------------------------------------------------------------
+ typedef color_conv_same<2> color_conv_rgb555_to_rgb555; //----color_conv_rgb555_to_rgb555
+ typedef color_conv_same<2> color_conv_rgb565_to_rgb565; //----color_conv_rgb565_to_rgb565
+
+
+ template<int R, int B> class color_conv_rgb24_gray8
+ {
+ public:
+ void operator () (int8u* dst,
+ const int8u* src,
+ unsigned width) const
+ {
+ do
+ {
+ *dst++ = (src[R]*77 + src[1]*150 + src[B]*29) >> 8;
+ src += 3;
+ }
+ while(--width);
+ }
+ };
+
+ typedef color_conv_rgb24_gray8<0,2> color_conv_rgb24_to_gray8; //----color_conv_rgb24_to_gray8
+ typedef color_conv_rgb24_gray8<2,0> color_conv_bgr24_to_gray8; //----color_conv_bgr24_to_gray8
+
+
+}
+
+
+
+#endif
diff --git a/plugins/Clist_ng/AGG/src/ChangeLog b/plugins/Clist_ng/AGG/src/ChangeLog new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ChangeLog diff --git a/plugins/Clist_ng/AGG/src/Makefile b/plugins/Clist_ng/AGG/src/Makefile new file mode 100644 index 0000000000..429f66ab8e --- /dev/null +++ b/plugins/Clist_ng/AGG/src/Makefile @@ -0,0 +1,59 @@ +include ../Makefile.in.$(shell uname)
+
+CXXFLAGS= $(AGGCXXFLAGS) -I../include -L./
+
+SRC_CXX=\
+agg_arc.cpp \
+agg_arrowhead.cpp \
+agg_bezier_arc.cpp \
+agg_bspline.cpp \
+agg_curves.cpp \
+agg_vcgen_contour.cpp \
+agg_vcgen_dash.cpp \
+agg_vcgen_markers_term.cpp \
+agg_vcgen_smooth_poly1.cpp \
+agg_vcgen_stroke.cpp \
+agg_vcgen_bspline.cpp \
+agg_gsv_text.cpp \
+agg_image_filters.cpp \
+agg_line_aa_basics.cpp \
+agg_line_profile_aa.cpp \
+agg_rounded_rect.cpp \
+agg_sqrt_tables.cpp \
+agg_embedded_raster_fonts.cpp \
+agg_trans_affine.cpp \
+agg_trans_warp_magnifier.cpp \
+agg_trans_single_path.cpp \
+agg_trans_double_path.cpp \
+agg_vpgen_clip_polygon.cpp \
+agg_vpgen_clip_polyline.cpp \
+agg_vpgen_segmentator.cpp \
+ctrl/agg_cbox_ctrl.cpp \
+ctrl/agg_gamma_ctrl.cpp \
+ctrl/agg_gamma_spline.cpp \
+ctrl/agg_rbox_ctrl.cpp \
+ctrl/agg_slider_ctrl.cpp \
+ctrl/agg_spline_ctrl.cpp \
+ctrl/agg_scale_ctrl.cpp \
+ctrl/agg_polygon_ctrl.cpp \
+ctrl/agg_bezier_ctrl.cpp
+
+SRC_C=\
+../gpc/gpc.c
+
+
+OBJ=$(SRC_CXX:.cpp=.o) $(SRC_C:.c=.o)
+
+all: $(OBJ)
+ $(LIB) libagg.a $(OBJ)
+
+clean:
+ rm -f *.o *.a ctrl/*.o ../gpc/*.o
+ rm -rf SunWS_cache
+ rm -rf ctrl/SunWS_cache
+
+%.o: %.cpp
+ $(CXX) -c $(CXXFLAGS) $*.cpp -o $@
+
+%.o: %.c
+ $(C) -c $(CXXFLAGS) $*.c -o $@
diff --git a/plugins/Clist_ng/AGG/src/Makefile.am b/plugins/Clist_ng/AGG/src/Makefile.am new file mode 100644 index 0000000000..f9a35fb27b --- /dev/null +++ b/plugins/Clist_ng/AGG/src/Makefile.am @@ -0,0 +1,47 @@ +SUBDIRS = ctrl . platform
+
+INCLUDES = -I$(top_srcdir)/include
+
+lib_LTLIBRARIES = libagg.la
+
+libagg_la_LDFLAGS = -no-undefined -version-info @AGG_LIB_VERSION@
+libagg_la_SOURCES = agg_arc.cpp \
+ agg_arrowhead.cpp \
+ agg_bezier_arc.cpp \
+ agg_bspline.cpp \
+ agg_curves.cpp \
+ agg_embedded_raster_fonts.cpp \
+ agg_gsv_text.cpp \
+ agg_image_filters.cpp \
+ agg_line_aa_basics.cpp \
+ agg_line_profile_aa.cpp \
+ agg_rounded_rect.cpp \
+ agg_sqrt_tables.cpp \
+ agg_trans_affine.cpp \
+ agg_trans_double_path.cpp \
+ agg_trans_single_path.cpp \
+ agg_trans_warp_magnifier.cpp \
+ agg_vcgen_bspline.cpp \
+ agg_vcgen_contour.cpp \
+ agg_vcgen_dash.cpp \
+ agg_vcgen_markers_term.cpp \
+ agg_vcgen_smooth_poly1.cpp \
+ agg_vcgen_stroke.cpp \
+ agg_vpgen_clip_polygon.cpp \
+ agg_vpgen_clip_polyline.cpp \
+ agg_vpgen_segmentator.cpp
+
+if ENABLE_GPC
+GPCLD=$(top_builddir)/gpc/libagggpc.la
+else
+GPCLD=
+endif
+
+if ENABLE_CTRL
+CTRLLD=$(top_builddir)/src/ctrl/libaggctrl.la
+else
+CTRLLD=
+endif
+
+libagg_la_LIBADD = $(GPCLD) $(CTRLLD)
+
diff --git a/plugins/Clist_ng/AGG/src/agg_arc.cpp b/plugins/Clist_ng/AGG/src/agg_arc.cpp new file mode 100644 index 0000000000..f97717f584 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_arc.cpp @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_arc.h"
+
+
+namespace agg
+{
+ //------------------------------------------------------------------------
+ arc::arc(double x, double y,
+ double rx, double ry,
+ double a1, double a2,
+ bool ccw) :
+ m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0)
+ {
+ normalize(a1, a2, ccw);
+ }
+
+ //------------------------------------------------------------------------
+ void arc::init(double x, double y,
+ double rx, double ry,
+ double a1, double a2,
+ bool ccw)
+ {
+ m_x = x; m_y = y;
+ m_rx = rx; m_ry = ry;
+ normalize(a1, a2, ccw);
+ }
+
+ //------------------------------------------------------------------------
+ void arc::approximation_scale(double s)
+ {
+ m_scale = s;
+ if(m_initialized)
+ {
+ normalize(m_start, m_end, m_ccw);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void arc::rewind(unsigned)
+ {
+ m_path_cmd = path_cmd_move_to;
+ m_angle = m_start;
+ }
+
+ //------------------------------------------------------------------------
+ unsigned arc::vertex(double* x, double* y)
+ {
+ if(is_stop(m_path_cmd)) return path_cmd_stop;
+ if((m_angle < m_end - m_da/4) != m_ccw)
+ {
+ *x = m_x + cos(m_end) * m_rx;
+ *y = m_y + sin(m_end) * m_ry;
+ m_path_cmd = path_cmd_stop;
+ return path_cmd_line_to;
+ }
+
+ *x = m_x + cos(m_angle) * m_rx;
+ *y = m_y + sin(m_angle) * m_ry;
+
+ m_angle += m_da;
+
+ unsigned pf = m_path_cmd;
+ m_path_cmd = path_cmd_line_to;
+ return pf;
+ }
+
+ //------------------------------------------------------------------------
+ void arc::normalize(double a1, double a2, bool ccw)
+ {
+ double ra = (fabs(m_rx) + fabs(m_ry)) / 2;
+ m_da = acos(ra / (ra + 0.125 / m_scale)) * 2;
+ if(ccw)
+ {
+ while(a2 < a1) a2 += pi * 2.0;
+ }
+ else
+ {
+ while(a1 < a2) a1 += pi * 2.0;
+ m_da = -m_da;
+ }
+ m_ccw = ccw;
+ m_start = a1;
+ m_end = a2;
+ m_initialized = true;
+ }
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_arrowhead.cpp b/plugins/Clist_ng/AGG/src/agg_arrowhead.cpp new file mode 100644 index 0000000000..47a6572a8d --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_arrowhead.cpp @@ -0,0 +1,115 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_arrowhead.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ arrowhead::arrowhead() :
+ m_head_d1(1.0),
+ m_head_d2(1.0),
+ m_head_d3(1.0),
+ m_head_d4(0.0),
+ m_tail_d1(1.0),
+ m_tail_d2(1.0),
+ m_tail_d3(1.0),
+ m_tail_d4(0.0),
+ m_head_flag(false),
+ m_tail_flag(false),
+ m_curr_id(0),
+ m_curr_coord(0)
+ {
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void arrowhead::rewind(unsigned path_id)
+ {
+ m_curr_id = path_id;
+ m_curr_coord = 0;
+ if(path_id == 0)
+ {
+ if(!m_tail_flag)
+ {
+ m_cmd[0] = path_cmd_stop;
+ return;
+ }
+ m_coord[0] = m_tail_d1; m_coord[1] = 0.0;
+ m_coord[2] = m_tail_d1 - m_tail_d4; m_coord[3] = m_tail_d3;
+ m_coord[4] = -m_tail_d2 - m_tail_d4; m_coord[5] = m_tail_d3;
+ m_coord[6] = -m_tail_d2; m_coord[7] = 0.0;
+ m_coord[8] = -m_tail_d2 - m_tail_d4; m_coord[9] = -m_tail_d3;
+ m_coord[10] = m_tail_d1 - m_tail_d4; m_coord[11] = -m_tail_d3;
+
+ m_cmd[0] = path_cmd_move_to;
+ m_cmd[1] = path_cmd_line_to;
+ m_cmd[2] = path_cmd_line_to;
+ m_cmd[3] = path_cmd_line_to;
+ m_cmd[4] = path_cmd_line_to;
+ m_cmd[5] = path_cmd_line_to;
+ m_cmd[7] = path_cmd_end_poly | path_flags_close | path_flags_ccw;
+ m_cmd[6] = path_cmd_stop;
+ return;
+ }
+
+ if(path_id == 1)
+ {
+ if(!m_head_flag)
+ {
+ m_cmd[0] = path_cmd_stop;
+ return;
+ }
+ m_coord[0] = -m_head_d1; m_coord[1] = 0.0;
+ m_coord[2] = m_head_d2 + m_head_d4; m_coord[3] = -m_head_d3;
+ m_coord[4] = m_head_d2; m_coord[5] = 0.0;
+ m_coord[6] = m_head_d2 + m_head_d4; m_coord[7] = m_head_d3;
+
+ m_cmd[0] = path_cmd_move_to;
+ m_cmd[1] = path_cmd_line_to;
+ m_cmd[2] = path_cmd_line_to;
+ m_cmd[3] = path_cmd_line_to;
+ m_cmd[4] = path_cmd_end_poly | path_flags_close | path_flags_ccw;
+ m_cmd[5] = path_cmd_stop;
+ return;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned arrowhead::vertex(double* x, double* y)
+ {
+ if(m_curr_id < 2)
+ {
+ unsigned curr_idx = m_curr_coord * 2;
+ *x = m_coord[curr_idx];
+ *y = m_coord[curr_idx + 1];
+ return m_cmd[m_curr_coord++];
+ }
+ return path_cmd_stop;
+ }
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_bezier_arc.cpp b/plugins/Clist_ng/AGG/src/agg_bezier_arc.cpp new file mode 100644 index 0000000000..2140783ac6 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_bezier_arc.cpp @@ -0,0 +1,261 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_bezier_arc.h"
+
+
+namespace agg
+{
+
+ // This epsilon is used to prevent us from adding degenerate curves
+ // (converging to a single point).
+ // The value isn't very critical. Function arc_to_bezier() has a limit
+ // of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve
+ // becomes inaccurate. But slight exceeding is quite appropriate.
+ //-------------------------------------------------bezier_arc_angle_epsilon
+ const double bezier_arc_angle_epsilon = 0.01;
+
+ //------------------------------------------------------------arc_to_bezier
+ void arc_to_bezier(double cx, double cy, double rx, double ry,
+ double start_angle, double sweep_angle,
+ double* curve)
+ {
+ double x0 = cos(sweep_angle / 2.0);
+ double y0 = sin(sweep_angle / 2.0);
+ double tx = (1.0 - x0) * 4.0 / 3.0;
+ double ty = y0 - tx * x0 / y0;
+ double px[4];
+ double py[4];
+ px[0] = x0;
+ py[0] = -y0;
+ px[1] = x0 + tx;
+ py[1] = -ty;
+ px[2] = x0 + tx;
+ py[2] = ty;
+ px[3] = x0;
+ py[3] = y0;
+
+ double sn = sin(start_angle + sweep_angle / 2.0);
+ double cs = cos(start_angle + sweep_angle / 2.0);
+
+ unsigned i;
+ for(i = 0; i < 4; i++)
+ {
+ curve[i * 2] = cx + rx * (px[i] * cs - py[i] * sn);
+ curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs);
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void bezier_arc::init(double x, double y,
+ double rx, double ry,
+ double start_angle,
+ double sweep_angle)
+ {
+ start_angle = fmod(start_angle, 2.0 * pi);
+ if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi;
+ if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi;
+
+ if(fabs(sweep_angle) < 1e-10)
+ {
+ m_num_vertices = 4;
+ m_cmd = path_cmd_line_to;
+ m_vertices[0] = x + rx * cos(start_angle);
+ m_vertices[1] = y + ry * sin(start_angle);
+ m_vertices[2] = x + rx * cos(start_angle + sweep_angle);
+ m_vertices[3] = y + ry * sin(start_angle + sweep_angle);
+ return;
+ }
+
+ double total_sweep = 0.0;
+ double local_sweep = 0.0;
+ double prev_sweep;
+ m_num_vertices = 2;
+ m_cmd = path_cmd_curve4;
+ bool done = false;
+ do
+ {
+ if(sweep_angle < 0.0)
+ {
+ prev_sweep = total_sweep;
+ local_sweep = -pi * 0.5;
+ total_sweep -= pi * 0.5;
+ if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon)
+ {
+ local_sweep = sweep_angle - prev_sweep;
+ done = true;
+ }
+ }
+ else
+ {
+ prev_sweep = total_sweep;
+ local_sweep = pi * 0.5;
+ total_sweep += pi * 0.5;
+ if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon)
+ {
+ local_sweep = sweep_angle - prev_sweep;
+ done = true;
+ }
+ }
+
+ arc_to_bezier(x, y, rx, ry,
+ start_angle,
+ local_sweep,
+ m_vertices + m_num_vertices - 2);
+
+ m_num_vertices += 6;
+ start_angle += local_sweep;
+ }
+ while(!done && m_num_vertices < 26);
+ }
+
+
+
+
+ //--------------------------------------------------------------------
+ void bezier_arc_svg::init(double x0, double y0,
+ double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double x2, double y2)
+ {
+ m_radii_ok = true;
+
+ if(rx < 0.0) rx = -rx;
+ if(ry < 0.0) ry = -rx;
+
+ // Calculate the middle point between
+ // the current and the final points
+ //------------------------
+ double dx2 = (x0 - x2) / 2.0;
+ double dy2 = (y0 - y2) / 2.0;
+
+ double cos_a = cos(angle);
+ double sin_a = sin(angle);
+
+ // Calculate (x1, y1)
+ //------------------------
+ double x1 = cos_a * dx2 + sin_a * dy2;
+ double y1 = -sin_a * dx2 + cos_a * dy2;
+
+ // Ensure radii are large enough
+ //------------------------
+ double prx = rx * rx;
+ double pry = ry * ry;
+ double px1 = x1 * x1;
+ double py1 = y1 * y1;
+
+ // Check that radii are large enough
+ //------------------------
+ double radii_check = px1/prx + py1/pry;
+ if(radii_check > 1.0)
+ {
+ rx = sqrt(radii_check) * rx;
+ ry = sqrt(radii_check) * ry;
+ prx = rx * rx;
+ pry = ry * ry;
+ if(radii_check > 10.0) m_radii_ok = false;
+ }
+
+ // Calculate (cx1, cy1)
+ //------------------------
+ double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0;
+ double sq = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1);
+ double coef = sign * sqrt((sq < 0) ? 0 : sq);
+ double cx1 = coef * ((rx * y1) / ry);
+ double cy1 = coef * -((ry * x1) / rx);
+
+ //
+ // Calculate (cx, cy) from (cx1, cy1)
+ //------------------------
+ double sx2 = (x0 + x2) / 2.0;
+ double sy2 = (y0 + y2) / 2.0;
+ double cx = sx2 + (cos_a * cx1 - sin_a * cy1);
+ double cy = sy2 + (sin_a * cx1 + cos_a * cy1);
+
+ // Calculate the start_angle (angle1) and the sweep_angle (dangle)
+ //------------------------
+ double ux = (x1 - cx1) / rx;
+ double uy = (y1 - cy1) / ry;
+ double vx = (-x1 - cx1) / rx;
+ double vy = (-y1 - cy1) / ry;
+ double p, n;
+
+ // Calculate the angle start
+ //------------------------
+ n = sqrt(ux*ux + uy*uy);
+ p = ux; // (1 * ux) + (0 * uy)
+ sign = (uy < 0) ? -1.0 : 1.0;
+ double v = p / n;
+ if(v < -1.0) v = -1.0;
+ if(v > 1.0) v = 1.0;
+ double start_angle = sign * acos(v);
+
+ // Calculate the sweep angle
+ //------------------------
+ n = sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy));
+ p = ux * vx + uy * vy;
+ sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0;
+ v = p / n;
+ if(v < -1.0) v = -1.0;
+ if(v > 1.0) v = 1.0;
+ double sweep_angle = sign * acos(v);
+ if(!sweep_flag && sweep_angle > 0)
+ {
+ sweep_angle -= pi * 2.0;
+ }
+ else
+ if (sweep_flag && sweep_angle < 0)
+ {
+ sweep_angle += pi * 2.0;
+ }
+
+ // We can now build and transform the resulting arc
+ //------------------------
+ m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle);
+ trans_affine mtx = trans_affine_rotation(angle);
+ mtx *= trans_affine_translation(cx, cy);
+
+ for(unsigned i = 2; i < m_arc.num_vertices()-2; i += 2)
+ {
+ mtx.transform(m_arc.vertices() + i, m_arc.vertices() + i + 1);
+ }
+
+ // We must make sure that the starting and ending points
+ // exactly coincide with the initial (x0,y0) and (x2,y2)
+ m_arc.vertices()[0] = x0;
+ m_arc.vertices()[1] = y0;
+ if(m_arc.num_vertices() > 2)
+ {
+ m_arc.vertices()[m_arc.num_vertices() - 2] = x2;
+ m_arc.vertices()[m_arc.num_vertices() - 1] = y2;
+ }
+ }
+
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_bspline.cpp b/plugins/Clist_ng/AGG/src/agg_bspline.cpp new file mode 100644 index 0000000000..85bdfa969e --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_bspline.cpp @@ -0,0 +1,289 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_bspline.h"
+
+namespace agg
+{
+ //------------------------------------------------------------------------
+ bspline::bspline() :
+ m_max(0),
+ m_num(0),
+ m_x(0),
+ m_y(0),
+ m_last_idx(-1)
+ {
+ }
+
+ //------------------------------------------------------------------------
+ bspline::bspline(int num) :
+ m_max(0),
+ m_num(0),
+ m_x(0),
+ m_y(0),
+ m_last_idx(-1)
+ {
+ init(num);
+ }
+
+ //------------------------------------------------------------------------
+ bspline::bspline(int num, const double* x, const double* y) :
+ m_max(0),
+ m_num(0),
+ m_x(0),
+ m_y(0),
+ m_last_idx(-1)
+ {
+ init(num, x, y);
+ }
+
+
+ //------------------------------------------------------------------------
+ void bspline::init(int max)
+ {
+ if(max > 2 && max > m_max)
+ {
+ m_am.resize(max * 3);
+ m_max = max;
+ m_x = &m_am[m_max];
+ m_y = &m_am[m_max * 2];
+ }
+ m_num = 0;
+ m_last_idx = -1;
+ }
+
+
+ //------------------------------------------------------------------------
+ void bspline::add_point(double x, double y)
+ {
+ if(m_num < m_max)
+ {
+ m_x[m_num] = x;
+ m_y[m_num] = y;
+ ++m_num;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void bspline::prepare()
+ {
+ if(m_num > 2)
+ {
+ int i, k, n1;
+ double* temp;
+ double* r;
+ double* s;
+ double h, p, d, f, e;
+
+ for(k = 0; k < m_num; k++)
+ {
+ m_am[k] = 0.0;
+ }
+
+ n1 = 3 * m_num;
+
+ pod_array<double> al(n1);
+ temp = &al[0];
+
+ for(k = 0; k < n1; k++)
+ {
+ temp[k] = 0.0;
+ }
+
+ r = temp + m_num;
+ s = temp + m_num * 2;
+
+ n1 = m_num - 1;
+ d = m_x[1] - m_x[0];
+ e = (m_y[1] - m_y[0]) / d;
+
+ for(k = 1; k < n1; k++)
+ {
+ h = d;
+ d = m_x[k + 1] - m_x[k];
+ f = e;
+ e = (m_y[k + 1] - m_y[k]) / d;
+ al[k] = d / (d + h);
+ r[k] = 1.0 - al[k];
+ s[k] = 6.0 * (e - f) / (h + d);
+ }
+
+ for(k = 1; k < n1; k++)
+ {
+ p = 1.0 / (r[k] * al[k - 1] + 2.0);
+ al[k] *= -p;
+ s[k] = (s[k] - r[k] * s[k - 1]) * p;
+ }
+
+ m_am[n1] = 0.0;
+ al[n1 - 1] = s[n1 - 1];
+ m_am[n1 - 1] = al[n1 - 1];
+
+ for(k = n1 - 2, i = 0; i < m_num - 2; i++, k--)
+ {
+ al[k] = al[k] * al[k + 1] + s[k];
+ m_am[k] = al[k];
+ }
+ }
+ m_last_idx = -1;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void bspline::init(int num, const double* x, const double* y)
+ {
+ if(num > 2)
+ {
+ init(num);
+ int i;
+ for(i = 0; i < num; i++)
+ {
+ add_point(*x++, *y++);
+ }
+ prepare();
+ }
+ m_last_idx = -1;
+ }
+
+
+ //------------------------------------------------------------------------
+ void bspline::bsearch(int n, const double *x, double x0, int *i)
+ {
+ int j = n - 1;
+ int k;
+
+ for(*i = 0; (j - *i) > 1; )
+ {
+ if(x0 < x[k = (*i + j) >> 1]) j = k;
+ else *i = k;
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ double bspline::interpolation(double x, int i) const
+ {
+ int j = i + 1;
+ double d = m_x[i] - m_x[j];
+ double h = x - m_x[j];
+ double r = m_x[i] - x;
+ double p = d * d / 6.0;
+ return (m_am[j] * r * r * r + m_am[i] * h * h * h) / 6.0 / d +
+ ((m_y[j] - m_am[j] * p) * r + (m_y[i] - m_am[i] * p) * h) / d;
+ }
+
+
+ //------------------------------------------------------------------------
+ double bspline::extrapolation_left(double x) const
+ {
+ double d = m_x[1] - m_x[0];
+ return (-d * m_am[1] / 6 + (m_y[1] - m_y[0]) / d) *
+ (x - m_x[0]) +
+ m_y[0];
+ }
+
+ //------------------------------------------------------------------------
+ double bspline::extrapolation_right(double x) const
+ {
+ double d = m_x[m_num - 1] - m_x[m_num - 2];
+ return (d * m_am[m_num - 2] / 6 + (m_y[m_num - 1] - m_y[m_num - 2]) / d) *
+ (x - m_x[m_num - 1]) +
+ m_y[m_num - 1];
+ }
+
+ //------------------------------------------------------------------------
+ double bspline::get(double x) const
+ {
+ if(m_num > 2)
+ {
+ int i;
+
+ // Extrapolation on the left
+ if(x < m_x[0]) return extrapolation_left(x);
+
+ // Extrapolation on the right
+ if(x >= m_x[m_num - 1]) return extrapolation_right(x);
+
+ // Interpolation
+ bsearch(m_num, m_x, x, &i);
+ return interpolation(x, i);
+ }
+ return 0.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ double bspline::get_stateful(double x) const
+ {
+ if(m_num > 2)
+ {
+ // Extrapolation on the left
+ if(x < m_x[0]) return extrapolation_left(x);
+
+ // Extrapolation on the right
+ if(x >= m_x[m_num - 1]) return extrapolation_right(x);
+
+ if(m_last_idx >= 0)
+ {
+ // Check if x is not in current range
+ if(x < m_x[m_last_idx] || x > m_x[m_last_idx + 1])
+ {
+ // Check if x between next points (most probably)
+ if(m_last_idx < m_num - 2 &&
+ x >= m_x[m_last_idx + 1] &&
+ x <= m_x[m_last_idx + 2])
+ {
+ ++m_last_idx;
+ }
+ else
+ if(m_last_idx > 0 &&
+ x >= m_x[m_last_idx - 1] &&
+ x <= m_x[m_last_idx])
+ {
+ // x is between pevious points
+ --m_last_idx;
+ }
+ else
+ {
+ // Else perform full search
+ bsearch(m_num, m_x, x, &m_last_idx);
+ }
+ }
+ return interpolation(x, m_last_idx);
+ }
+ else
+ {
+ // Interpolation
+ bsearch(m_num, m_x, x, &m_last_idx);
+ return interpolation(x, m_last_idx);
+ }
+ }
+ return 0.0;
+ }
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_curves.cpp b/plugins/Clist_ng/AGG/src/agg_curves.cpp new file mode 100644 index 0000000000..eec67d21f3 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_curves.cpp @@ -0,0 +1,620 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_curves.h"
+#include "agg_math.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ const double curve_distance_epsilon = 1e-30;
+ const double curve_collinearity_epsilon = 1e-30;
+ const double curve_angle_tolerance_epsilon = 0.01;
+ enum curve_recursion_limit_e { curve_recursion_limit = 32 };
+
+
+
+ //------------------------------------------------------------------------
+ void curve3_inc::approximation_scale(double s)
+ {
+ m_scale = s;
+ }
+
+ //------------------------------------------------------------------------
+ double curve3_inc::approximation_scale() const
+ {
+ return m_scale;
+ }
+
+ //------------------------------------------------------------------------
+ void curve3_inc::init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ m_start_x = x1;
+ m_start_y = y1;
+ m_end_x = x3;
+ m_end_y = y3;
+
+ double dx1 = x2 - x1;
+ double dy1 = y2 - y1;
+ double dx2 = x3 - x2;
+ double dy2 = y3 - y2;
+
+ double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2);
+
+ m_num_steps = uround(len * 0.25 * m_scale);
+
+ if(m_num_steps < 4)
+ {
+ m_num_steps = 4;
+ }
+
+ double subdivide_step = 1.0 / m_num_steps;
+ double subdivide_step2 = subdivide_step * subdivide_step;
+
+ double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2;
+ double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2;
+
+ m_saved_fx = m_fx = x1;
+ m_saved_fy = m_fy = y1;
+
+ m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step);
+ m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step);
+
+ m_ddfx = tmpx * 2.0;
+ m_ddfy = tmpy * 2.0;
+
+ m_step = m_num_steps;
+ }
+
+ //------------------------------------------------------------------------
+ void curve3_inc::rewind(unsigned)
+ {
+ if(m_num_steps == 0)
+ {
+ m_step = -1;
+ return;
+ }
+ m_step = m_num_steps;
+ m_fx = m_saved_fx;
+ m_fy = m_saved_fy;
+ m_dfx = m_saved_dfx;
+ m_dfy = m_saved_dfy;
+ }
+
+ //------------------------------------------------------------------------
+ unsigned curve3_inc::vertex(double* x, double* y)
+ {
+ if(m_step < 0) return path_cmd_stop;
+ if(m_step == m_num_steps)
+ {
+ *x = m_start_x;
+ *y = m_start_y;
+ --m_step;
+ return path_cmd_move_to;
+ }
+ if(m_step == 0)
+ {
+ *x = m_end_x;
+ *y = m_end_y;
+ --m_step;
+ return path_cmd_line_to;
+ }
+ m_fx += m_dfx;
+ m_fy += m_dfy;
+ m_dfx += m_ddfx;
+ m_dfy += m_ddfy;
+ *x = m_fx;
+ *y = m_fy;
+ --m_step;
+ return path_cmd_line_to;
+ }
+
+ //------------------------------------------------------------------------
+ void curve3_div::init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ m_points.remove_all();
+ m_distance_tolerance_square = 0.5 / m_approximation_scale;
+ m_distance_tolerance_square *= m_distance_tolerance_square;
+ bezier(x1, y1, x2, y2, x3, y3);
+ m_count = 0;
+ }
+
+ //------------------------------------------------------------------------
+ void curve3_div::recursive_bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ unsigned level)
+ {
+ if(level > curve_recursion_limit)
+ {
+ return;
+ }
+
+ // Calculate all the mid-points of the line segments
+ //----------------------
+ double x12 = (x1 + x2) / 2;
+ double y12 = (y1 + y2) / 2;
+ double x23 = (x2 + x3) / 2;
+ double y23 = (y2 + y3) / 2;
+ double x123 = (x12 + x23) / 2;
+ double y123 = (y12 + y23) / 2;
+
+ double dx = x3-x1;
+ double dy = y3-y1;
+ double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx));
+ double da;
+
+ if(d > curve_collinearity_epsilon)
+ {
+ // Regular case
+ //-----------------
+ if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy))
+ {
+ // If the curvature doesn't exceed the distance_tolerance value
+ // we tend to finish subdivisions.
+ //----------------------
+ if(m_angle_tolerance < curve_angle_tolerance_epsilon)
+ {
+ m_points.add(point_d(x123, y123));
+ return;
+ }
+
+ // Angle & Cusp Condition
+ //----------------------
+ da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
+ if(da >= pi) da = 2*pi - da;
+
+ if(da < m_angle_tolerance)
+ {
+ // Finally we can stop the recursion
+ //----------------------
+ m_points.add(point_d(x123, y123));
+ return;
+ }
+ }
+ }
+ else
+ {
+ // Collinear case
+ //------------------
+ da = dx*dx + dy*dy;
+ if(da == 0)
+ {
+ d = calc_sq_distance(x1, y1, x2, y2);
+ }
+ else
+ {
+ d = ((x2 - x1)*dx + (y2 - y1)*dy) / da;
+ if(d > 0 && d < 1)
+ {
+ // Simple collinear case, 1---2---3
+ // We can leave just two endpoints
+ return;
+ }
+ if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1);
+ else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3);
+ else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy);
+ }
+ if(d < m_distance_tolerance_square)
+ {
+ m_points.add(point_d(x2, y2));
+ return;
+ }
+ }
+
+ // Continue subdivision
+ //----------------------
+ recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1);
+ recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1);
+ }
+
+ //------------------------------------------------------------------------
+ void curve3_div::bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ m_points.add(point_d(x1, y1));
+ recursive_bezier(x1, y1, x2, y2, x3, y3, 0);
+ m_points.add(point_d(x3, y3));
+ }
+
+
+
+
+
+ //------------------------------------------------------------------------
+ void curve4_inc::approximation_scale(double s)
+ {
+ m_scale = s;
+ }
+
+ //------------------------------------------------------------------------
+ double curve4_inc::approximation_scale() const
+ {
+ return m_scale;
+ }
+
+ //------------------------------------------------------------------------
+ static double MSC60_fix_ICE(double v) { return v; }
+
+ //------------------------------------------------------------------------
+ void curve4_inc::init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ m_start_x = x1;
+ m_start_y = y1;
+ m_end_x = x4;
+ m_end_y = y4;
+
+ double dx1 = x2 - x1;
+ double dy1 = y2 - y1;
+ double dx2 = x3 - x2;
+ double dy2 = y3 - y2;
+ double dx3 = x4 - x3;
+ double dy3 = y4 - y3;
+
+ double len = (sqrt(dx1 * dx1 + dy1 * dy1) +
+ sqrt(dx2 * dx2 + dy2 * dy2) +
+ sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale;
+
+#if defined(_MSC_VER) && _MSC_VER <= 1200
+ m_num_steps = uround(MSC60_fix_ICE(len));
+#else
+ m_num_steps = uround(len);
+#endif
+
+ if(m_num_steps < 4)
+ {
+ m_num_steps = 4;
+ }
+
+ double subdivide_step = 1.0 / m_num_steps;
+ double subdivide_step2 = subdivide_step * subdivide_step;
+ double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step;
+
+ double pre1 = 3.0 * subdivide_step;
+ double pre2 = 3.0 * subdivide_step2;
+ double pre4 = 6.0 * subdivide_step2;
+ double pre5 = 6.0 * subdivide_step3;
+
+ double tmp1x = x1 - x2 * 2.0 + x3;
+ double tmp1y = y1 - y2 * 2.0 + y3;
+
+ double tmp2x = (x2 - x3) * 3.0 - x1 + x4;
+ double tmp2y = (y2 - y3) * 3.0 - y1 + y4;
+
+ m_saved_fx = m_fx = x1;
+ m_saved_fy = m_fy = y1;
+
+ m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3;
+ m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3;
+
+ m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5;
+ m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5;
+
+ m_dddfx = tmp2x * pre5;
+ m_dddfy = tmp2y * pre5;
+
+ m_step = m_num_steps;
+ }
+
+ //------------------------------------------------------------------------
+ void curve4_inc::rewind(unsigned)
+ {
+ if(m_num_steps == 0)
+ {
+ m_step = -1;
+ return;
+ }
+ m_step = m_num_steps;
+ m_fx = m_saved_fx;
+ m_fy = m_saved_fy;
+ m_dfx = m_saved_dfx;
+ m_dfy = m_saved_dfy;
+ m_ddfx = m_saved_ddfx;
+ m_ddfy = m_saved_ddfy;
+ }
+
+ //------------------------------------------------------------------------
+ unsigned curve4_inc::vertex(double* x, double* y)
+ {
+ if(m_step < 0) return path_cmd_stop;
+ if(m_step == m_num_steps)
+ {
+ *x = m_start_x;
+ *y = m_start_y;
+ --m_step;
+ return path_cmd_move_to;
+ }
+
+ if(m_step == 0)
+ {
+ *x = m_end_x;
+ *y = m_end_y;
+ --m_step;
+ return path_cmd_line_to;
+ }
+
+ m_fx += m_dfx;
+ m_fy += m_dfy;
+ m_dfx += m_ddfx;
+ m_dfy += m_ddfy;
+ m_ddfx += m_dddfx;
+ m_ddfy += m_dddfy;
+
+ *x = m_fx;
+ *y = m_fy;
+ --m_step;
+ return path_cmd_line_to;
+ }
+
+
+
+
+ //------------------------------------------------------------------------
+ void curve4_div::init(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ m_points.remove_all();
+ m_distance_tolerance_square = 0.5 / m_approximation_scale;
+ m_distance_tolerance_square *= m_distance_tolerance_square;
+ bezier(x1, y1, x2, y2, x3, y3, x4, y4);
+ m_count = 0;
+ }
+
+ //------------------------------------------------------------------------
+ void curve4_div::recursive_bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4,
+ unsigned level)
+ {
+ if(level > curve_recursion_limit)
+ {
+ return;
+ }
+
+ // Calculate all the mid-points of the line segments
+ //----------------------
+ double x12 = (x1 + x2) / 2;
+ double y12 = (y1 + y2) / 2;
+ double x23 = (x2 + x3) / 2;
+ double y23 = (y2 + y3) / 2;
+ double x34 = (x3 + x4) / 2;
+ double y34 = (y3 + y4) / 2;
+ double x123 = (x12 + x23) / 2;
+ double y123 = (y12 + y23) / 2;
+ double x234 = (x23 + x34) / 2;
+ double y234 = (y23 + y34) / 2;
+ double x1234 = (x123 + x234) / 2;
+ double y1234 = (y123 + y234) / 2;
+
+
+ // Try to approximate the full cubic curve by a single straight line
+ //------------------
+ double dx = x4-x1;
+ double dy = y4-y1;
+
+ double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx));
+ double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx));
+ double da1, da2, k;
+
+ switch((int(d2 > curve_collinearity_epsilon) << 1) +
+ int(d3 > curve_collinearity_epsilon))
+ {
+ case 0:
+ // All collinear OR p1==p4
+ //----------------------
+ k = dx*dx + dy*dy;
+ if(k == 0)
+ {
+ d2 = calc_sq_distance(x1, y1, x2, y2);
+ d3 = calc_sq_distance(x4, y4, x3, y3);
+ }
+ else
+ {
+ k = 1 / k;
+ da1 = x2 - x1;
+ da2 = y2 - y1;
+ d2 = k * (da1*dx + da2*dy);
+ da1 = x3 - x1;
+ da2 = y3 - y1;
+ d3 = k * (da1*dx + da2*dy);
+ if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
+ {
+ // Simple collinear case, 1---2---3---4
+ // We can leave just two endpoints
+ return;
+ }
+ if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1);
+ else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4);
+ else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy);
+
+ if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1);
+ else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4);
+ else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy);
+ }
+ if(d2 > d3)
+ {
+ if(d2 < m_distance_tolerance_square)
+ {
+ m_points.add(point_d(x2, y2));
+ return;
+ }
+ }
+ else
+ {
+ if(d3 < m_distance_tolerance_square)
+ {
+ m_points.add(point_d(x3, y3));
+ return;
+ }
+ }
+ break;
+
+ case 1:
+ // p1,p2,p4 are collinear, p3 is significant
+ //----------------------
+ if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
+ {
+ if(m_angle_tolerance < curve_angle_tolerance_epsilon)
+ {
+ m_points.add(point_d(x23, y23));
+ return;
+ }
+
+ // Angle Condition
+ //----------------------
+ da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2));
+ if(da1 >= pi) da1 = 2*pi - da1;
+
+ if(da1 < m_angle_tolerance)
+ {
+ m_points.add(point_d(x2, y2));
+ m_points.add(point_d(x3, y3));
+ return;
+ }
+
+ if(m_cusp_limit != 0.0)
+ {
+ if(da1 > m_cusp_limit)
+ {
+ m_points.add(point_d(x3, y3));
+ return;
+ }
+ }
+ }
+ break;
+
+ case 2:
+ // p1,p3,p4 are collinear, p2 is significant
+ //----------------------
+ if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
+ {
+ if(m_angle_tolerance < curve_angle_tolerance_epsilon)
+ {
+ m_points.add(point_d(x23, y23));
+ return;
+ }
+
+ // Angle Condition
+ //----------------------
+ da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
+ if(da1 >= pi) da1 = 2*pi - da1;
+
+ if(da1 < m_angle_tolerance)
+ {
+ m_points.add(point_d(x2, y2));
+ m_points.add(point_d(x3, y3));
+ return;
+ }
+
+ if(m_cusp_limit != 0.0)
+ {
+ if(da1 > m_cusp_limit)
+ {
+ m_points.add(point_d(x2, y2));
+ return;
+ }
+ }
+ }
+ break;
+
+ case 3:
+ // Regular case
+ //-----------------
+ if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
+ {
+ // If the curvature doesn't exceed the distance_tolerance value
+ // we tend to finish subdivisions.
+ //----------------------
+ if(m_angle_tolerance < curve_angle_tolerance_epsilon)
+ {
+ m_points.add(point_d(x23, y23));
+ return;
+ }
+
+ // Angle & Cusp Condition
+ //----------------------
+ k = atan2(y3 - y2, x3 - x2);
+ da1 = fabs(k - atan2(y2 - y1, x2 - x1));
+ da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
+ if(da1 >= pi) da1 = 2*pi - da1;
+ if(da2 >= pi) da2 = 2*pi - da2;
+
+ if(da1 + da2 < m_angle_tolerance)
+ {
+ // Finally we can stop the recursion
+ //----------------------
+ m_points.add(point_d(x23, y23));
+ return;
+ }
+
+ if(m_cusp_limit != 0.0)
+ {
+ if(da1 > m_cusp_limit)
+ {
+ m_points.add(point_d(x2, y2));
+ return;
+ }
+
+ if(da2 > m_cusp_limit)
+ {
+ m_points.add(point_d(x3, y3));
+ return;
+ }
+ }
+ }
+ break;
+ }
+
+ // Continue subdivision
+ //----------------------
+ recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
+ recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
+ }
+
+ //------------------------------------------------------------------------
+ void curve4_div::bezier(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ m_points.add(point_d(x1, y1));
+ recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0);
+ m_points.add(point_d(x4, y4));
+ }
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_font_win32_tt.cpp b/plugins/Clist_ng/AGG/src/agg_font_win32_tt.cpp new file mode 100644 index 0000000000..d2cf10aee1 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_font_win32_tt.cpp @@ -0,0 +1,946 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include "agg_font_win32_tt.h"
+#include "agg_bitset_iterator.h"
+#include "agg_renderer_scanline.h"
+
+#ifdef AGG_WIN9X_COMPLIANT
+#define GetGlyphOutlineX GetGlyphOutline
+#else
+#define GetGlyphOutlineX GetGlyphOutlineW
+#endif
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------------
+ //
+ // This code implements the AUTODIN II polynomial
+ // The variable corresponding to the macro argument "crc" should
+ // be an unsigned long.
+ // Oroginal code by Spencer Garrett <srg@quick.com>
+ //
+
+ // generated using the AUTODIN II polynomial
+ // x^32 + x^26 + x^23 + x^22 + x^16 +
+ // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ //
+ //------------------------------------------------------------------------------
+
+ static const unsigned crc32tab[256] =
+ {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+ };
+
+ //------------------------------------------------------------------------------
+ static unsigned calc_crc32(const unsigned char* buf, unsigned size)
+ {
+ unsigned crc = (unsigned)~0;
+ const unsigned char* p;
+ unsigned len = 0;
+ unsigned nr = size;
+
+ for (len += nr, p = buf; nr--; ++p)
+ {
+ crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff];
+ }
+ return ~crc;
+ }
+
+ //------------------------------------------------------------------------
+ static inline FIXED dbl_to_fx(double d)
+ {
+ int l;
+ l = int(d * 65536.0);
+ return *(FIXED*)&l;
+ }
+
+ //------------------------------------------------------------------------
+ static inline int dbl_to_plain_fx(double d)
+ {
+ return int(d * 65536.0);
+ }
+
+ //------------------------------------------------------------------------
+ static inline FIXED negate_fx(const FIXED& fx)
+ {
+ int l = -(*(int*)(&fx));
+ return *(FIXED*)&l;
+ }
+
+ //------------------------------------------------------------------------
+ static inline double fx_to_dbl(const FIXED& p)
+ {
+ return double(p.value) + double(p.fract) * (1.0 / 65536.0);
+ }
+
+ //------------------------------------------------------------------------
+ static inline int fx_to_plain_int(const FIXED& fx)
+ {
+ return *(int*)(&fx);
+ }
+
+ //------------------------------------------------------------------------
+ static inline int fx_to_int26p6(const FIXED& p)
+ {
+ return (int(p.value) << 6) + (int(p.fract) >> 10);
+ }
+
+ //------------------------------------------------------------------------
+ static inline int dbl_to_int26p6(double p)
+ {
+ return int(p * 64.0 + 0.5);
+ }
+
+ //------------------------------------------------------------------------
+ template<class Scanline, class ScanlineStorage>
+ void decompose_win32_glyph_bitmap_mono(const char* gbuf,
+ int w, int h,
+ int x, int y,
+ bool flip_y,
+ Scanline& sl,
+ ScanlineStorage& storage)
+ {
+ int i;
+ int pitch = ((w + 31) >> 5) << 2;
+ const int8u* buf = (const int8u*)gbuf;
+ sl.reset(x, x + w);
+ storage.prepare();
+ if(flip_y)
+ {
+ buf += pitch * (h - 1);
+ y += h;
+ pitch = -pitch;
+ }
+ for(i = 0; i < h; i++)
+ {
+ sl.reset_spans();
+ bitset_iterator bits(buf, 0);
+ int j;
+ for(j = 0; j < w; j++)
+ {
+ if(bits.bit()) sl.add_cell(x + j, cover_full);
+ ++bits;
+ }
+ buf += pitch;
+ if(sl.num_spans())
+ {
+ sl.finalize(y - i - 1);
+ storage.render(sl);
+ }
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ template<class Rasterizer, class Scanline, class ScanlineStorage>
+ void decompose_win32_glyph_bitmap_gray8(const char* gbuf,
+ int w, int h,
+ int x, int y,
+ bool flip_y,
+ Rasterizer& ras,
+ Scanline& sl,
+ ScanlineStorage& storage)
+ {
+ int i, j;
+ int pitch = ((w + 3) >> 2) << 2;
+ const int8u* buf = (const int8u*)gbuf;
+ sl.reset(x, x + w);
+ storage.prepare();
+ if(flip_y)
+ {
+ buf += pitch * (h - 1);
+ y += h;
+ pitch = -pitch;
+ }
+ for(i = 0; i < h; i++)
+ {
+ sl.reset_spans();
+ const int8u* p = buf;
+ for(j = 0; j < w; j++)
+ {
+ if(*p)
+ {
+ unsigned v = *p;
+ if(v == 64) v = 255;
+ else v <<= 2;
+ sl.add_cell(x + j, ras.apply_gamma(v));
+ }
+ ++p;
+ }
+ buf += pitch;
+ if(sl.num_spans())
+ {
+ sl.finalize(y - i - 1);
+ storage.render(sl);
+ }
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ template<class PathStorage>
+ bool decompose_win32_glyph_outline(const char* gbuf,
+ unsigned total_size,
+ bool flip_y,
+ const trans_affine& mtx,
+ PathStorage& path)
+ {
+ const char* cur_glyph = gbuf;
+ const char* end_glyph = gbuf + total_size;
+ double x, y;
+ typedef typename PathStorage::value_type value_type;
+
+ while(cur_glyph < end_glyph)
+ {
+ const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
+
+ const char* end_poly = cur_glyph + th->cb;
+ const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
+
+ x = fx_to_dbl(th->pfxStart.x);
+ y = fx_to_dbl(th->pfxStart.y);
+ if(flip_y) y = -y;
+ mtx.transform(&x, &y);
+ path.move_to(value_type(dbl_to_int26p6(x)),
+ value_type(dbl_to_int26p6(y)));
+
+ while(cur_poly < end_poly)
+ {
+ const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
+
+ if (pc->wType == TT_PRIM_LINE)
+ {
+ int i;
+ for (i = 0; i < pc->cpfx; i++)
+ {
+ x = fx_to_dbl(pc->apfx[i].x);
+ y = fx_to_dbl(pc->apfx[i].y);
+ if(flip_y) y = -y;
+ mtx.transform(&x, &y);
+ path.line_to(value_type(dbl_to_int26p6(x)),
+ value_type(dbl_to_int26p6(y)));
+ }
+ }
+
+ if (pc->wType == TT_PRIM_QSPLINE)
+ {
+ int u;
+ for (u = 0; u < pc->cpfx - 1; u++) // Walk through points in spline
+ {
+ POINTFX pnt_b = pc->apfx[u]; // B is always the current point
+ POINTFX pnt_c = pc->apfx[u+1];
+
+ if (u < pc->cpfx - 2) // If not on last spline, compute C
+ {
+ // midpoint (x,y)
+ *(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
+ *(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2;
+ }
+
+ double x2, y2;
+ x = fx_to_dbl(pnt_b.x);
+ y = fx_to_dbl(pnt_b.y);
+ x2 = fx_to_dbl(pnt_c.x);
+ y2 = fx_to_dbl(pnt_c.y);
+ if(flip_y) { y = -y; y2 = -y2; }
+ mtx.transform(&x, &y);
+ mtx.transform(&x2, &y2);
+ path.curve3(value_type(dbl_to_int26p6(x)),
+ value_type(dbl_to_int26p6(y)),
+ value_type(dbl_to_int26p6(x2)),
+ value_type(dbl_to_int26p6(y2)));
+ }
+ }
+ cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
+ }
+ cur_glyph += th->cb;
+ }
+ return true;
+ }
+
+
+
+
+ //------------------------------------------------------------------------
+ font_engine_win32_tt_base::~font_engine_win32_tt_base()
+ {
+ delete [] m_kerning_pairs;
+ delete [] m_gbuf;
+ delete [] m_signature;
+ delete [] m_typeface;
+ if(m_dc && m_old_font) ::SelectObject(m_dc, m_old_font);
+ unsigned i;
+ for(i = 0; i < m_num_fonts; ++i)
+ {
+ delete [] m_font_names[i];
+ ::DeleteObject(m_fonts[i]);
+ }
+ delete [] m_font_names;
+ delete [] m_fonts;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ font_engine_win32_tt_base::font_engine_win32_tt_base(bool flag32,
+ HDC dc,
+ unsigned max_fonts) :
+ m_flag32(flag32),
+ m_dc(dc),
+ m_old_font(m_dc ? (HFONT)::GetCurrentObject(m_dc, OBJ_FONT) : 0),
+ m_fonts(new HFONT [max_fonts]),
+ m_num_fonts(0),
+ m_max_fonts(max_fonts),
+ m_font_names(new char* [max_fonts]),
+ m_cur_font(0),
+
+ m_change_stamp(0),
+ m_typeface(new char [256-16]),
+ m_typeface_len(256-16-1),
+ m_signature(new char [256+256-16]),
+ m_height(0),
+ m_width(0),
+ m_weight(FW_REGULAR),
+ m_italic(false),
+ m_char_set(DEFAULT_CHARSET),
+ m_pitch_and_family(FF_DONTCARE),
+ m_hinting(true),
+ m_flip_y(false),
+ m_font_created(false),
+ m_resolution(0),
+ m_glyph_rendering(glyph_ren_native_gray8),
+ m_glyph_index(0),
+ m_data_size(0),
+ m_data_type(glyph_data_invalid),
+ m_bounds(1,1,0,0),
+ m_advance_x(0.0),
+ m_advance_y(0.0),
+ m_gbuf(new char [buf_size]),
+ m_kerning_pairs(0),
+ m_num_kerning_pairs(0),
+ m_max_kerning_pairs(0),
+
+ m_path16(),
+ m_path32(),
+ m_curves16(m_path16),
+ m_curves32(m_path32),
+ m_scanline_aa(),
+ m_scanline_bin(),
+ m_scanlines_aa(),
+ m_scanlines_bin(),
+ m_rasterizer()
+ {
+ m_curves16.approximation_scale(4.0);
+ m_curves32.approximation_scale(4.0);
+ memset(&m_matrix, 0, sizeof(m_matrix));
+ m_matrix.eM11.value = 1;
+ m_matrix.eM22.value = 1;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ int font_engine_win32_tt_base::find_font(const char* name) const
+ {
+ unsigned i;
+ for(i = 0; i < m_num_fonts; ++i)
+ {
+ if(strcmp(name, m_font_names[i]) == 0) return i;
+ }
+ return -1;
+ }
+
+ //------------------------------------------------------------------------
+ bool font_engine_win32_tt_base::create_font(const char* typeface_,
+ glyph_rendering ren_type)
+ {
+ if(m_dc)
+ {
+ unsigned len = strlen(typeface_);
+ if(len > m_typeface_len)
+ {
+ delete [] m_signature;
+ delete [] m_typeface;
+ m_typeface = new char [len + 32];
+ m_signature = new char [len + 32 + 256];
+ m_typeface_len = len + 32 - 1;
+ }
+
+ strcpy(m_typeface, typeface_);
+
+ int h = m_height;
+ int w = m_width;
+
+ if(m_resolution)
+ {
+ h = ::MulDiv(m_height, m_resolution, 72);
+ w = ::MulDiv(m_width, m_resolution, 72);
+ }
+
+ m_glyph_rendering = ren_type;
+ update_signature();
+ int idx = find_font(m_signature);
+ if(idx >= 0)
+ {
+ m_cur_font = m_fonts[idx];
+ ::SelectObject(m_dc, m_cur_font);
+ m_num_kerning_pairs = 0;
+ return true;
+ }
+ else
+ {
+ m_cur_font = ::CreateFontA(-h, // height of font
+ w, // average character width
+ 0, // angle of escapement
+ 0, // base-line orientation angle
+ m_weight, // font weight
+ m_italic, // italic attribute option
+ 0, // underline attribute option
+ 0, // strikeout attribute option
+ m_char_set, // character set identifier
+ OUT_DEFAULT_PRECIS, // output precision
+ CLIP_DEFAULT_PRECIS, // clipping precision
+ ANTIALIASED_QUALITY, // output quality
+ m_pitch_and_family, // pitch and family
+ m_typeface); // typeface name
+ if(m_cur_font)
+ {
+ if(m_num_fonts >= m_max_fonts)
+ {
+ delete [] m_font_names[0];
+ if(m_old_font) ::SelectObject(m_dc, m_old_font);
+ ::DeleteObject(m_fonts[0]);
+ memcpy(m_fonts,
+ m_fonts + 1,
+ (m_max_fonts - 1) * sizeof(HFONT));
+ memcpy(m_font_names,
+ m_font_names + 1,
+ (m_max_fonts - 1) * sizeof(char*));
+ m_num_fonts = m_max_fonts - 1;
+ }
+
+ update_signature();
+ m_font_names[m_num_fonts] = new char[strlen(m_signature) + 1];
+ strcpy(m_font_names[m_num_fonts], m_signature);
+ m_fonts[m_num_fonts] = m_cur_font;
+ ++m_num_fonts;
+ ::SelectObject(m_dc, m_cur_font);
+ m_num_kerning_pairs = 0;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+
+
+
+ //------------------------------------------------------------------------
+ bool font_engine_win32_tt_base::create_font(const char* typeface_,
+ glyph_rendering ren_type,
+ double height_,
+ double width_,
+ int weight_,
+ bool italic_,
+ DWORD char_set_,
+ DWORD pitch_and_family_)
+ {
+ height(height_);
+ width(width_);
+ weight(weight_);
+ italic(italic_);
+ char_set(char_set_);
+ pitch_and_family(pitch_and_family_);
+ return create_font(typeface_, ren_type);
+ }
+
+
+
+
+ //------------------------------------------------------------------------
+ void font_engine_win32_tt_base::update_signature()
+ {
+ m_signature[0] = 0;
+ if(m_dc && m_cur_font)
+ {
+ unsigned gamma_hash = 0;
+ if(m_glyph_rendering == glyph_ren_native_gray8 ||
+ m_glyph_rendering == glyph_ren_agg_mono ||
+ m_glyph_rendering == glyph_ren_agg_gray8)
+ {
+ unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale];
+ unsigned i;
+ for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i)
+ {
+ gamma_table[i] = m_rasterizer.apply_gamma(i);
+ }
+ gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table));
+ }
+
+ sprintf(m_signature,
+ "%s,%u,%d,%d:%dx%d,%d,%d,%d,%d,%d,%08X",
+ m_typeface,
+ m_char_set,
+ int(m_glyph_rendering),
+ m_resolution,
+ m_height,
+ m_width,
+ m_weight,
+ int(m_italic),
+ int(m_hinting),
+ int(m_flip_y),
+ int(m_pitch_and_family),
+ gamma_hash);
+
+ if(m_glyph_rendering == glyph_ren_outline ||
+ m_glyph_rendering == glyph_ren_agg_mono ||
+ m_glyph_rendering == glyph_ren_agg_gray8)
+ {
+ double mtx[6];
+ char buf[100];
+ m_affine.store_to(mtx);
+ sprintf(buf, ",%08X%08X%08X%08X%08X%08X",
+ dbl_to_plain_fx(mtx[0]),
+ dbl_to_plain_fx(mtx[1]),
+ dbl_to_plain_fx(mtx[2]),
+ dbl_to_plain_fx(mtx[3]),
+ dbl_to_plain_fx(mtx[4]),
+ dbl_to_plain_fx(mtx[5]));
+ strcat(m_signature, buf);
+ }
+ ++m_change_stamp;
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool font_engine_win32_tt_base::prepare_glyph(unsigned glyph_code)
+ {
+ if(m_dc && m_cur_font)
+ {
+ int format = GGO_BITMAP;
+
+ switch(m_glyph_rendering)
+ {
+ case glyph_ren_native_gray8:
+ format = GGO_GRAY8_BITMAP;
+ break;
+
+ case glyph_ren_outline:
+ case glyph_ren_agg_mono:
+ case glyph_ren_agg_gray8:
+ format = GGO_NATIVE;
+ break;
+ }
+
+#ifndef GGO_UNHINTED // For compatibility with old SDKs.
+#define GGO_UNHINTED 0x0100
+#endif
+ if(!m_hinting) format |= GGO_UNHINTED;
+
+ GLYPHMETRICS gm;
+ int total_size = GetGlyphOutlineX(m_dc,
+ glyph_code,
+ format,
+ &gm,
+ buf_size,
+ (void*)m_gbuf,
+ &m_matrix);
+
+ if(total_size < 0)
+ {
+ // GetGlyphOutline() fails when being called for
+ // GGO_GRAY8_BITMAP and white space (stupid Microsoft).
+ // It doesn't even initialize the glyph metrics
+ // structure. So, we have to query the metrics
+ // separately (basically we need gmCellIncX).
+ int total_size = GetGlyphOutlineX(m_dc,
+ glyph_code,
+ GGO_METRICS,
+ &gm,
+ buf_size,
+ (void*)m_gbuf,
+ &m_matrix);
+
+ if(total_size < 0) return false;
+ gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
+ total_size = 0;
+ }
+
+ m_glyph_index = glyph_code;
+ m_advance_x = gm.gmCellIncX;
+ m_advance_y = -gm.gmCellIncY;
+
+ switch(m_glyph_rendering)
+ {
+ case glyph_ren_native_mono:
+ decompose_win32_glyph_bitmap_mono(m_gbuf,
+ gm.gmBlackBoxX,
+ gm.gmBlackBoxY,
+ gm.gmptGlyphOrigin.x,
+ m_flip_y ? -gm.gmptGlyphOrigin.y :
+ gm.gmptGlyphOrigin.y,
+ m_flip_y,
+ m_scanline_bin,
+ m_scanlines_bin);
+ m_bounds.x1 = m_scanlines_bin.min_x();
+ m_bounds.y1 = m_scanlines_bin.min_y();
+ m_bounds.x2 = m_scanlines_bin.max_x() + 1;
+ m_bounds.y2 = m_scanlines_bin.max_y() + 1;
+ m_data_size = m_scanlines_bin.byte_size();
+ m_data_type = glyph_data_mono;
+ return true;
+
+ case glyph_ren_native_gray8:
+ decompose_win32_glyph_bitmap_gray8(m_gbuf,
+ gm.gmBlackBoxX,
+ gm.gmBlackBoxY,
+ gm.gmptGlyphOrigin.x,
+ m_flip_y ? -gm.gmptGlyphOrigin.y :
+ gm.gmptGlyphOrigin.y,
+ m_flip_y,
+ m_rasterizer,
+ m_scanline_aa,
+ m_scanlines_aa);
+ m_bounds.x1 = m_scanlines_aa.min_x();
+ m_bounds.y1 = m_scanlines_aa.min_y();
+ m_bounds.x2 = m_scanlines_aa.max_x() + 1;
+ m_bounds.y2 = m_scanlines_aa.max_y() + 1;
+ m_data_size = m_scanlines_aa.byte_size();
+ m_data_type = glyph_data_gray8;
+ return true;
+
+ case glyph_ren_outline:
+ m_affine.transform(&m_advance_x, &m_advance_y);
+ if(m_flag32)
+ {
+ m_path32.remove_all();
+ if(decompose_win32_glyph_outline(m_gbuf,
+ total_size,
+ m_flip_y,
+ m_affine,
+ m_path32))
+ {
+ rect_d bnd = m_path32.bounding_rect();
+ m_data_size = m_path32.byte_size();
+ m_data_type = glyph_data_outline;
+ m_bounds.x1 = int(floor(bnd.x1));
+ m_bounds.y1 = int(floor(bnd.y1));
+ m_bounds.x2 = int(ceil(bnd.x2));
+ m_bounds.y2 = int(ceil(bnd.y2));
+ return true;
+ }
+ }
+ else
+ {
+ m_path16.remove_all();
+ if(decompose_win32_glyph_outline(m_gbuf,
+ total_size,
+ m_flip_y,
+ m_affine,
+ m_path16))
+ {
+ rect_d bnd = m_path16.bounding_rect();
+ m_data_size = m_path16.byte_size();
+ m_data_type = glyph_data_outline;
+ m_bounds.x1 = int(floor(bnd.x1));
+ m_bounds.y1 = int(floor(bnd.y1));
+ m_bounds.x2 = int(ceil(bnd.x2));
+ m_bounds.y2 = int(ceil(bnd.y2));
+ return true;
+ }
+ }
+ break;
+
+ case glyph_ren_agg_mono:
+ m_rasterizer.reset();
+ m_affine.transform(&m_advance_x, &m_advance_y);
+ if(m_flag32)
+ {
+ m_path32.remove_all();
+ decompose_win32_glyph_outline(m_gbuf,
+ total_size,
+ m_flip_y,
+ m_affine,
+ m_path32);
+ m_rasterizer.add_path(m_curves32);
+ }
+ else
+ {
+ m_path16.remove_all();
+ decompose_win32_glyph_outline(m_gbuf,
+ total_size,
+ m_flip_y,
+ m_affine,
+ m_path16);
+ m_rasterizer.add_path(m_curves16);
+ }
+ m_scanlines_bin.prepare(); // Remove all
+ render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin);
+ m_bounds.x1 = m_scanlines_bin.min_x();
+ m_bounds.y1 = m_scanlines_bin.min_y();
+ m_bounds.x2 = m_scanlines_bin.max_x() + 1;
+ m_bounds.y2 = m_scanlines_bin.max_y() + 1;
+ m_data_size = m_scanlines_bin.byte_size();
+ m_data_type = glyph_data_mono;
+ return true;
+
+ case glyph_ren_agg_gray8:
+ m_rasterizer.reset();
+ m_affine.transform(&m_advance_x, &m_advance_y);
+ if(m_flag32)
+ {
+ m_path32.remove_all();
+ decompose_win32_glyph_outline(m_gbuf,
+ total_size,
+ m_flip_y,
+ m_affine,
+ m_path32);
+ m_rasterizer.add_path(m_curves32);
+ }
+ else
+ {
+ m_path16.remove_all();
+ decompose_win32_glyph_outline(m_gbuf,
+ total_size,
+ m_flip_y,
+ m_affine,
+ m_path16);
+ m_rasterizer.add_path(m_curves16);
+ }
+ m_scanlines_aa.prepare(); // Remove all
+ render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa);
+ m_bounds.x1 = m_scanlines_aa.min_x();
+ m_bounds.y1 = m_scanlines_aa.min_y();
+ m_bounds.x2 = m_scanlines_aa.max_x() + 1;
+ m_bounds.y2 = m_scanlines_aa.max_y() + 1;
+ m_data_size = m_scanlines_aa.byte_size();
+ m_data_type = glyph_data_gray8;
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void font_engine_win32_tt_base::write_glyph_to(int8u* data) const
+ {
+ if(data && m_data_size)
+ {
+ switch(m_data_type)
+ {
+ case glyph_data_mono: m_scanlines_bin.serialize(data); break;
+ case glyph_data_gray8: m_scanlines_aa.serialize(data); break;
+ case glyph_data_outline:
+ if(m_flag32)
+ {
+ m_path32.serialize(data);
+ }
+ else
+ {
+ m_path16.serialize(data);
+ }
+ break;
+ }
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ static bool pair_less(const KERNINGPAIR& v1, const KERNINGPAIR& v2)
+ {
+ if(v1.wFirst != v2.wFirst) return v1.wFirst < v2.wFirst;
+ return v1.wSecond < v2.wSecond;
+ }
+
+
+ //------------------------------------------------------------------------
+ void font_engine_win32_tt_base::sort_kerning_pairs()
+ {
+ pod_array_adaptor<KERNINGPAIR> pairs(m_kerning_pairs, m_num_kerning_pairs);
+ quick_sort(pairs, pair_less);
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void font_engine_win32_tt_base::load_kerning_pairs()
+ {
+ if(m_dc && m_cur_font)
+ {
+ if(m_kerning_pairs == 0)
+ {
+ m_kerning_pairs = new KERNINGPAIR [16384-16];
+ m_max_kerning_pairs = 16384-16;
+ }
+ m_num_kerning_pairs = ::GetKerningPairs(m_dc,
+ m_max_kerning_pairs,
+ m_kerning_pairs);
+
+ if(m_num_kerning_pairs)
+ {
+ // Check to see if the kerning pairs are sorted and
+ // sort them if they are not.
+ //----------------
+ unsigned i;
+ for(i = 1; i < m_num_kerning_pairs; ++i)
+ {
+ if(!pair_less(m_kerning_pairs[i - 1], m_kerning_pairs[i]))
+ {
+ sort_kerning_pairs();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ bool font_engine_win32_tt_base::add_kerning(unsigned first, unsigned second,
+ double* x, double* y)
+ {
+ if(m_dc && m_cur_font)
+ {
+ if(m_num_kerning_pairs == 0)
+ {
+ load_kerning_pairs();
+ }
+
+ int end = m_num_kerning_pairs - 1;
+ int beg = 0;
+ KERNINGPAIR t;
+ t.wFirst = (WORD)first;
+ t.wSecond = (WORD)second;
+ while(beg <= end)
+ {
+ int mid = (end + beg) / 2;
+ if(m_kerning_pairs[mid].wFirst == t.wFirst &&
+ m_kerning_pairs[mid].wSecond == t.wSecond)
+ {
+ double dx = m_kerning_pairs[mid].iKernAmount;
+ double dy = 0.0;
+ if(m_glyph_rendering == glyph_ren_outline ||
+ m_glyph_rendering == glyph_ren_agg_mono ||
+ m_glyph_rendering == glyph_ren_agg_gray8)
+ {
+ m_affine.transform_2x2(&dx, &dy);
+ }
+ *x += dx;
+ *y += dy;
+ return true;
+ }
+ else
+ if(pair_less(t, m_kerning_pairs[mid]))
+ {
+ end = mid - 1;
+ }
+ else
+ {
+ beg = mid + 1;
+ }
+ }
+ return false;
+ }
+ return false;
+ }
+
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_gsv_text.cpp b/plugins/Clist_ng/AGG/src/agg_gsv_text.cpp new file mode 100644 index 0000000000..bc54ef7cb3 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_gsv_text.cpp @@ -0,0 +1,681 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <string.h>
+#include <stdio.h>
+#include "agg_gsv_text.h"
+#include "agg_bounding_rect.h"
+
+
+
+namespace agg
+{
+ int8u gsv_default_font[] =
+ {
+ 0x40,0x00,0x6c,0x0f,0x15,0x00,0x0e,0x00,0xf9,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x0d,0x0a,0x0d,0x0a,0x46,0x6f,0x6e,0x74,0x20,0x28,
+ 0x63,0x29,0x20,0x4d,0x69,0x63,0x72,0x6f,0x50,0x72,
+ 0x6f,0x66,0x20,0x32,0x37,0x20,0x53,0x65,0x70,0x74,
+ 0x65,0x6d,0x62,0x2e,0x31,0x39,0x38,0x39,0x00,0x0d,
+ 0x0a,0x0d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x12,0x00,0x34,0x00,0x46,0x00,0x94,0x00,
+ 0xd0,0x00,0x2e,0x01,0x3e,0x01,0x64,0x01,0x8a,0x01,
+ 0x98,0x01,0xa2,0x01,0xb4,0x01,0xba,0x01,0xc6,0x01,
+ 0xcc,0x01,0xf0,0x01,0xfa,0x01,0x18,0x02,0x38,0x02,
+ 0x44,0x02,0x68,0x02,0x98,0x02,0xa2,0x02,0xde,0x02,
+ 0x0e,0x03,0x24,0x03,0x40,0x03,0x48,0x03,0x52,0x03,
+ 0x5a,0x03,0x82,0x03,0xec,0x03,0xfa,0x03,0x26,0x04,
+ 0x4c,0x04,0x6a,0x04,0x7c,0x04,0x8a,0x04,0xb6,0x04,
+ 0xc4,0x04,0xca,0x04,0xe0,0x04,0xee,0x04,0xf8,0x04,
+ 0x0a,0x05,0x18,0x05,0x44,0x05,0x5e,0x05,0x8e,0x05,
+ 0xac,0x05,0xd6,0x05,0xe0,0x05,0xf6,0x05,0x00,0x06,
+ 0x12,0x06,0x1c,0x06,0x28,0x06,0x36,0x06,0x48,0x06,
+ 0x4e,0x06,0x60,0x06,0x6e,0x06,0x74,0x06,0x84,0x06,
+ 0xa6,0x06,0xc8,0x06,0xe6,0x06,0x08,0x07,0x2c,0x07,
+ 0x3c,0x07,0x68,0x07,0x7c,0x07,0x8c,0x07,0xa2,0x07,
+ 0xb0,0x07,0xb6,0x07,0xd8,0x07,0xec,0x07,0x10,0x08,
+ 0x32,0x08,0x54,0x08,0x64,0x08,0x88,0x08,0x98,0x08,
+ 0xac,0x08,0xb6,0x08,0xc8,0x08,0xd2,0x08,0xe4,0x08,
+ 0xf2,0x08,0x3e,0x09,0x48,0x09,0x94,0x09,0xc2,0x09,
+ 0xc4,0x09,0xd0,0x09,0xe2,0x09,0x04,0x0a,0x0e,0x0a,
+ 0x26,0x0a,0x34,0x0a,0x4a,0x0a,0x66,0x0a,0x70,0x0a,
+ 0x7e,0x0a,0x8e,0x0a,0x9a,0x0a,0xa6,0x0a,0xb4,0x0a,
+ 0xd8,0x0a,0xe2,0x0a,0xf6,0x0a,0x18,0x0b,0x22,0x0b,
+ 0x32,0x0b,0x56,0x0b,0x60,0x0b,0x6e,0x0b,0x7c,0x0b,
+ 0x8a,0x0b,0x9c,0x0b,0x9e,0x0b,0xb2,0x0b,0xc2,0x0b,
+ 0xd8,0x0b,0xf4,0x0b,0x08,0x0c,0x30,0x0c,0x56,0x0c,
+ 0x72,0x0c,0x90,0x0c,0xb2,0x0c,0xce,0x0c,0xe2,0x0c,
+ 0xfe,0x0c,0x10,0x0d,0x26,0x0d,0x36,0x0d,0x42,0x0d,
+ 0x4e,0x0d,0x5c,0x0d,0x78,0x0d,0x8c,0x0d,0x8e,0x0d,
+ 0x90,0x0d,0x92,0x0d,0x94,0x0d,0x96,0x0d,0x98,0x0d,
+ 0x9a,0x0d,0x9c,0x0d,0x9e,0x0d,0xa0,0x0d,0xa2,0x0d,
+ 0xa4,0x0d,0xa6,0x0d,0xa8,0x0d,0xaa,0x0d,0xac,0x0d,
+ 0xae,0x0d,0xb0,0x0d,0xb2,0x0d,0xb4,0x0d,0xb6,0x0d,
+ 0xb8,0x0d,0xba,0x0d,0xbc,0x0d,0xbe,0x0d,0xc0,0x0d,
+ 0xc2,0x0d,0xc4,0x0d,0xc6,0x0d,0xc8,0x0d,0xca,0x0d,
+ 0xcc,0x0d,0xce,0x0d,0xd0,0x0d,0xd2,0x0d,0xd4,0x0d,
+ 0xd6,0x0d,0xd8,0x0d,0xda,0x0d,0xdc,0x0d,0xde,0x0d,
+ 0xe0,0x0d,0xe2,0x0d,0xe4,0x0d,0xe6,0x0d,0xe8,0x0d,
+ 0xea,0x0d,0xec,0x0d,0x0c,0x0e,0x26,0x0e,0x48,0x0e,
+ 0x64,0x0e,0x88,0x0e,0x92,0x0e,0xa6,0x0e,0xb4,0x0e,
+ 0xd0,0x0e,0xee,0x0e,0x02,0x0f,0x16,0x0f,0x26,0x0f,
+ 0x3c,0x0f,0x58,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,
+ 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,
+ 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,
+ 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x10,0x80,
+ 0x05,0x95,0x00,0x72,0x00,0xfb,0xff,0x7f,0x01,0x7f,
+ 0x01,0x01,0xff,0x01,0x05,0xfe,0x05,0x95,0xff,0x7f,
+ 0x00,0x7a,0x01,0x86,0xff,0x7a,0x01,0x87,0x01,0x7f,
+ 0xfe,0x7a,0x0a,0x87,0xff,0x7f,0x00,0x7a,0x01,0x86,
+ 0xff,0x7a,0x01,0x87,0x01,0x7f,0xfe,0x7a,0x05,0xf2,
+ 0x0b,0x95,0xf9,0x64,0x0d,0x9c,0xf9,0x64,0xfa,0x91,
+ 0x0e,0x00,0xf1,0xfa,0x0e,0x00,0x04,0xfc,0x08,0x99,
+ 0x00,0x63,0x04,0x9d,0x00,0x63,0x04,0x96,0xff,0x7f,
+ 0x01,0x7f,0x01,0x01,0x00,0x01,0xfe,0x02,0xfd,0x01,
+ 0xfc,0x00,0xfd,0x7f,0xfe,0x7e,0x00,0x7e,0x01,0x7e,
+ 0x01,0x7f,0x02,0x7f,0x06,0x7e,0x02,0x7f,0x02,0x7e,
+ 0xf2,0x89,0x02,0x7e,0x02,0x7f,0x06,0x7e,0x02,0x7f,
+ 0x01,0x7f,0x01,0x7e,0x00,0x7c,0xfe,0x7e,0xfd,0x7f,
+ 0xfc,0x00,0xfd,0x01,0xfe,0x02,0x00,0x01,0x01,0x01,
+ 0x01,0x7f,0xff,0x7f,0x10,0xfd,0x15,0x95,0xee,0x6b,
+ 0x05,0x95,0x02,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7f,
+ 0xfe,0x00,0xfe,0x02,0x00,0x02,0x01,0x02,0x02,0x01,
+ 0x02,0x00,0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01,
+ 0x02,0x01,0xfc,0xf2,0xfe,0x7f,0xff,0x7e,0x00,0x7e,
+ 0x02,0x7e,0x02,0x00,0x02,0x01,0x01,0x02,0x00,0x02,
+ 0xfe,0x02,0xfe,0x00,0x07,0xf9,0x15,0x8d,0xff,0x7f,
+ 0x01,0x7f,0x01,0x01,0x00,0x01,0xff,0x01,0xff,0x00,
+ 0xff,0x7f,0xff,0x7e,0xfe,0x7b,0xfe,0x7d,0xfe,0x7e,
+ 0xfe,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02,0x00,0x03,
+ 0x01,0x02,0x06,0x04,0x02,0x02,0x01,0x02,0x00,0x02,
+ 0xff,0x02,0xfe,0x01,0xfe,0x7f,0xff,0x7e,0x00,0x7e,
+ 0x01,0x7d,0x02,0x7d,0x05,0x79,0x02,0x7e,0x03,0x7f,
+ 0x01,0x00,0x01,0x01,0x00,0x01,0xf1,0xfe,0xfe,0x01,
+ 0xff,0x02,0x00,0x03,0x01,0x02,0x02,0x02,0x00,0x86,
+ 0x01,0x7e,0x08,0x75,0x02,0x7e,0x02,0x7f,0x05,0x80,
+ 0x05,0x93,0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e,
+ 0xff,0x7e,0xff,0x7f,0x06,0xf1,0x0b,0x99,0xfe,0x7e,
+ 0xfe,0x7d,0xfe,0x7c,0xff,0x7b,0x00,0x7c,0x01,0x7b,
+ 0x02,0x7c,0x02,0x7d,0x02,0x7e,0xfe,0x9e,0xfe,0x7c,
+ 0xff,0x7d,0xff,0x7b,0x00,0x7c,0x01,0x7b,0x01,0x7d,
+ 0x02,0x7c,0x05,0x85,0x03,0x99,0x02,0x7e,0x02,0x7d,
+ 0x02,0x7c,0x01,0x7b,0x00,0x7c,0xff,0x7b,0xfe,0x7c,
+ 0xfe,0x7d,0xfe,0x7e,0x02,0x9e,0x02,0x7c,0x01,0x7d,
+ 0x01,0x7b,0x00,0x7c,0xff,0x7b,0xff,0x7d,0xfe,0x7c,
+ 0x09,0x85,0x08,0x95,0x00,0x74,0xfb,0x89,0x0a,0x7a,
+ 0x00,0x86,0xf6,0x7a,0x0d,0xf4,0x0d,0x92,0x00,0x6e,
+ 0xf7,0x89,0x12,0x00,0x04,0xf7,0x06,0x81,0xff,0x7f,
+ 0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e,0xff,0x7e,
+ 0xff,0x7f,0x06,0x84,0x04,0x89,0x12,0x00,0x04,0xf7,
+ 0x05,0x82,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01,
+ 0x05,0xfe,0x00,0xfd,0x0e,0x18,0x00,0xeb,0x09,0x95,
+ 0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7d,0x01,0x7b,
+ 0x02,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x03,
+ 0x01,0x05,0x00,0x03,0xff,0x05,0xfe,0x03,0xfd,0x01,
+ 0xfe,0x00,0x0b,0xeb,0x06,0x91,0x02,0x01,0x03,0x03,
+ 0x00,0x6b,0x09,0x80,0x04,0x90,0x00,0x01,0x01,0x02,
+ 0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7f,
+ 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7d,0xf6,0x76,
+ 0x0e,0x00,0x03,0x80,0x05,0x95,0x0b,0x00,0xfa,0x78,
+ 0x03,0x00,0x02,0x7f,0x01,0x7f,0x01,0x7d,0x00,0x7e,
+ 0xff,0x7d,0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,
+ 0xff,0x01,0xff,0x02,0x11,0xfc,0x0d,0x95,0xf6,0x72,
+ 0x0f,0x00,0xfb,0x8e,0x00,0x6b,0x07,0x80,0x0f,0x95,
+ 0xf6,0x00,0xff,0x77,0x01,0x01,0x03,0x01,0x03,0x00,
+ 0x03,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e,0xff,0x7d,
+ 0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x01,
+ 0xff,0x02,0x11,0xfc,0x10,0x92,0xff,0x02,0xfd,0x01,
+ 0xfe,0x00,0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7b,
+ 0x01,0x7c,0x02,0x7e,0x03,0x7f,0x01,0x00,0x03,0x01,
+ 0x02,0x02,0x01,0x03,0x00,0x01,0xff,0x03,0xfe,0x02,
+ 0xfd,0x01,0xff,0x00,0xfd,0x7f,0xfe,0x7e,0xff,0x7d,
+ 0x10,0xf9,0x11,0x95,0xf6,0x6b,0xfc,0x95,0x0e,0x00,
+ 0x03,0xeb,0x08,0x95,0xfd,0x7f,0xff,0x7e,0x00,0x7e,
+ 0x01,0x7e,0x02,0x7f,0x04,0x7f,0x03,0x7f,0x02,0x7e,
+ 0x01,0x7e,0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f,
+ 0xfc,0x00,0xfd,0x01,0xff,0x01,0xff,0x02,0x00,0x03,
+ 0x01,0x02,0x02,0x02,0x03,0x01,0x04,0x01,0x02,0x01,
+ 0x01,0x02,0x00,0x02,0xff,0x02,0xfd,0x01,0xfc,0x00,
+ 0x0c,0xeb,0x10,0x8e,0xff,0x7d,0xfe,0x7e,0xfd,0x7f,
+ 0xff,0x00,0xfd,0x01,0xfe,0x02,0xff,0x03,0x00,0x01,
+ 0x01,0x03,0x02,0x02,0x03,0x01,0x01,0x00,0x03,0x7f,
+ 0x02,0x7e,0x01,0x7c,0x00,0x7b,0xff,0x7b,0xfe,0x7d,
+ 0xfd,0x7f,0xfe,0x00,0xfd,0x01,0xff,0x02,0x10,0xfd,
+ 0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01,
+ 0x00,0xf4,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01,
+ 0x05,0xfe,0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01,
+ 0xff,0x01,0x01,0xf3,0xff,0x7f,0xff,0x01,0x01,0x01,
+ 0x01,0x7f,0x00,0x7e,0xff,0x7e,0xff,0x7f,0x06,0x84,
+ 0x14,0x92,0xf0,0x77,0x10,0x77,0x04,0x80,0x04,0x8c,
+ 0x12,0x00,0xee,0xfa,0x12,0x00,0x04,0xfa,0x04,0x92,
+ 0x10,0x77,0xf0,0x77,0x14,0x80,0x03,0x90,0x00,0x01,
+ 0x01,0x02,0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f,
+ 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,
+ 0xfc,0x7e,0x00,0x7d,0x00,0xfb,0xff,0x7f,0x01,0x7f,
+ 0x01,0x01,0xff,0x01,0x09,0xfe,0x12,0x8d,0xff,0x02,
+ 0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xff,0x7f,0xff,0x7d,
+ 0x00,0x7d,0x01,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
+ 0x01,0x02,0xfb,0x88,0xfe,0x7e,0xff,0x7d,0x00,0x7d,
+ 0x01,0x7e,0x01,0x7f,0x07,0x8b,0xff,0x78,0x00,0x7e,
+ 0x02,0x7f,0x02,0x00,0x02,0x02,0x01,0x03,0x00,0x02,
+ 0xff,0x03,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfd,0x01,
+ 0xfd,0x00,0xfd,0x7f,0xfe,0x7f,0xfe,0x7e,0xff,0x7e,
+ 0xff,0x7d,0x00,0x7d,0x01,0x7d,0x01,0x7e,0x02,0x7e,
+ 0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01,0x02,0x01,
+ 0x01,0x01,0xfe,0x8d,0xff,0x78,0x00,0x7e,0x01,0x7f,
+ 0x08,0xfb,0x09,0x95,0xf8,0x6b,0x08,0x95,0x08,0x6b,
+ 0xf3,0x87,0x0a,0x00,0x04,0xf9,0x04,0x95,0x00,0x6b,
+ 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,
+ 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x80,
+ 0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d,
+ 0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00,0x11,0x80,
+ 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00,
+ 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b,
+ 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00,
+ 0x02,0x01,0x02,0x02,0x01,0x02,0x03,0xfb,0x04,0x95,
+ 0x00,0x6b,0x00,0x95,0x07,0x00,0x03,0x7f,0x02,0x7e,
+ 0x01,0x7e,0x01,0x7d,0x00,0x7b,0xff,0x7d,0xff,0x7e,
+ 0xfe,0x7e,0xfd,0x7f,0xf9,0x00,0x11,0x80,0x04,0x95,
+ 0x00,0x6b,0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00,
+ 0xf8,0xf5,0x0d,0x00,0x02,0x80,0x04,0x95,0x00,0x6b,
+ 0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00,0x06,0xf5,
+ 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00,
+ 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b,
+ 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00,
+ 0x02,0x01,0x02,0x02,0x01,0x02,0x00,0x03,0xfb,0x80,
+ 0x05,0x00,0x03,0xf8,0x04,0x95,0x00,0x6b,0x0e,0x95,
+ 0x00,0x6b,0xf2,0x8b,0x0e,0x00,0x04,0xf5,0x04,0x95,
+ 0x00,0x6b,0x04,0x80,0x0c,0x95,0x00,0x70,0xff,0x7d,
+ 0xff,0x7f,0xfe,0x7f,0xfe,0x00,0xfe,0x01,0xff,0x01,
+ 0xff,0x03,0x00,0x02,0x0e,0xf9,0x04,0x95,0x00,0x6b,
+ 0x0e,0x95,0xf2,0x72,0x05,0x85,0x09,0x74,0x03,0x80,
+ 0x04,0x95,0x00,0x6b,0x00,0x80,0x0c,0x00,0x01,0x80,
+ 0x04,0x95,0x00,0x6b,0x00,0x95,0x08,0x6b,0x08,0x95,
+ 0xf8,0x6b,0x08,0x95,0x00,0x6b,0x04,0x80,0x04,0x95,
+ 0x00,0x6b,0x00,0x95,0x0e,0x6b,0x00,0x95,0x00,0x6b,
+ 0x04,0x80,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e,
+ 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e,
+ 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02,
+ 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02,
+ 0xfe,0x01,0xfc,0x00,0x0d,0xeb,0x04,0x95,0x00,0x6b,
+ 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,
+ 0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00,
+ 0x11,0xf6,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e,
+ 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e,
+ 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02,
+ 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02,
+ 0xfe,0x01,0xfc,0x00,0x03,0xef,0x06,0x7a,0x04,0x82,
+ 0x04,0x95,0x00,0x6b,0x00,0x95,0x09,0x00,0x03,0x7f,
+ 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,
+ 0xfd,0x7f,0xf7,0x00,0x07,0x80,0x07,0x75,0x03,0x80,
+ 0x11,0x92,0xfe,0x02,0xfd,0x01,0xfc,0x00,0xfd,0x7f,
+ 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x02,0x7f,
+ 0x06,0x7e,0x02,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d,
+ 0xfe,0x7e,0xfd,0x7f,0xfc,0x00,0xfd,0x01,0xfe,0x02,
+ 0x11,0xfd,0x08,0x95,0x00,0x6b,0xf9,0x95,0x0e,0x00,
+ 0x01,0xeb,0x04,0x95,0x00,0x71,0x01,0x7d,0x02,0x7e,
+ 0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x02,0x01,0x03,
+ 0x00,0x0f,0x04,0xeb,0x01,0x95,0x08,0x6b,0x08,0x95,
+ 0xf8,0x6b,0x09,0x80,0x02,0x95,0x05,0x6b,0x05,0x95,
+ 0xfb,0x6b,0x05,0x95,0x05,0x6b,0x05,0x95,0xfb,0x6b,
+ 0x07,0x80,0x03,0x95,0x0e,0x6b,0x00,0x95,0xf2,0x6b,
+ 0x11,0x80,0x01,0x95,0x08,0x76,0x00,0x75,0x08,0x95,
+ 0xf8,0x76,0x09,0xf5,0x11,0x95,0xf2,0x6b,0x00,0x95,
+ 0x0e,0x00,0xf2,0xeb,0x0e,0x00,0x03,0x80,0x03,0x93,
+ 0x00,0x6c,0x01,0x94,0x00,0x6c,0xff,0x94,0x05,0x00,
+ 0xfb,0xec,0x05,0x00,0x02,0x81,0x00,0x95,0x0e,0x68,
+ 0x00,0x83,0x06,0x93,0x00,0x6c,0x01,0x94,0x00,0x6c,
+ 0xfb,0x94,0x05,0x00,0xfb,0xec,0x05,0x00,0x03,0x81,
+ 0x03,0x87,0x08,0x05,0x08,0x7b,0xf0,0x80,0x08,0x04,
+ 0x08,0x7c,0x03,0xf9,0x01,0x80,0x10,0x00,0x01,0x80,
+ 0x06,0x95,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7f,
+ 0x01,0x01,0xff,0x01,0x05,0xef,0x0f,0x8e,0x00,0x72,
+ 0x00,0x8b,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,
+ 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,
+ 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,
+ 0x04,0x95,0x00,0x6b,0x00,0x8b,0x02,0x02,0x02,0x01,
+ 0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e,
+ 0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00,0xfe,0x01,
+ 0xfe,0x02,0x0f,0xfd,0x0f,0x8b,0xfe,0x02,0xfe,0x01,
+ 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e,
+ 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
+ 0x02,0x02,0x03,0xfd,0x0f,0x95,0x00,0x6b,0x00,0x8b,
+ 0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xfe,0x7e,
+ 0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,0x02,0x7f,
+ 0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,0x03,0x88,
+ 0x0c,0x00,0x00,0x02,0xff,0x02,0xff,0x01,0xfe,0x01,
+ 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e,
+ 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
+ 0x02,0x02,0x03,0xfd,0x0a,0x95,0xfe,0x00,0xfe,0x7f,
+ 0xff,0x7d,0x00,0x6f,0xfd,0x8e,0x07,0x00,0x03,0xf2,
+ 0x0f,0x8e,0x00,0x70,0xff,0x7d,0xff,0x7f,0xfe,0x7f,
+ 0xfd,0x00,0xfe,0x01,0x09,0x91,0xfe,0x02,0xfe,0x01,
+ 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e,
+ 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
+ 0x02,0x02,0x04,0xfd,0x04,0x95,0x00,0x6b,0x00,0x8a,
+ 0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d,
+ 0x00,0x76,0x04,0x80,0x03,0x95,0x01,0x7f,0x01,0x01,
+ 0xff,0x01,0xff,0x7f,0x01,0xf9,0x00,0x72,0x04,0x80,
+ 0x05,0x95,0x01,0x7f,0x01,0x01,0xff,0x01,0xff,0x7f,
+ 0x01,0xf9,0x00,0x6f,0xff,0x7d,0xfe,0x7f,0xfe,0x00,
+ 0x09,0x87,0x04,0x95,0x00,0x6b,0x0a,0x8e,0xf6,0x76,
+ 0x04,0x84,0x07,0x78,0x02,0x80,0x04,0x95,0x00,0x6b,
+ 0x04,0x80,0x04,0x8e,0x00,0x72,0x00,0x8a,0x03,0x03,
+ 0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d,0x00,0x76,
+ 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,
+ 0x01,0x7d,0x00,0x76,0x04,0x80,0x04,0x8e,0x00,0x72,
+ 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,
+ 0x01,0x7d,0x00,0x76,0x04,0x80,0x08,0x8e,0xfe,0x7f,
+ 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,
+ 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x01,0x03,
+ 0x00,0x02,0xff,0x03,0xfe,0x02,0xfe,0x01,0xfd,0x00,
+ 0x0b,0xf2,0x04,0x8e,0x00,0x6b,0x00,0x92,0x02,0x02,
+ 0x02,0x01,0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d,
+ 0x00,0x7e,0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00,
+ 0xfe,0x01,0xfe,0x02,0x0f,0xfd,0x0f,0x8e,0x00,0x6b,
+ 0x00,0x92,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,
+ 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,
+ 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,
+ 0x04,0x8e,0x00,0x72,0x00,0x88,0x01,0x03,0x02,0x02,
+ 0x02,0x01,0x03,0x00,0x01,0xf2,0x0e,0x8b,0xff,0x02,
+ 0xfd,0x01,0xfd,0x00,0xfd,0x7f,0xff,0x7e,0x01,0x7e,
+ 0x02,0x7f,0x05,0x7f,0x02,0x7f,0x01,0x7e,0x00,0x7f,
+ 0xff,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02,
+ 0x0e,0xfd,0x05,0x95,0x00,0x6f,0x01,0x7d,0x02,0x7f,
+ 0x02,0x00,0xf8,0x8e,0x07,0x00,0x03,0xf2,0x04,0x8e,
+ 0x00,0x76,0x01,0x7d,0x02,0x7f,0x03,0x00,0x02,0x01,
+ 0x03,0x03,0x00,0x8a,0x00,0x72,0x04,0x80,0x02,0x8e,
+ 0x06,0x72,0x06,0x8e,0xfa,0x72,0x08,0x80,0x03,0x8e,
+ 0x04,0x72,0x04,0x8e,0xfc,0x72,0x04,0x8e,0x04,0x72,
+ 0x04,0x8e,0xfc,0x72,0x07,0x80,0x03,0x8e,0x0b,0x72,
+ 0x00,0x8e,0xf5,0x72,0x0e,0x80,0x02,0x8e,0x06,0x72,
+ 0x06,0x8e,0xfa,0x72,0xfe,0x7c,0xfe,0x7e,0xfe,0x7f,
+ 0xff,0x00,0x0f,0x87,0x0e,0x8e,0xf5,0x72,0x00,0x8e,
+ 0x0b,0x00,0xf5,0xf2,0x0b,0x00,0x03,0x80,0x09,0x99,
+ 0xfe,0x7f,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,
+ 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xfe,0x7e,0x01,0x8e,
+ 0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e,
+ 0x00,0x7e,0xff,0x7e,0xfc,0x7e,0x04,0x7e,0x01,0x7e,
+ 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e,
+ 0x01,0x7e,0xff,0x8e,0x02,0x7e,0x00,0x7e,0xff,0x7e,
+ 0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,
+ 0x02,0x7f,0x05,0x87,0x04,0x95,0x00,0x77,0x00,0xfd,
+ 0x00,0x77,0x04,0x80,0x05,0x99,0x02,0x7f,0x01,0x7f,
+ 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e,
+ 0x00,0x7e,0x02,0x7e,0xff,0x8e,0x01,0x7e,0x00,0x7e,
+ 0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,
+ 0x04,0x7e,0xfc,0x7e,0xff,0x7e,0x00,0x7e,0x01,0x7e,
+ 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0x01,0x8e,
+ 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e,
+ 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfe,0x7f,0x09,0x87,
+ 0x03,0x86,0x00,0x02,0x01,0x03,0x02,0x01,0x02,0x00,
+ 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01,
+ 0x01,0x02,0xee,0xfe,0x01,0x02,0x02,0x01,0x02,0x00,
+ 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01,
+ 0x01,0x03,0x00,0x02,0x03,0xf4,0x10,0x80,0x03,0x80,
+ 0x07,0x15,0x08,0x6b,0xfe,0x85,0xf5,0x00,0x10,0xfb,
+ 0x0d,0x95,0xf6,0x00,0x00,0x6b,0x0a,0x00,0x02,0x02,
+ 0x00,0x08,0xfe,0x02,0xf6,0x00,0x0e,0xf4,0x03,0x80,
+ 0x00,0x15,0x0a,0x00,0x02,0x7e,0x00,0x7e,0x00,0x7d,
+ 0x00,0x7e,0xfe,0x7f,0xf6,0x00,0x0a,0x80,0x02,0x7e,
+ 0x01,0x7e,0x00,0x7d,0xff,0x7d,0xfe,0x7f,0xf6,0x00,
+ 0x10,0x80,0x03,0x80,0x00,0x15,0x0c,0x00,0xff,0x7e,
+ 0x03,0xed,0x03,0xfd,0x00,0x03,0x02,0x00,0x00,0x12,
+ 0x02,0x03,0x0a,0x00,0x00,0x6b,0x02,0x00,0x00,0x7d,
+ 0xfe,0x83,0xf4,0x00,0x11,0x80,0x0f,0x80,0xf4,0x00,
+ 0x00,0x15,0x0c,0x00,0xff,0xf6,0xf5,0x00,0x0f,0xf5,
+ 0x04,0x95,0x07,0x76,0x00,0x0a,0x07,0x80,0xf9,0x76,
+ 0x00,0x75,0xf8,0x80,0x07,0x0c,0x09,0xf4,0xf9,0x0c,
+ 0x09,0xf4,0x03,0x92,0x02,0x03,0x07,0x00,0x03,0x7d,
+ 0x00,0x7b,0xfc,0x7e,0x04,0x7d,0x00,0x7a,0xfd,0x7e,
+ 0xf9,0x00,0xfe,0x02,0x06,0x89,0x02,0x00,0x06,0xf5,
+ 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0x02,0x80,
+ 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0xf8,0x96,
+ 0x03,0x00,0x07,0xea,0x03,0x80,0x00,0x15,0x0c,0x80,
+ 0xf7,0x76,0xfd,0x00,0x03,0x80,0x0a,0x75,0x03,0x80,
+ 0x03,0x80,0x07,0x13,0x02,0x02,0x03,0x00,0x00,0x6b,
+ 0x02,0x80,0x03,0x80,0x00,0x15,0x09,0x6b,0x09,0x15,
+ 0x00,0x6b,0x03,0x80,0x03,0x80,0x00,0x15,0x00,0xf6,
+ 0x0d,0x00,0x00,0x8a,0x00,0x6b,0x03,0x80,0x07,0x80,
+ 0xfd,0x00,0xff,0x03,0x00,0x04,0x00,0x07,0x00,0x04,
+ 0x01,0x02,0x03,0x01,0x06,0x00,0x03,0x7f,0x01,0x7e,
+ 0x01,0x7c,0x00,0x79,0xff,0x7c,0xff,0x7d,0xfd,0x00,
+ 0xfa,0x00,0x0e,0x80,0x03,0x80,0x00,0x15,0x0c,0x00,
+ 0x00,0x6b,0x02,0x80,0x03,0x80,0x00,0x15,0x0a,0x00,
+ 0x02,0x7f,0x01,0x7d,0x00,0x7b,0xff,0x7e,0xfe,0x7f,
+ 0xf6,0x00,0x10,0xf7,0x11,0x8f,0xff,0x03,0xff,0x02,
+ 0xfe,0x01,0xfa,0x00,0xfd,0x7f,0xff,0x7e,0x00,0x7c,
+ 0x00,0x79,0x00,0x7b,0x01,0x7e,0x03,0x00,0x06,0x00,
+ 0x02,0x00,0x01,0x03,0x01,0x02,0x03,0xfb,0x03,0x95,
+ 0x0c,0x00,0xfa,0x80,0x00,0x6b,0x09,0x80,0x03,0x95,
+ 0x00,0x77,0x06,0x7a,0x06,0x06,0x00,0x09,0xfa,0xf1,
+ 0xfa,0x7a,0x0e,0x80,0x03,0x87,0x00,0x0b,0x02,0x02,
+ 0x03,0x00,0x02,0x7e,0x01,0x02,0x04,0x00,0x02,0x7e,
+ 0x00,0x75,0xfe,0x7e,0xfc,0x00,0xff,0x01,0xfe,0x7f,
+ 0xfd,0x00,0xfe,0x02,0x07,0x8e,0x00,0x6b,0x09,0x80,
+ 0x03,0x80,0x0e,0x15,0xf2,0x80,0x0e,0x6b,0x03,0x80,
+ 0x03,0x95,0x00,0x6b,0x0e,0x00,0x00,0x7d,0xfe,0x98,
+ 0x00,0x6b,0x05,0x80,0x03,0x95,0x00,0x75,0x02,0x7d,
+ 0x0a,0x00,0x00,0x8e,0x00,0x6b,0x02,0x80,0x03,0x95,
+ 0x00,0x6b,0x10,0x00,0x00,0x15,0xf8,0x80,0x00,0x6b,
+ 0x0a,0x80,0x03,0x95,0x00,0x6b,0x10,0x00,0x00,0x15,
+ 0xf8,0x80,0x00,0x6b,0x0a,0x00,0x00,0x7d,0x02,0x83,
+ 0x10,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02,
+ 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0x89,0x00,0x6b,
+ 0x03,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02,
+ 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0xf4,0x03,0x92,
+ 0x02,0x03,0x07,0x00,0x03,0x7d,0x00,0x70,0xfd,0x7e,
+ 0xf9,0x00,0xfe,0x02,0x03,0x89,0x09,0x00,0x02,0xf5,
+ 0x03,0x80,0x00,0x15,0x00,0xf5,0x07,0x00,0x00,0x08,
+ 0x02,0x03,0x06,0x00,0x02,0x7d,0x00,0x70,0xfe,0x7e,
+ 0xfa,0x00,0xfe,0x02,0x00,0x08,0x0c,0xf6,0x0f,0x80,
+ 0x00,0x15,0xf6,0x00,0xfe,0x7d,0x00,0x79,0x02,0x7e,
+ 0x0a,0x00,0xf4,0xf7,0x07,0x09,0x07,0xf7,0x03,0x8c,
+ 0x01,0x02,0x01,0x01,0x05,0x00,0x02,0x7f,0x01,0x7e,
+ 0x00,0x74,0x00,0x86,0xff,0x01,0xfe,0x01,0xfb,0x00,
+ 0xff,0x7f,0xff,0x7f,0x00,0x7c,0x01,0x7e,0x01,0x00,
+ 0x05,0x00,0x02,0x00,0x01,0x02,0x03,0xfe,0x04,0x8e,
+ 0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7e,0x00,0x77,
+ 0xff,0x7e,0xfe,0x7f,0xfc,0x00,0xfe,0x01,0xff,0x02,
+ 0x00,0x09,0x01,0x02,0x02,0x02,0x03,0x01,0x02,0x01,
+ 0x01,0x01,0x01,0x02,0x02,0xeb,0x03,0x80,0x00,0x15,
+ 0x03,0x00,0x02,0x7e,0x00,0x7b,0xfe,0x7e,0xfd,0x00,
+ 0x03,0x80,0x04,0x00,0x03,0x7e,0x00,0x78,0xfd,0x7e,
+ 0xf9,0x00,0x0c,0x80,0x03,0x8c,0x02,0x02,0x02,0x01,
+ 0x03,0x00,0x02,0x7f,0x01,0x7d,0xfe,0x7e,0xf9,0x7d,
+ 0xff,0x7e,0x00,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01,
+ 0x02,0x01,0x02,0xfe,0x0d,0x8c,0xff,0x02,0xfe,0x01,
+ 0xfc,0x00,0xfe,0x7f,0xff,0x7e,0x00,0x77,0x01,0x7e,
+ 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x02,0x00,0x0f,
+ 0xff,0x02,0xfe,0x01,0xf9,0x00,0x0c,0xeb,0x03,0x88,
+ 0x0a,0x00,0x00,0x02,0x00,0x03,0xfe,0x02,0xfa,0x00,
+ 0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c,0x01,0x7f,
+ 0x06,0x00,0x02,0x02,0x03,0xfe,0x03,0x8f,0x06,0x77,
+ 0x06,0x09,0xfa,0x80,0x00,0x71,0xff,0x87,0xfb,0x79,
+ 0x07,0x87,0x05,0x79,0x02,0x80,0x03,0x8d,0x02,0x02,
+ 0x06,0x00,0x02,0x7e,0x00,0x7d,0xfc,0x7d,0x04,0x7e,
+ 0x00,0x7d,0xfe,0x7e,0xfa,0x00,0xfe,0x02,0x04,0x85,
+ 0x02,0x00,0x06,0xf9,0x03,0x8f,0x00,0x73,0x01,0x7e,
+ 0x07,0x00,0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,
+ 0x03,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x07,0x00,
+ 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0xf8,0x90,
+ 0x03,0x00,0x08,0xf0,0x03,0x80,0x00,0x15,0x00,0xf3,
+ 0x02,0x00,0x06,0x07,0xfa,0xf9,0x07,0x78,0x03,0x80,
+ 0x03,0x80,0x04,0x0c,0x02,0x03,0x04,0x00,0x00,0x71,
+ 0x02,0x80,0x03,0x80,0x00,0x0f,0x06,0x77,0x06,0x09,
+ 0x00,0x71,0x02,0x80,0x03,0x80,0x00,0x0f,0x0a,0xf1,
+ 0x00,0x0f,0xf6,0xf8,0x0a,0x00,0x02,0xf9,0x05,0x80,
+ 0xff,0x01,0xff,0x04,0x00,0x05,0x01,0x03,0x01,0x02,
+ 0x06,0x00,0x02,0x7e,0x00,0x7d,0x00,0x7b,0x00,0x7c,
+ 0xfe,0x7f,0xfa,0x00,0x0b,0x80,0x03,0x80,0x00,0x0f,
+ 0x00,0xfb,0x01,0x03,0x01,0x02,0x05,0x00,0x02,0x7e,
+ 0x01,0x7d,0x00,0x76,0x03,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
+ 0x10,0x80,0x0a,0x8f,0x02,0x7f,0x01,0x7e,0x00,0x76,
+ 0xff,0x7f,0xfe,0x7f,0xfb,0x00,0xff,0x01,0xff,0x01,
+ 0x00,0x0a,0x01,0x02,0x01,0x01,0x05,0x00,0xf9,0x80,
+ 0x00,0x6b,0x0c,0x86,0x0d,0x8a,0xff,0x03,0xfe,0x02,
+ 0xfb,0x00,0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c,
+ 0x01,0x7f,0x05,0x00,0x02,0x01,0x01,0x03,0x03,0xfc,
+ 0x03,0x80,0x00,0x0f,0x00,0xfb,0x01,0x03,0x01,0x02,
+ 0x04,0x00,0x01,0x7e,0x01,0x7d,0x00,0x76,0x00,0x8a,
+ 0x01,0x03,0x02,0x02,0x03,0x00,0x02,0x7e,0x01,0x7d,
+ 0x00,0x76,0x03,0x80,0x03,0x8f,0x00,0x74,0x01,0x7e,
+ 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x01,0x00,0x8d,
+ 0x00,0x6e,0xff,0x7e,0xfe,0x7f,0xfb,0x00,0xfe,0x01,
+ 0x0c,0x85,0x03,0x8d,0x01,0x02,0x03,0x00,0x02,0x7e,
+ 0x01,0x02,0x03,0x00,0x02,0x7e,0x00,0x74,0xfe,0x7f,
+ 0xfd,0x00,0xff,0x01,0xfe,0x7f,0xfd,0x00,0xff,0x01,
+ 0x00,0x0c,0x06,0x82,0x00,0x6b,0x08,0x86,0x03,0x80,
+ 0x0a,0x0f,0xf6,0x80,0x0a,0x71,0x03,0x80,0x03,0x8f,
+ 0x00,0x73,0x01,0x7e,0x07,0x00,0x02,0x02,0x00,0x0d,
+ 0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82,0x03,0x8f,
+ 0x00,0x79,0x02,0x7e,0x08,0x00,0x00,0x89,0x00,0x71,
+ 0x02,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00,
+ 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00,
+ 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x80,
+ 0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00,0x02,0x02,
+ 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00,0x02,0x02,
+ 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82,
+ 0x03,0x8d,0x00,0x02,0x02,0x00,0x00,0x71,0x08,0x00,
+ 0x02,0x02,0x00,0x06,0xfe,0x02,0xf8,0x00,0x0c,0xf6,
+ 0x03,0x8f,0x00,0x71,0x07,0x00,0x02,0x02,0x00,0x06,
+ 0xfe,0x02,0xf9,0x00,0x0c,0x85,0x00,0x71,0x02,0x80,
+ 0x03,0x8f,0x00,0x71,0x07,0x00,0x03,0x02,0x00,0x06,
+ 0xfd,0x02,0xf9,0x00,0x0c,0xf6,0x03,0x8d,0x02,0x02,
+ 0x06,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfa,0x00,
+ 0xfe,0x02,0x04,0x85,0x06,0x00,0x02,0xf9,0x03,0x80,
+ 0x00,0x0f,0x00,0xf8,0x04,0x00,0x00,0x06,0x02,0x02,
+ 0x04,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfc,0x00,
+ 0xfe,0x02,0x00,0x05,0x0a,0xf9,0x0d,0x80,0x00,0x0f,
+ 0xf7,0x00,0xff,0x7e,0x00,0x7b,0x01,0x7e,0x09,0x00,
+ 0xf6,0xfa,0x04,0x06,0x08,0xfa
+ };
+
+ //-------------------------------------------------------------------------
+ gsv_text::gsv_text() :
+ m_x(0.0),
+ m_y(0.0),
+ m_start_x(0.0),
+ m_width(10.0),
+ m_height(0.0),
+ m_space(0.0),
+ m_line_space(0.0),
+ m_text(m_chr),
+ m_text_buf(),
+ m_cur_chr(m_chr),
+ m_font(gsv_default_font),
+ m_loaded_font(),
+ m_status(initial),
+ m_big_endian(false),
+ m_flip(false)
+ {
+ m_chr[0] = m_chr[1] = 0;
+
+ int t = 1;
+ if(*(char*)&t == 0) m_big_endian = true;
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::font(const void* font)
+ {
+ m_font = font;
+ if(m_font == 0) m_font = &m_loaded_font[0];
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::size(double height, double width)
+ {
+ m_height = height;
+ m_width = width;
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::space(double space)
+ {
+ m_space = space;
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::line_space(double line_space)
+ {
+ m_line_space = line_space;
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::start_point(double x, double y)
+ {
+ m_x = m_start_x = x;
+ m_y = y;
+ //if(m_flip) m_y += m_height;
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::load_font(const char* file)
+ {
+ m_loaded_font.resize(0);
+ FILE* fd = fopen(file, "rb");
+ if(fd)
+ {
+ unsigned len;
+
+ fseek(fd, 0l, SEEK_END);
+ len = ftell(fd);
+ fseek(fd, 0l, SEEK_SET);
+ if(len > 0)
+ {
+ m_loaded_font.resize(len);
+ fread(&m_loaded_font[0], 1, len, fd);
+ m_font = &m_loaded_font[0];
+ }
+ fclose(fd);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::text(const char* text)
+ {
+ if(text == 0)
+ {
+ m_chr[0] = 0;
+ m_text = m_chr;
+ return;
+ }
+ unsigned new_size = strlen(text) + 1;
+ if(new_size > m_text_buf.size())
+ {
+ m_text_buf.resize(new_size);
+ }
+ memcpy(&m_text_buf[0], text, new_size);
+ m_text = &m_text_buf[0];
+ }
+
+ //-------------------------------------------------------------------------
+ void gsv_text::rewind(unsigned)
+ {
+ m_status = initial;
+ if(m_font == 0) return;
+
+ m_indices = (int8u*)m_font;
+ double base_height = value(m_indices + 4);
+ m_indices += value(m_indices);
+ m_glyphs = (int8*)(m_indices + 257*2);
+ m_h = m_height / base_height;
+ m_w = (m_width == 0.0) ? m_h : m_width / base_height;
+ if(m_flip) m_h = -m_h;
+ m_cur_chr = m_text;
+ }
+
+ //-------------------------------------------------------------------------
+ unsigned gsv_text::vertex(double* x, double* y)
+ {
+ unsigned idx;
+ int8 yc, yf;
+ int dx, dy;
+ bool quit = false;
+
+ while(!quit)
+ {
+ switch(m_status)
+ {
+ case initial:
+ if(m_font == 0)
+ {
+ quit = true;
+ break;
+ }
+ m_status = next_char;
+
+ case next_char:
+ if(*m_cur_chr == 0)
+ {
+ quit = true;
+ break;
+ }
+ idx = (*m_cur_chr++) & 0xFF;
+ if(idx == '\n')
+ {
+ m_x = m_start_x;
+ m_y -= m_flip ? -m_height - m_line_space : m_height + m_line_space;
+ break;
+ }
+ idx <<= 1;
+ m_bglyph = m_glyphs + value(m_indices + idx);
+ m_eglyph = m_glyphs + value(m_indices + idx + 2);
+ m_status = start_glyph;
+
+ case start_glyph:
+ *x = m_x;
+ *y = m_y;
+ m_status = glyph;
+ return path_cmd_move_to;
+
+ case glyph:
+ if(m_bglyph >= m_eglyph)
+ {
+ m_status = next_char;
+ m_x += m_space;
+ break;
+ }
+ dx = int(*m_bglyph++);
+ yf = (yc = *m_bglyph++) & 0x80;
+ yc <<= 1;
+ yc >>= 1;
+ dy = int(yc);
+ m_x += double(dx) * m_w;
+ m_y += double(dy) * m_h;
+ *x = m_x;
+ *y = m_y;
+ return yf ? path_cmd_move_to : path_cmd_line_to;
+ }
+
+ }
+ return path_cmd_stop;
+ }
+
+ //-------------------------------------------------------------------------
+ double gsv_text::text_width()
+ {
+ double x1, y1, x2, y2;
+ bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2);
+ return x2 - x1;
+ }
+
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_image_filters.cpp b/plugins/Clist_ng/AGG/src/agg_image_filters.cpp new file mode 100644 index 0000000000..fb508f61d7 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_image_filters.cpp @@ -0,0 +1,107 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_image_filters.h"
+
+
+namespace agg
+{
+ //--------------------------------------------------------------------
+ void image_filter_lut::realloc_lut(double radius)
+ {
+ m_radius = radius;
+ m_diameter = uceil(radius) * 2;
+ m_start = -int(m_diameter / 2 - 1);
+ unsigned size = m_diameter << image_subpixel_shift;
+ if(size > m_weight_array.size())
+ {
+ m_weight_array.resize(size);
+ }
+ }
+
+
+
+ //--------------------------------------------------------------------
+ // This function normalizes integer values and corrects the rounding
+ // errors. It doesn't do anything with the source floating point values
+ // (m_weight_array_dbl), it corrects only integers according to the rule
+ // of 1.0 which means that any sum of pixel weights must be equal to 1.0.
+ // So, the filter function must produce a graph of the proper shape.
+ //--------------------------------------------------------------------
+ void image_filter_lut::normalize()
+ {
+ unsigned i;
+ int flip = 1;
+
+ for(i = 0; i < image_subpixel_scale; i++)
+ {
+ for(;;)
+ {
+ int sum = 0;
+ unsigned j;
+ for(j = 0; j < m_diameter; j++)
+ {
+ sum += m_weight_array[j * image_subpixel_scale + i];
+ }
+
+ if(sum == image_filter_scale) break;
+
+ double k = double(image_filter_scale) / double(sum);
+ sum = 0;
+ for(j = 0; j < m_diameter; j++)
+ {
+ sum += m_weight_array[j * image_subpixel_scale + i] =
+ iround(m_weight_array[j * image_subpixel_scale + i] * k);
+ }
+
+ sum -= image_filter_scale;
+ int inc = (sum > 0) ? -1 : 1;
+
+ for(j = 0; j < m_diameter && sum; j++)
+ {
+ flip ^= 1;
+ unsigned idx = flip ? m_diameter/2 + j/2 : m_diameter/2 - j/2;
+ int v = m_weight_array[idx * image_subpixel_scale + i];
+ if(v < image_filter_scale)
+ {
+ m_weight_array[idx * image_subpixel_scale + i] += inc;
+ sum += inc;
+ }
+ }
+ }
+ }
+
+ unsigned pivot = m_diameter << (image_subpixel_shift - 1);
+
+ for(i = 0; i < pivot; i++)
+ {
+ m_weight_array[pivot + i] = m_weight_array[pivot - i];
+ }
+ unsigned end = (diameter() << image_subpixel_shift) - 1;
+ m_weight_array[0] = m_weight_array[end];
+ }
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_line_aa_basics.cpp b/plugins/Clist_ng/AGG/src/agg_line_aa_basics.cpp new file mode 100644 index 0000000000..8570e5c717 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_line_aa_basics.cpp @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_line_aa_basics.h"
+
+namespace agg
+{
+ //-------------------------------------------------------------------------
+ // The number of the octant is determined as a 3-bit value as follows:
+ // bit 0 = vertical flag
+ // bit 1 = sx < 0
+ // bit 2 = sy < 0
+ //
+ // [N] shows the number of the orthogonal quadrant
+ // <M> shows the number of the diagonal quadrant
+ // <1>
+ // [1] | [0]
+ // . (3)011 | 001(1) .
+ // . | .
+ // . | .
+ // . | .
+ // (2)010 .|. 000(0)
+ // <2> ----------.+.----------- <0>
+ // (6)110 . | . 100(4)
+ // . | .
+ // . | .
+ // . | .
+ // (7)111 | 101(5)
+ // [2] | [3]
+ // <3>
+ // 0,1,2,3,4,5,6,7
+ const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 };
+ const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 };
+
+
+
+ //-------------------------------------------------------------------------
+ void bisectrix(const line_parameters& l1,
+ const line_parameters& l2,
+ int* x, int* y)
+ {
+ double k = double(l2.len) / double(l1.len);
+ double tx = l2.x2 - (l2.x1 - l1.x1) * k;
+ double ty = l2.y2 - (l2.y1 - l1.y1) * k;
+
+ //All bisectrices must be on the right of the line
+ //If the next point is on the left (l1 => l2.2)
+ //then the bisectix should be rotated by 180 degrees.
+ if(double(l2.x2 - l2.x1) * double(l2.y1 - l1.y1) <
+ double(l2.y2 - l2.y1) * double(l2.x1 - l1.x1) + 100.0)
+ {
+ tx -= (tx - l2.x1) * 2.0;
+ ty -= (ty - l2.y1) * 2.0;
+ }
+
+ // Check if the bisectrix is too short
+ double dx = tx - l2.x1;
+ double dy = ty - l2.y1;
+ if((int)sqrt(dx * dx + dy * dy) < line_subpixel_scale)
+ {
+ *x = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) >> 1;
+ *y = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) >> 1;
+ return;
+ }
+ *x = iround(tx);
+ *y = iround(ty);
+ }
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_line_profile_aa.cpp b/plugins/Clist_ng/AGG/src/agg_line_profile_aa.cpp new file mode 100644 index 0000000000..1df9e2cb82 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_line_profile_aa.cpp @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_renderer_outline_aa.h"
+
+namespace agg
+{
+
+ //---------------------------------------------------------------------
+ void line_profile_aa::width(double w)
+ {
+ if(w < 0.0) w = 0.0;
+
+ if(w < m_smoother_width) w += w;
+ else w += m_smoother_width;
+
+ w *= 0.5;
+
+ w -= m_smoother_width;
+ double s = m_smoother_width;
+ if(w < 0.0)
+ {
+ s += w;
+ w = 0.0;
+ }
+ set(w, s);
+ }
+
+
+ //---------------------------------------------------------------------
+ line_profile_aa::value_type* line_profile_aa::profile(double w)
+ {
+ m_subpixel_width = uround(w * subpixel_scale);
+ unsigned size = m_subpixel_width + subpixel_scale * 6;
+ if(size > m_profile.size())
+ {
+ m_profile.resize(size);
+ }
+ return &m_profile[0];
+ }
+
+
+ //---------------------------------------------------------------------
+ void line_profile_aa::set(double center_width, double smoother_width)
+ {
+ double base_val = 1.0;
+ if(center_width == 0.0) center_width = 1.0 / subpixel_scale;
+ if(smoother_width == 0.0) smoother_width = 1.0 / subpixel_scale;
+
+ double width = center_width + smoother_width;
+ if(width < m_min_width)
+ {
+ double k = width / m_min_width;
+ base_val *= k;
+ center_width /= k;
+ smoother_width /= k;
+ }
+
+ value_type* ch = profile(center_width + smoother_width);
+
+ unsigned subpixel_center_width = unsigned(center_width * subpixel_scale);
+ unsigned subpixel_smoother_width = unsigned(smoother_width * subpixel_scale);
+
+ value_type* ch_center = ch + subpixel_scale*2;
+ value_type* ch_smoother = ch_center + subpixel_center_width;
+
+ unsigned i;
+
+ unsigned val = m_gamma[unsigned(base_val * aa_mask)];
+ ch = ch_center;
+ for(i = 0; i < subpixel_center_width; i++)
+ {
+ *ch++ = (value_type)val;
+ }
+
+ for(i = 0; i < subpixel_smoother_width; i++)
+ {
+ *ch_smoother++ =
+ m_gamma[unsigned((base_val -
+ base_val *
+ (double(i) / subpixel_smoother_width)) * aa_mask)];
+ }
+
+ unsigned n_smoother = profile_size() -
+ subpixel_smoother_width -
+ subpixel_center_width -
+ subpixel_scale*2;
+
+ val = m_gamma[0];
+ for(i = 0; i < n_smoother; i++)
+ {
+ *ch_smoother++ = (value_type)val;
+ }
+
+ ch = ch_center;
+ for(i = 0; i < subpixel_scale*2; i++)
+ {
+ *--ch = *ch_center++;
+ }
+ }
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_rounded_rect.cpp b/plugins/Clist_ng/AGG/src/agg_rounded_rect.cpp new file mode 100644 index 0000000000..a480043a3d --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_rounded_rect.cpp @@ -0,0 +1,169 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_rounded_rect.h"
+
+
+namespace agg
+{
+ //------------------------------------------------------------------------
+ rounded_rect::rounded_rect(double x1, double y1, double x2, double y2, double r) :
+ m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2),
+ m_rx1(r), m_ry1(r), m_rx2(r), m_ry2(r),
+ m_rx3(r), m_ry3(r), m_rx4(r), m_ry4(r)
+ {
+ if(x1 > x2) { m_x1 = x2; m_x2 = x1; }
+ if(y1 > y2) { m_y1 = y2; m_y2 = y1; }
+ }
+
+ //--------------------------------------------------------------------
+ void rounded_rect::rect(double x1, double y1, double x2, double y2)
+ {
+ m_x1 = x1;
+ m_y1 = y1;
+ m_x2 = x2;
+ m_y2 = y2;
+ if(x1 > x2) { m_x1 = x2; m_x2 = x1; }
+ if(y1 > y2) { m_y1 = y2; m_y2 = y1; }
+ }
+
+ //--------------------------------------------------------------------
+ void rounded_rect::radius(double r)
+ {
+ m_rx1 = m_ry1 = m_rx2 = m_ry2 = m_rx3 = m_ry3 = m_rx4 = m_ry4 = r;
+ }
+
+ //--------------------------------------------------------------------
+ void rounded_rect::radius(double rx, double ry)
+ {
+ m_rx1 = m_rx2 = m_rx3 = m_rx4 = rx;
+ m_ry1 = m_ry2 = m_ry3 = m_ry4 = ry;
+ }
+
+ //--------------------------------------------------------------------
+ void rounded_rect::radius(double rx_bottom, double ry_bottom,
+ double rx_top, double ry_top)
+ {
+ m_rx1 = m_rx2 = rx_bottom;
+ m_rx3 = m_rx4 = rx_top;
+ m_ry1 = m_ry2 = ry_bottom;
+ m_ry3 = m_ry4 = ry_top;
+ }
+
+ //--------------------------------------------------------------------
+ void rounded_rect::radius(double rx1, double ry1, double rx2, double ry2,
+ double rx3, double ry3, double rx4, double ry4)
+ {
+ m_rx1 = rx1; m_ry1 = ry1; m_rx2 = rx2; m_ry2 = ry2;
+ m_rx3 = rx3; m_ry3 = ry3; m_rx4 = rx4; m_ry4 = ry4;
+ }
+
+ //--------------------------------------------------------------------
+ void rounded_rect::normalize_radius()
+ {
+ double dx = fabs(m_x2 - m_x1);
+ double dy = fabs(m_y2 - m_y1);
+
+ double k = 1.0;
+ double t;
+ t = dx / (m_rx1 + m_rx2); if(t < k) k = t;
+ t = dx / (m_rx3 + m_rx4); if(t < k) k = t;
+ t = dy / (m_ry1 + m_ry2); if(t < k) k = t;
+ t = dy / (m_ry3 + m_ry4); if(t < k) k = t;
+
+ if(k < 1.0)
+ {
+ m_rx1 *= k; m_ry1 *= k; m_rx2 *= k; m_ry2 *= k;
+ m_rx3 *= k; m_ry3 *= k; m_rx4 *= k; m_ry4 *= k;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void rounded_rect::rewind(unsigned)
+ {
+ m_status = 0;
+ }
+
+ //--------------------------------------------------------------------
+ unsigned rounded_rect::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_stop;
+ switch(m_status)
+ {
+ case 0:
+ m_arc.init(m_x1 + m_rx1, m_y1 + m_ry1, m_rx1, m_ry1,
+ pi, pi+pi*0.5);
+ m_arc.rewind(0);
+ m_status++;
+
+ case 1:
+ cmd = m_arc.vertex(x, y);
+ if(is_stop(cmd)) m_status++;
+ else return cmd;
+
+ case 2:
+ m_arc.init(m_x2 - m_rx2, m_y1 + m_ry2, m_rx2, m_ry2,
+ pi+pi*0.5, 0.0);
+ m_arc.rewind(0);
+ m_status++;
+
+ case 3:
+ cmd = m_arc.vertex(x, y);
+ if(is_stop(cmd)) m_status++;
+ else return path_cmd_line_to;
+
+ case 4:
+ m_arc.init(m_x2 - m_rx3, m_y2 - m_ry3, m_rx3, m_ry3,
+ 0.0, pi*0.5);
+ m_arc.rewind(0);
+ m_status++;
+
+ case 5:
+ cmd = m_arc.vertex(x, y);
+ if(is_stop(cmd)) m_status++;
+ else return path_cmd_line_to;
+
+ case 6:
+ m_arc.init(m_x1 + m_rx4, m_y2 - m_ry4, m_rx4, m_ry4,
+ pi*0.5, pi);
+ m_arc.rewind(0);
+ m_status++;
+
+ case 7:
+ cmd = m_arc.vertex(x, y);
+ if(is_stop(cmd)) m_status++;
+ else return path_cmd_line_to;
+
+ case 8:
+ cmd = path_cmd_end_poly | path_flags_close | path_flags_ccw;
+ m_status++;
+ break;
+ }
+ return cmd;
+ }
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_sqrt_tables.cpp b/plugins/Clist_ng/AGG/src/agg_sqrt_tables.cpp new file mode 100644 index 0000000000..52c311c5f9 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_sqrt_tables.cpp @@ -0,0 +1,120 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_basics.h"
+
+namespace agg
+{
+ int16u g_sqrt_table[1024] = //----------g_sqrt_table
+ {
+ 0,
+ 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444,
+ 8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585,
+ 11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890,
+ 14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864,
+ 15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618,
+ 17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212,
+ 19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684,
+ 20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058,
+ 22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351,
+ 23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576,
+ 24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743,
+ 25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859,
+ 26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931,
+ 28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963,
+ 29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960,
+ 30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924,
+ 30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859,
+ 31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768,
+ 32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652,
+ 33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514,
+ 34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354,
+ 35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175,
+ 36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978,
+ 37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763,
+ 37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533,
+ 38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287,
+ 39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028,
+ 40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755,
+ 40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469,
+ 41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171,
+ 42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861,
+ 42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541,
+ 43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210,
+ 44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869,
+ 44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519,
+ 45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160,
+ 46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791,
+ 46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415,
+ 47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030,
+ 48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637,
+ 48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237,
+ 49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830,
+ 49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416,
+ 50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995,
+ 51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567,
+ 51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134,
+ 52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694,
+ 52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248,
+ 53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797,
+ 53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340,
+ 54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877,
+ 54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410,
+ 55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937,
+ 55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459,
+ 56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977,
+ 57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490,
+ 57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999,
+ 58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503,
+ 58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002,
+ 59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498,
+ 59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989,
+ 60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477,
+ 60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960,
+ 60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440,
+ 61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916,
+ 61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388,
+ 62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857,
+ 62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323,
+ 63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785,
+ 63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243,
+ 64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699,
+ 64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151,
+ 65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504
+ };
+
+
+ int8 g_elder_bit_table[256] = //---------g_elder_bit_table
+ {
+ 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+ };
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_trans_affine.cpp b/plugins/Clist_ng/AGG/src/agg_trans_affine.cpp new file mode 100644 index 0000000000..489c056cce --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_trans_affine.cpp @@ -0,0 +1,200 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_trans_affine.h"
+
+
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::parl_to_parl(const double* src,
+ const double* dst)
+ {
+ sx = src[2] - src[0];
+ shy = src[3] - src[1];
+ shx = src[4] - src[0];
+ sy = src[5] - src[1];
+ tx = src[0];
+ ty = src[1];
+ invert();
+ multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1],
+ dst[4] - dst[0], dst[5] - dst[1],
+ dst[0], dst[1]));
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::rect_to_parl(double x1, double y1,
+ double x2, double y2,
+ const double* parl)
+ {
+ double src[6];
+ src[0] = x1; src[1] = y1;
+ src[2] = x2; src[3] = y1;
+ src[4] = x2; src[5] = y2;
+ parl_to_parl(src, parl);
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::parl_to_rect(const double* parl,
+ double x1, double y1,
+ double x2, double y2)
+ {
+ double dst[6];
+ dst[0] = x1; dst[1] = y1;
+ dst[2] = x2; dst[3] = y1;
+ dst[4] = x2; dst[5] = y2;
+ parl_to_parl(parl, dst);
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::multiply(const trans_affine& m)
+ {
+ double t0 = sx * m.sx + shy * m.shx;
+ double t2 = shx * m.sx + sy * m.shx;
+ double t4 = tx * m.sx + ty * m.shx + m.tx;
+ shy = sx * m.shy + shy * m.sy;
+ sy = shx * m.shy + sy * m.sy;
+ ty = tx * m.shy + ty * m.sy + m.ty;
+ sx = t0;
+ shx = t2;
+ tx = t4;
+ return *this;
+ }
+
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::invert()
+ {
+ double d = determinant_reciprocal();
+
+ double t0 = sy * d;
+ sy = sx * d;
+ shy = -shy * d;
+ shx = -shx * d;
+
+ double t4 = -tx * t0 - ty * shx;
+ ty = -tx * shy - ty * sy;
+
+ sx = t0;
+ tx = t4;
+ return *this;
+ }
+
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::flip_x()
+ {
+ sx = -sx;
+ shy = -shy;
+ tx = -tx;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::flip_y()
+ {
+ shx = -shx;
+ sy = -sy;
+ ty = -ty;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ const trans_affine& trans_affine::reset()
+ {
+ sx = sy = 1.0;
+ shy = shx = tx = ty = 0.0;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------
+ bool trans_affine::is_identity(double epsilon) const
+ {
+ return is_equal_eps(sx, 1.0, epsilon) &&
+ is_equal_eps(shy, 0.0, epsilon) &&
+ is_equal_eps(shx, 0.0, epsilon) &&
+ is_equal_eps(sy, 1.0, epsilon) &&
+ is_equal_eps(tx, 0.0, epsilon) &&
+ is_equal_eps(ty, 0.0, epsilon);
+ }
+
+ //------------------------------------------------------------------------
+ bool trans_affine::is_valid(double epsilon) const
+ {
+ return fabs(sx) > epsilon && fabs(sy) > epsilon;
+ }
+
+ //------------------------------------------------------------------------
+ bool trans_affine::is_equal(const trans_affine& m, double epsilon) const
+ {
+ return is_equal_eps(sx, m.sx, epsilon) &&
+ is_equal_eps(shy, m.shy, epsilon) &&
+ is_equal_eps(shx, m.shx, epsilon) &&
+ is_equal_eps(sy, m.sy, epsilon) &&
+ is_equal_eps(tx, m.tx, epsilon) &&
+ is_equal_eps(ty, m.ty, epsilon);
+ }
+
+ //------------------------------------------------------------------------
+ double trans_affine::rotation() const
+ {
+ double x1 = 0.0;
+ double y1 = 0.0;
+ double x2 = 1.0;
+ double y2 = 0.0;
+ transform(&x1, &y1);
+ transform(&x2, &y2);
+ return atan2(y2-y1, x2-x1);
+ }
+
+ //------------------------------------------------------------------------
+ void trans_affine::translation(double* dx, double* dy) const
+ {
+ *dx = tx;
+ *dy = ty;
+ }
+
+ //------------------------------------------------------------------------
+ void trans_affine::scaling(double* x, double* y) const
+ {
+ double x1 = 0.0;
+ double y1 = 0.0;
+ double x2 = 1.0;
+ double y2 = 1.0;
+ trans_affine t(*this);
+ t *= trans_affine_rotation(-rotation());
+ t.transform(&x1, &y1);
+ t.transform(&x2, &y2);
+ *x = x2 - x1;
+ *y = y2 - y1;
+ }
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_trans_double_path.cpp b/plugins/Clist_ng/AGG/src/agg_trans_double_path.cpp new file mode 100644 index 0000000000..fc3d184e5b --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_trans_double_path.cpp @@ -0,0 +1,282 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_math.h"
+#include "agg_trans_double_path.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ trans_double_path::trans_double_path() :
+ m_kindex1(0.0),
+ m_kindex2(0.0),
+ m_base_length(0.0),
+ m_base_height(1.0),
+ m_status1(initial),
+ m_status2(initial),
+ m_preserve_x_scale(true)
+ {
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::reset()
+ {
+ m_src_vertices1.remove_all();
+ m_src_vertices2.remove_all();
+ m_kindex1 = 0.0;
+ m_kindex1 = 0.0;
+ m_status1 = initial;
+ m_status2 = initial;
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::move_to1(double x, double y)
+ {
+ if(m_status1 == initial)
+ {
+ m_src_vertices1.modify_last(vertex_dist(x, y));
+ m_status1 = making_path;
+ }
+ else
+ {
+ line_to1(x, y);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::line_to1(double x, double y)
+ {
+ if(m_status1 == making_path)
+ {
+ m_src_vertices1.add(vertex_dist(x, y));
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::move_to2(double x, double y)
+ {
+ if(m_status2 == initial)
+ {
+ m_src_vertices2.modify_last(vertex_dist(x, y));
+ m_status2 = making_path;
+ }
+ else
+ {
+ line_to2(x, y);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::line_to2(double x, double y)
+ {
+ if(m_status2 == making_path)
+ {
+ m_src_vertices2.add(vertex_dist(x, y));
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ double trans_double_path::finalize_path(vertex_storage& vertices)
+ {
+ unsigned i;
+ double dist;
+ double d;
+
+ vertices.close(false);
+ if(vertices.size() > 2)
+ {
+ if(vertices[vertices.size() - 2].dist * 10.0 <
+ vertices[vertices.size() - 3].dist)
+ {
+ d = vertices[vertices.size() - 3].dist +
+ vertices[vertices.size() - 2].dist;
+
+ vertices[vertices.size() - 2] =
+ vertices[vertices.size() - 1];
+
+ vertices.remove_last();
+ vertices[vertices.size() - 2].dist = d;
+ }
+ }
+
+ dist = 0;
+ for(i = 0; i < vertices.size(); i++)
+ {
+ vertex_dist& v = vertices[i];
+ d = v.dist;
+ v.dist = dist;
+ dist += d;
+ }
+
+ return (vertices.size() - 1) / dist;
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::finalize_paths()
+ {
+ if(m_status1 == making_path && m_src_vertices1.size() > 1 &&
+ m_status2 == making_path && m_src_vertices2.size() > 1)
+ {
+ m_kindex1 = finalize_path(m_src_vertices1);
+ m_kindex2 = finalize_path(m_src_vertices2);
+ m_status1 = ready;
+ m_status2 = ready;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ double trans_double_path::total_length1() const
+ {
+ if(m_base_length >= 1e-10) return m_base_length;
+ return (m_status1 == ready) ?
+ m_src_vertices1[m_src_vertices1.size() - 1].dist :
+ 0.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ double trans_double_path::total_length2() const
+ {
+ if(m_base_length >= 1e-10) return m_base_length;
+ return (m_status2 == ready) ?
+ m_src_vertices2[m_src_vertices2.size() - 1].dist :
+ 0.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::transform1(const vertex_storage& vertices,
+ double kindex, double kx,
+ double *x, double* y) const
+ {
+ double x1 = 0.0;
+ double y1 = 0.0;
+ double dx = 1.0;
+ double dy = 1.0;
+ double d = 0.0;
+ double dd = 1.0;
+ *x *= kx;
+ if(*x < 0.0)
+ {
+ // Extrapolation on the left
+ //--------------------------
+ x1 = vertices[0].x;
+ y1 = vertices[0].y;
+ dx = vertices[1].x - x1;
+ dy = vertices[1].y - y1;
+ dd = vertices[1].dist - vertices[0].dist;
+ d = *x;
+ }
+ else
+ if(*x > vertices[vertices.size() - 1].dist)
+ {
+ // Extrapolation on the right
+ //--------------------------
+ unsigned i = vertices.size() - 2;
+ unsigned j = vertices.size() - 1;
+ x1 = vertices[j].x;
+ y1 = vertices[j].y;
+ dx = x1 - vertices[i].x;
+ dy = y1 - vertices[i].y;
+ dd = vertices[j].dist - vertices[i].dist;
+ d = *x - vertices[j].dist;
+ }
+ else
+ {
+ // Interpolation
+ //--------------------------
+ unsigned i = 0;
+ unsigned j = vertices.size() - 1;
+ if(m_preserve_x_scale)
+ {
+ unsigned k;
+ for(i = 0; (j - i) > 1; )
+ {
+ if(*x < vertices[k = (i + j) >> 1].dist)
+ {
+ j = k;
+ }
+ else
+ {
+ i = k;
+ }
+ }
+ d = vertices[i].dist;
+ dd = vertices[j].dist - d;
+ d = *x - d;
+ }
+ else
+ {
+ i = unsigned(*x * kindex);
+ j = i + 1;
+ dd = vertices[j].dist - vertices[i].dist;
+ d = ((*x * kindex) - i) * dd;
+ }
+ x1 = vertices[i].x;
+ y1 = vertices[i].y;
+ dx = vertices[j].x - x1;
+ dy = vertices[j].y - y1;
+ }
+ *x = x1 + dx * d / dd;
+ *y = y1 + dy * d / dd;
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_double_path::transform(double *x, double *y) const
+ {
+ if(m_status1 == ready && m_status2 == ready)
+ {
+ if(m_base_length > 1e-10)
+ {
+ *x *= m_src_vertices1[m_src_vertices1.size() - 1].dist /
+ m_base_length;
+ }
+
+ double x1 = *x;
+ double y1 = *y;
+ double x2 = *x;
+ double y2 = *y;
+ double dd = m_src_vertices2[m_src_vertices2.size() - 1].dist /
+ m_src_vertices1[m_src_vertices1.size() - 1].dist;
+
+ transform1(m_src_vertices1, m_kindex1, 1.0, &x1, &y1);
+ transform1(m_src_vertices2, m_kindex2, dd, &x2, &y2);
+
+ *x = x1 + *y * (x2 - x1) / m_base_height;
+ *y = y1 + *y * (y2 - y1) / m_base_height;
+ }
+ }
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_trans_single_path.cpp b/plugins/Clist_ng/AGG/src/agg_trans_single_path.cpp new file mode 100644 index 0000000000..368ab883a0 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_trans_single_path.cpp @@ -0,0 +1,211 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_math.h"
+#include "agg_vertex_sequence.h"
+#include "agg_trans_single_path.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ trans_single_path::trans_single_path() :
+ m_base_length(0.0),
+ m_kindex(0.0),
+ m_status(initial),
+ m_preserve_x_scale(true)
+ {
+ }
+
+ //------------------------------------------------------------------------
+ void trans_single_path::reset()
+ {
+ m_src_vertices.remove_all();
+ m_kindex = 0.0;
+ m_status = initial;
+ }
+
+ //------------------------------------------------------------------------
+ void trans_single_path::move_to(double x, double y)
+ {
+ if(m_status == initial)
+ {
+ m_src_vertices.modify_last(vertex_dist(x, y));
+ m_status = making_path;
+ }
+ else
+ {
+ line_to(x, y);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void trans_single_path::line_to(double x, double y)
+ {
+ if(m_status == making_path)
+ {
+ m_src_vertices.add(vertex_dist(x, y));
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_single_path::finalize_path()
+ {
+ if(m_status == making_path && m_src_vertices.size() > 1)
+ {
+ unsigned i;
+ double dist;
+ double d;
+
+ m_src_vertices.close(false);
+ if(m_src_vertices.size() > 2)
+ {
+ if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 <
+ m_src_vertices[m_src_vertices.size() - 3].dist)
+ {
+ d = m_src_vertices[m_src_vertices.size() - 3].dist +
+ m_src_vertices[m_src_vertices.size() - 2].dist;
+
+ m_src_vertices[m_src_vertices.size() - 2] =
+ m_src_vertices[m_src_vertices.size() - 1];
+
+ m_src_vertices.remove_last();
+ m_src_vertices[m_src_vertices.size() - 2].dist = d;
+ }
+ }
+
+ dist = 0.0;
+ for(i = 0; i < m_src_vertices.size(); i++)
+ {
+ vertex_dist& v = m_src_vertices[i];
+ double d = v.dist;
+ v.dist = dist;
+ dist += d;
+ }
+ m_kindex = (m_src_vertices.size() - 1) / dist;
+ m_status = ready;
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ double trans_single_path::total_length() const
+ {
+ if(m_base_length >= 1e-10) return m_base_length;
+ return (m_status == ready) ?
+ m_src_vertices[m_src_vertices.size() - 1].dist :
+ 0.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void trans_single_path::transform(double *x, double *y) const
+ {
+ if(m_status == ready)
+ {
+ if(m_base_length > 1e-10)
+ {
+ *x *= m_src_vertices[m_src_vertices.size() - 1].dist /
+ m_base_length;
+ }
+
+ double x1 = 0.0;
+ double y1 = 0.0;
+ double dx = 1.0;
+ double dy = 1.0;
+ double d = 0.0;
+ double dd = 1.0;
+ if(*x < 0.0)
+ {
+ // Extrapolation on the left
+ //--------------------------
+ x1 = m_src_vertices[0].x;
+ y1 = m_src_vertices[0].y;
+ dx = m_src_vertices[1].x - x1;
+ dy = m_src_vertices[1].y - y1;
+ dd = m_src_vertices[1].dist - m_src_vertices[0].dist;
+ d = *x;
+ }
+ else
+ if(*x > m_src_vertices[m_src_vertices.size() - 1].dist)
+ {
+ // Extrapolation on the right
+ //--------------------------
+ unsigned i = m_src_vertices.size() - 2;
+ unsigned j = m_src_vertices.size() - 1;
+ x1 = m_src_vertices[j].x;
+ y1 = m_src_vertices[j].y;
+ dx = x1 - m_src_vertices[i].x;
+ dy = y1 - m_src_vertices[i].y;
+ dd = m_src_vertices[j].dist - m_src_vertices[i].dist;
+ d = *x - m_src_vertices[j].dist;
+ }
+ else
+ {
+ // Interpolation
+ //--------------------------
+ unsigned i = 0;
+ unsigned j = m_src_vertices.size() - 1;
+ if(m_preserve_x_scale)
+ {
+ unsigned k;
+ for(i = 0; (j - i) > 1; )
+ {
+ if(*x < m_src_vertices[k = (i + j) >> 1].dist)
+ {
+ j = k;
+ }
+ else
+ {
+ i = k;
+ }
+ }
+ d = m_src_vertices[i].dist;
+ dd = m_src_vertices[j].dist - d;
+ d = *x - d;
+ }
+ else
+ {
+ i = unsigned(*x * m_kindex);
+ j = i + 1;
+ dd = m_src_vertices[j].dist - m_src_vertices[i].dist;
+ d = ((*x * m_kindex) - i) * dd;
+ }
+ x1 = m_src_vertices[i].x;
+ y1 = m_src_vertices[i].y;
+ dx = m_src_vertices[j].x - x1;
+ dy = m_src_vertices[j].y - y1;
+ }
+ double x2 = x1 + dx * d / dd;
+ double y2 = y1 + dy * d / dd;
+ *x = x2 - *y * dy / dd;
+ *y = y2 + *y * dx / dd;
+ }
+ }
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_trans_warp_magnifier.cpp b/plugins/Clist_ng/AGG/src/agg_trans_warp_magnifier.cpp new file mode 100644 index 0000000000..0854d06ce7 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_trans_warp_magnifier.cpp @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_trans_warp_magnifier.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ void trans_warp_magnifier::transform(double* x, double* y) const
+ {
+ double dx = *x - m_xc;
+ double dy = *y - m_yc;
+ double r = sqrt(dx * dx + dy * dy);
+ if(r < m_radius)
+ {
+ *x = m_xc + dx * m_magn;
+ *y = m_yc + dy * m_magn;
+ return;
+ }
+
+ double m = (r + m_radius * (m_magn - 1.0)) / r;
+ *x = m_xc + dx * m;
+ *y = m_yc + dy * m;
+ }
+
+ //------------------------------------------------------------------------
+ void trans_warp_magnifier::inverse_transform(double* x, double* y) const
+ {
+ // New version by Andrew Skalkin
+ //-----------------
+ double dx = *x - m_xc;
+ double dy = *y - m_yc;
+ double r = sqrt(dx * dx + dy * dy);
+
+ if(r < m_radius * m_magn)
+ {
+ *x = m_xc + dx / m_magn;
+ *y = m_yc + dy / m_magn;
+ }
+ else
+ {
+ double rnew = r - m_radius * (m_magn - 1.0);
+ *x = m_xc + rnew * dx / r;
+ *y = m_yc + rnew * dy / r;
+ }
+
+ // Old version
+ //-----------------
+ //trans_warp_magnifier t(*this);
+ //t.magnification(1.0 / m_magn);
+ //t.radius(m_radius * m_magn);
+ //t.transform(x, y);
+ }
+
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_vcgen_bspline.cpp b/plugins/Clist_ng/AGG/src/agg_vcgen_bspline.cpp new file mode 100644 index 0000000000..4483f612ee --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vcgen_bspline.cpp @@ -0,0 +1,203 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_vcgen_bspline.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ vcgen_bspline::vcgen_bspline() :
+ m_src_vertices(),
+ m_spline_x(),
+ m_spline_y(),
+ m_interpolation_step(1.0/50.0),
+ m_closed(0),
+ m_status(initial),
+ m_src_vertex(0)
+ {
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_bspline::remove_all()
+ {
+ m_src_vertices.remove_all();
+ m_closed = 0;
+ m_status = initial;
+ m_src_vertex = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_bspline::add_vertex(double x, double y, unsigned cmd)
+ {
+ m_status = initial;
+ if(is_move_to(cmd))
+ {
+ m_src_vertices.modify_last(point_d(x, y));
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ m_src_vertices.add(point_d(x, y));
+ }
+ else
+ {
+ m_closed = get_close_flag(cmd);
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_bspline::rewind(unsigned)
+ {
+ m_cur_abscissa = 0.0;
+ m_max_abscissa = 0.0;
+ m_src_vertex = 0;
+ if(m_status == initial && m_src_vertices.size() > 2)
+ {
+ if(m_closed)
+ {
+ m_spline_x.init(m_src_vertices.size() + 8);
+ m_spline_y.init(m_src_vertices.size() + 8);
+ m_spline_x.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).x);
+ m_spline_y.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).y);
+ m_spline_x.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].x);
+ m_spline_y.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].y);
+ m_spline_x.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].x);
+ m_spline_y.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].y);
+ m_spline_x.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].x);
+ m_spline_y.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].y);
+ }
+ else
+ {
+ m_spline_x.init(m_src_vertices.size());
+ m_spline_y.init(m_src_vertices.size());
+ }
+ unsigned i;
+ for(i = 0; i < m_src_vertices.size(); i++)
+ {
+ double x = m_closed ? i + 4 : i;
+ m_spline_x.add_point(x, m_src_vertices[i].x);
+ m_spline_y.add_point(x, m_src_vertices[i].y);
+ }
+ m_cur_abscissa = 0.0;
+ m_max_abscissa = m_src_vertices.size() - 1;
+ if(m_closed)
+ {
+ m_cur_abscissa = 4.0;
+ m_max_abscissa += 5.0;
+ m_spline_x.add_point(m_src_vertices.size() + 4, m_src_vertices[0].x);
+ m_spline_y.add_point(m_src_vertices.size() + 4, m_src_vertices[0].y);
+ m_spline_x.add_point(m_src_vertices.size() + 5, m_src_vertices[1].x);
+ m_spline_y.add_point(m_src_vertices.size() + 5, m_src_vertices[1].y);
+ m_spline_x.add_point(m_src_vertices.size() + 6, m_src_vertices[2].x);
+ m_spline_y.add_point(m_src_vertices.size() + 6, m_src_vertices[2].y);
+ m_spline_x.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).x);
+ m_spline_y.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).y);
+ }
+ m_spline_x.prepare();
+ m_spline_y.prepare();
+ }
+ m_status = ready;
+ }
+
+
+
+
+
+
+ //------------------------------------------------------------------------
+ unsigned vcgen_bspline::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ while(!is_stop(cmd))
+ {
+ switch(m_status)
+ {
+ case initial:
+ rewind(0);
+
+ case ready:
+ if(m_src_vertices.size() < 2)
+ {
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(m_src_vertices.size() == 2)
+ {
+ *x = m_src_vertices[m_src_vertex].x;
+ *y = m_src_vertices[m_src_vertex].y;
+ m_src_vertex++;
+ if(m_src_vertex == 1) return path_cmd_move_to;
+ if(m_src_vertex == 2) return path_cmd_line_to;
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ cmd = path_cmd_move_to;
+ m_status = polygon;
+ m_src_vertex = 0;
+
+ case polygon:
+ if(m_cur_abscissa >= m_max_abscissa)
+ {
+ if(m_closed)
+ {
+ m_status = end_poly;
+ break;
+ }
+ else
+ {
+ *x = m_src_vertices[m_src_vertices.size() - 1].x;
+ *y = m_src_vertices[m_src_vertices.size() - 1].y;
+ m_status = end_poly;
+ return path_cmd_line_to;
+ }
+ }
+
+ *x = m_spline_x.get_stateful(m_cur_abscissa);
+ *y = m_spline_y.get_stateful(m_cur_abscissa);
+ m_src_vertex++;
+ m_cur_abscissa += m_interpolation_step;
+ return (m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to;
+
+ case end_poly:
+ m_status = stop;
+ return path_cmd_end_poly | m_closed;
+
+ case stop:
+ return path_cmd_stop;
+ }
+ }
+ return cmd;
+ }
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_vcgen_contour.cpp b/plugins/Clist_ng/AGG/src/agg_vcgen_contour.cpp new file mode 100644 index 0000000000..02c8b73ff8 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vcgen_contour.cpp @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_vcgen_contour.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ vcgen_contour::vcgen_contour() :
+ m_stroker(),
+ m_width(1),
+ m_src_vertices(),
+ m_out_vertices(),
+ m_status(initial),
+ m_src_vertex(0),
+ m_closed(0),
+ m_orientation(0),
+ m_auto_detect(false)
+ {
+ }
+
+ //------------------------------------------------------------------------
+ void vcgen_contour::remove_all()
+ {
+ m_src_vertices.remove_all();
+ m_closed = 0;
+ m_orientation = 0;
+ m_status = initial;
+ }
+
+ //------------------------------------------------------------------------
+ void vcgen_contour::add_vertex(double x, double y, unsigned cmd)
+ {
+ m_status = initial;
+ if(is_move_to(cmd))
+ {
+ m_src_vertices.modify_last(vertex_dist(x, y));
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ m_src_vertices.add(vertex_dist(x, y));
+ }
+ else
+ {
+ if(is_end_poly(cmd))
+ {
+ m_closed = get_close_flag(cmd);
+ if(m_orientation == path_flags_none)
+ {
+ m_orientation = get_orientation(cmd);
+ }
+ }
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void vcgen_contour::rewind(unsigned)
+ {
+ if(m_status == initial)
+ {
+ m_src_vertices.close(true);
+ if(m_auto_detect)
+ {
+ if(!is_oriented(m_orientation))
+ {
+ m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ?
+ path_flags_ccw :
+ path_flags_cw;
+ }
+ }
+ if(is_oriented(m_orientation))
+ {
+ m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width);
+ }
+ }
+ m_status = ready;
+ m_src_vertex = 0;
+ }
+
+ //------------------------------------------------------------------------
+ unsigned vcgen_contour::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ while(!is_stop(cmd))
+ {
+ switch(m_status)
+ {
+ case initial:
+ rewind(0);
+
+ case ready:
+ if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
+ {
+ cmd = path_cmd_stop;
+ break;
+ }
+ m_status = outline;
+ cmd = path_cmd_move_to;
+ m_src_vertex = 0;
+ m_out_vertex = 0;
+
+ case outline:
+ if(m_src_vertex >= m_src_vertices.size())
+ {
+ m_status = end_poly;
+ break;
+ }
+ m_stroker.calc_join(m_out_vertices,
+ m_src_vertices.prev(m_src_vertex),
+ m_src_vertices.curr(m_src_vertex),
+ m_src_vertices.next(m_src_vertex),
+ m_src_vertices.prev(m_src_vertex).dist,
+ m_src_vertices.curr(m_src_vertex).dist);
+ ++m_src_vertex;
+ m_status = out_vertices;
+ m_out_vertex = 0;
+
+ case out_vertices:
+ if(m_out_vertex >= m_out_vertices.size())
+ {
+ m_status = outline;
+ }
+ else
+ {
+ const point_d& c = m_out_vertices[m_out_vertex++];
+ *x = c.x;
+ *y = c.y;
+ return cmd;
+ }
+ break;
+
+ case end_poly:
+ if(!m_closed) return path_cmd_stop;
+ m_status = stop;
+ return path_cmd_end_poly | path_flags_close | path_flags_ccw;
+
+ case stop:
+ return path_cmd_stop;
+ }
+ }
+ return cmd;
+ }
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_vcgen_dash.cpp b/plugins/Clist_ng/AGG/src/agg_vcgen_dash.cpp new file mode 100644 index 0000000000..60d2f9ac98 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vcgen_dash.cpp @@ -0,0 +1,240 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_vcgen_dash.h"
+#include "agg_shorten_path.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ vcgen_dash::vcgen_dash() :
+ m_total_dash_len(0.0),
+ m_num_dashes(0),
+ m_dash_start(0.0),
+ m_shorten(0.0),
+ m_curr_dash_start(0.0),
+ m_curr_dash(0),
+ m_src_vertices(),
+ m_closed(0),
+ m_status(initial),
+ m_src_vertex(0)
+ {
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void vcgen_dash::remove_all_dashes()
+ {
+ m_total_dash_len = 0.0;
+ m_num_dashes = 0;
+ m_curr_dash_start = 0.0;
+ m_curr_dash = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_dash::add_dash(double dash_len, double gap_len)
+ {
+ if(m_num_dashes < max_dashes)
+ {
+ m_total_dash_len += dash_len + gap_len;
+ m_dashes[m_num_dashes++] = dash_len;
+ m_dashes[m_num_dashes++] = gap_len;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_dash::dash_start(double ds)
+ {
+ m_dash_start = ds;
+ calc_dash_start(fabs(ds));
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_dash::calc_dash_start(double ds)
+ {
+ m_curr_dash = 0;
+ m_curr_dash_start = 0.0;
+ while(ds > 0.0)
+ {
+ if(ds > m_dashes[m_curr_dash])
+ {
+ ds -= m_dashes[m_curr_dash];
+ ++m_curr_dash;
+ m_curr_dash_start = 0.0;
+ if(m_curr_dash >= m_num_dashes) m_curr_dash = 0;
+ }
+ else
+ {
+ m_curr_dash_start = ds;
+ ds = 0.0;
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_dash::remove_all()
+ {
+ m_status = initial;
+ m_src_vertices.remove_all();
+ m_closed = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_dash::add_vertex(double x, double y, unsigned cmd)
+ {
+ m_status = initial;
+ if(is_move_to(cmd))
+ {
+ m_src_vertices.modify_last(vertex_dist(x, y));
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ m_src_vertices.add(vertex_dist(x, y));
+ }
+ else
+ {
+ m_closed = get_close_flag(cmd);
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_dash::rewind(unsigned)
+ {
+ if(m_status == initial)
+ {
+ m_src_vertices.close(m_closed != 0);
+ shorten_path(m_src_vertices, m_shorten, m_closed);
+ }
+ m_status = ready;
+ m_src_vertex = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned vcgen_dash::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_move_to;
+ while(!is_stop(cmd))
+ {
+ switch(m_status)
+ {
+ case initial:
+ rewind(0);
+
+ case ready:
+ if(m_num_dashes < 2 || m_src_vertices.size() < 2)
+ {
+ cmd = path_cmd_stop;
+ break;
+ }
+ m_status = polyline;
+ m_src_vertex = 1;
+ m_v1 = &m_src_vertices[0];
+ m_v2 = &m_src_vertices[1];
+ m_curr_rest = m_v1->dist;
+ *x = m_v1->x;
+ *y = m_v1->y;
+ if(m_dash_start >= 0.0) calc_dash_start(m_dash_start);
+ return path_cmd_move_to;
+
+ case polyline:
+ {
+ double dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start;
+
+ unsigned cmd = (m_curr_dash & 1) ?
+ path_cmd_move_to :
+ path_cmd_line_to;
+
+ if(m_curr_rest > dash_rest)
+ {
+ m_curr_rest -= dash_rest;
+ ++m_curr_dash;
+ if(m_curr_dash >= m_num_dashes) m_curr_dash = 0;
+ m_curr_dash_start = 0.0;
+ *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist;
+ *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist;
+ }
+ else
+ {
+ m_curr_dash_start += m_curr_rest;
+ *x = m_v2->x;
+ *y = m_v2->y;
+ ++m_src_vertex;
+ m_v1 = m_v2;
+ m_curr_rest = m_v1->dist;
+ if(m_closed)
+ {
+ if(m_src_vertex > m_src_vertices.size())
+ {
+ m_status = stop;
+ }
+ else
+ {
+ m_v2 = &m_src_vertices
+ [
+ (m_src_vertex >= m_src_vertices.size()) ? 0 :
+ m_src_vertex
+ ];
+ }
+ }
+ else
+ {
+ if(m_src_vertex >= m_src_vertices.size())
+ {
+ m_status = stop;
+ }
+ else
+ {
+ m_v2 = &m_src_vertices[m_src_vertex];
+ }
+ }
+ }
+ return cmd;
+ }
+ break;
+
+ case stop:
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ }
+ return path_cmd_stop;
+ }
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_vcgen_markers_term.cpp b/plugins/Clist_ng/AGG/src/agg_vcgen_markers_term.cpp new file mode 100644 index 0000000000..5863691f69 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vcgen_markers_term.cpp @@ -0,0 +1,108 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_vcgen_markers_term.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ void vcgen_markers_term::remove_all()
+ {
+ m_markers.remove_all();
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_markers_term::add_vertex(double x, double y, unsigned cmd)
+ {
+ if(is_move_to(cmd))
+ {
+ if(m_markers.size() & 1)
+ {
+ // Initial state, the first coordinate was added.
+ // If two of more calls of start_vertex() occures
+ // we just modify the last one.
+ m_markers.modify_last(coord_type(x, y));
+ }
+ else
+ {
+ m_markers.add(coord_type(x, y));
+ }
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ if(m_markers.size() & 1)
+ {
+ // Initial state, the first coordinate was added.
+ // Add three more points, 0,1,1,0
+ m_markers.add(coord_type(x, y));
+ m_markers.add(m_markers[m_markers.size() - 1]);
+ m_markers.add(m_markers[m_markers.size() - 3]);
+ }
+ else
+ {
+ if(m_markers.size())
+ {
+ // Replace two last points: 0,1,1,0 -> 0,1,2,1
+ m_markers[m_markers.size() - 1] = m_markers[m_markers.size() - 2];
+ m_markers[m_markers.size() - 2] = coord_type(x, y);
+ }
+ }
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_markers_term::rewind(unsigned path_id)
+ {
+ m_curr_id = path_id * 2;
+ m_curr_idx = m_curr_id;
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned vcgen_markers_term::vertex(double* x, double* y)
+ {
+ if(m_curr_id > 2 || m_curr_idx >= m_markers.size())
+ {
+ return path_cmd_stop;
+ }
+ const coord_type& c = m_markers[m_curr_idx];
+ *x = c.x;
+ *y = c.y;
+ if(m_curr_idx & 1)
+ {
+ m_curr_idx += 3;
+ return path_cmd_line_to;
+ }
+ ++m_curr_idx;
+ return path_cmd_move_to;
+ }
+
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_vcgen_smooth_poly1.cpp b/plugins/Clist_ng/AGG/src/agg_vcgen_smooth_poly1.cpp new file mode 100644 index 0000000000..359768aa78 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vcgen_smooth_poly1.cpp @@ -0,0 +1,230 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_vcgen_smooth_poly1.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ vcgen_smooth_poly1::vcgen_smooth_poly1() :
+ m_src_vertices(),
+ m_smooth_value(0.5),
+ m_closed(0),
+ m_status(initial),
+ m_src_vertex(0)
+ {
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_smooth_poly1::remove_all()
+ {
+ m_src_vertices.remove_all();
+ m_closed = 0;
+ m_status = initial;
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_smooth_poly1::add_vertex(double x, double y, unsigned cmd)
+ {
+ m_status = initial;
+ if(is_move_to(cmd))
+ {
+ m_src_vertices.modify_last(vertex_dist(x, y));
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ m_src_vertices.add(vertex_dist(x, y));
+ }
+ else
+ {
+ m_closed = get_close_flag(cmd);
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_smooth_poly1::rewind(unsigned)
+ {
+ if(m_status == initial)
+ {
+ m_src_vertices.close(m_closed != 0);
+ }
+ m_status = ready;
+ m_src_vertex = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_smooth_poly1::calculate(const vertex_dist& v0,
+ const vertex_dist& v1,
+ const vertex_dist& v2,
+ const vertex_dist& v3)
+ {
+
+ double k1 = v0.dist / (v0.dist + v1.dist);
+ double k2 = v1.dist / (v1.dist + v2.dist);
+
+ double xm1 = v0.x + (v2.x - v0.x) * k1;
+ double ym1 = v0.y + (v2.y - v0.y) * k1;
+ double xm2 = v1.x + (v3.x - v1.x) * k2;
+ double ym2 = v1.y + (v3.y - v1.y) * k2;
+
+ m_ctrl1_x = v1.x + m_smooth_value * (v2.x - xm1);
+ m_ctrl1_y = v1.y + m_smooth_value * (v2.y - ym1);
+ m_ctrl2_x = v2.x + m_smooth_value * (v1.x - xm2);
+ m_ctrl2_y = v2.y + m_smooth_value * (v1.y - ym2);
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned vcgen_smooth_poly1::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ while(!is_stop(cmd))
+ {
+ switch(m_status)
+ {
+ case initial:
+ rewind(0);
+
+ case ready:
+ if(m_src_vertices.size() < 2)
+ {
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(m_src_vertices.size() == 2)
+ {
+ *x = m_src_vertices[m_src_vertex].x;
+ *y = m_src_vertices[m_src_vertex].y;
+ m_src_vertex++;
+ if(m_src_vertex == 1) return path_cmd_move_to;
+ if(m_src_vertex == 2) return path_cmd_line_to;
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ cmd = path_cmd_move_to;
+ m_status = polygon;
+ m_src_vertex = 0;
+
+ case polygon:
+ if(m_closed)
+ {
+ if(m_src_vertex >= m_src_vertices.size())
+ {
+ *x = m_src_vertices[0].x;
+ *y = m_src_vertices[0].y;
+ m_status = end_poly;
+ return path_cmd_curve4;
+ }
+ }
+ else
+ {
+ if(m_src_vertex >= m_src_vertices.size() - 1)
+ {
+ *x = m_src_vertices[m_src_vertices.size() - 1].x;
+ *y = m_src_vertices[m_src_vertices.size() - 1].y;
+ m_status = end_poly;
+ return path_cmd_curve3;
+ }
+ }
+
+ calculate(m_src_vertices.prev(m_src_vertex),
+ m_src_vertices.curr(m_src_vertex),
+ m_src_vertices.next(m_src_vertex),
+ m_src_vertices.next(m_src_vertex + 1));
+
+ *x = m_src_vertices[m_src_vertex].x;
+ *y = m_src_vertices[m_src_vertex].y;
+ m_src_vertex++;
+
+ if(m_closed)
+ {
+ m_status = ctrl1;
+ return ((m_src_vertex == 1) ?
+ path_cmd_move_to :
+ path_cmd_curve4);
+ }
+ else
+ {
+ if(m_src_vertex == 1)
+ {
+ m_status = ctrl_b;
+ return path_cmd_move_to;
+ }
+ if(m_src_vertex >= m_src_vertices.size() - 1)
+ {
+ m_status = ctrl_e;
+ return path_cmd_curve3;
+ }
+ m_status = ctrl1;
+ return path_cmd_curve4;
+ }
+ break;
+
+ case ctrl_b:
+ *x = m_ctrl2_x;
+ *y = m_ctrl2_y;
+ m_status = polygon;
+ return path_cmd_curve3;
+
+ case ctrl_e:
+ *x = m_ctrl1_x;
+ *y = m_ctrl1_y;
+ m_status = polygon;
+ return path_cmd_curve3;
+
+ case ctrl1:
+ *x = m_ctrl1_x;
+ *y = m_ctrl1_y;
+ m_status = ctrl2;
+ return path_cmd_curve4;
+
+ case ctrl2:
+ *x = m_ctrl2_x;
+ *y = m_ctrl2_y;
+ m_status = polygon;
+ return path_cmd_curve4;
+
+ case end_poly:
+ m_status = stop;
+ return path_cmd_end_poly | m_closed;
+
+ case stop:
+ return path_cmd_stop;
+ }
+ }
+ return cmd;
+ }
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/agg_vcgen_stroke.cpp b/plugins/Clist_ng/AGG/src/agg_vcgen_stroke.cpp new file mode 100644 index 0000000000..b36927bf31 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vcgen_stroke.cpp @@ -0,0 +1,219 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_vcgen_stroke.h"
+#include "agg_shorten_path.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ vcgen_stroke::vcgen_stroke() :
+ m_stroker(),
+ m_src_vertices(),
+ m_out_vertices(),
+ m_shorten(0.0),
+ m_closed(0),
+ m_status(initial),
+ m_src_vertex(0),
+ m_out_vertex(0)
+ {
+ }
+
+ //------------------------------------------------------------------------
+ void vcgen_stroke::remove_all()
+ {
+ m_src_vertices.remove_all();
+ m_closed = 0;
+ m_status = initial;
+ }
+
+
+ //------------------------------------------------------------------------
+ void vcgen_stroke::add_vertex(double x, double y, unsigned cmd)
+ {
+ m_status = initial;
+ if(is_move_to(cmd))
+ {
+ m_src_vertices.modify_last(vertex_dist(x, y));
+ }
+ else
+ {
+ if(is_vertex(cmd))
+ {
+ m_src_vertices.add(vertex_dist(x, y));
+ }
+ else
+ {
+ m_closed = get_close_flag(cmd);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void vcgen_stroke::rewind(unsigned)
+ {
+ if(m_status == initial)
+ {
+ m_src_vertices.close(m_closed != 0);
+ shorten_path(m_src_vertices, m_shorten, m_closed);
+ if(m_src_vertices.size() < 3) m_closed = 0;
+ }
+ m_status = ready;
+ m_src_vertex = 0;
+ m_out_vertex = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned vcgen_stroke::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ while(!is_stop(cmd))
+ {
+ switch(m_status)
+ {
+ case initial:
+ rewind(0);
+
+ case ready:
+ if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
+ {
+ cmd = path_cmd_stop;
+ break;
+ }
+ m_status = m_closed ? outline1 : cap1;
+ cmd = path_cmd_move_to;
+ m_src_vertex = 0;
+ m_out_vertex = 0;
+ break;
+
+ case cap1:
+ m_stroker.calc_cap(m_out_vertices,
+ m_src_vertices[0],
+ m_src_vertices[1],
+ m_src_vertices[0].dist);
+ m_src_vertex = 1;
+ m_prev_status = outline1;
+ m_status = out_vertices;
+ m_out_vertex = 0;
+ break;
+
+ case cap2:
+ m_stroker.calc_cap(m_out_vertices,
+ m_src_vertices[m_src_vertices.size() - 1],
+ m_src_vertices[m_src_vertices.size() - 2],
+ m_src_vertices[m_src_vertices.size() - 2].dist);
+ m_prev_status = outline2;
+ m_status = out_vertices;
+ m_out_vertex = 0;
+ break;
+
+ case outline1:
+ if(m_closed)
+ {
+ if(m_src_vertex >= m_src_vertices.size())
+ {
+ m_prev_status = close_first;
+ m_status = end_poly1;
+ break;
+ }
+ }
+ else
+ {
+ if(m_src_vertex >= m_src_vertices.size() - 1)
+ {
+ m_status = cap2;
+ break;
+ }
+ }
+ m_stroker.calc_join(m_out_vertices,
+ m_src_vertices.prev(m_src_vertex),
+ m_src_vertices.curr(m_src_vertex),
+ m_src_vertices.next(m_src_vertex),
+ m_src_vertices.prev(m_src_vertex).dist,
+ m_src_vertices.curr(m_src_vertex).dist);
+ ++m_src_vertex;
+ m_prev_status = m_status;
+ m_status = out_vertices;
+ m_out_vertex = 0;
+ break;
+
+ case close_first:
+ m_status = outline2;
+ cmd = path_cmd_move_to;
+
+ case outline2:
+ if(m_src_vertex <= unsigned(m_closed == 0))
+ {
+ m_status = end_poly2;
+ m_prev_status = stop;
+ break;
+ }
+
+ --m_src_vertex;
+ m_stroker.calc_join(m_out_vertices,
+ m_src_vertices.next(m_src_vertex),
+ m_src_vertices.curr(m_src_vertex),
+ m_src_vertices.prev(m_src_vertex),
+ m_src_vertices.curr(m_src_vertex).dist,
+ m_src_vertices.prev(m_src_vertex).dist);
+
+ m_prev_status = m_status;
+ m_status = out_vertices;
+ m_out_vertex = 0;
+ break;
+
+ case out_vertices:
+ if(m_out_vertex >= m_out_vertices.size())
+ {
+ m_status = m_prev_status;
+ }
+ else
+ {
+ const point_d& c = m_out_vertices[m_out_vertex++];
+ *x = c.x;
+ *y = c.y;
+ return cmd;
+ }
+ break;
+
+ case end_poly1:
+ m_status = m_prev_status;
+ return path_cmd_end_poly | path_flags_close | path_flags_ccw;
+
+ case end_poly2:
+ m_status = m_prev_status;
+ return path_cmd_end_poly | path_flags_close | path_flags_cw;
+
+ case stop:
+ cmd = path_cmd_stop;
+ break;
+ }
+ }
+ return cmd;
+ }
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_vpgen_clip_polygon.cpp b/plugins/Clist_ng/AGG/src/agg_vpgen_clip_polygon.cpp new file mode 100644 index 0000000000..2e9502ce06 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vpgen_clip_polygon.cpp @@ -0,0 +1,142 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_vpgen_clip_polygon.h"
+#include "agg_clip_liang_barsky.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ // Determine the clipping code of the vertex according to the
+ // Cyrus-Beck line clipping algorithm
+ //
+ // | |
+ // 0110 | 0010 | 0011
+ // | |
+ // -------+--------+-------- clip_box.y2
+ // | |
+ // 0100 | 0000 | 0001
+ // | |
+ // -------+--------+-------- clip_box.y1
+ // | |
+ // 1100 | 1000 | 1001
+ // | |
+ // clip_box.x1 clip_box.x2
+ //
+ //
+ unsigned vpgen_clip_polygon::clipping_flags(double x, double y)
+ {
+ if(x < m_clip_box.x1)
+ {
+ if(y > m_clip_box.y2) return 6;
+ if(y < m_clip_box.y1) return 12;
+ return 4;
+ }
+
+ if(x > m_clip_box.x2)
+ {
+ if(y > m_clip_box.y2) return 3;
+ if(y < m_clip_box.y1) return 9;
+ return 1;
+ }
+
+ if(y > m_clip_box.y2) return 2;
+ if(y < m_clip_box.y1) return 8;
+
+ return 0;
+ }
+
+ //----------------------------------------------------------------------------
+ void vpgen_clip_polygon::reset()
+ {
+ m_vertex = 0;
+ m_num_vertices = 0;
+ }
+
+ //----------------------------------------------------------------------------
+ void vpgen_clip_polygon::move_to(double x, double y)
+ {
+ m_vertex = 0;
+ m_num_vertices = 0;
+ m_clip_flags = clipping_flags(x, y);
+ if(m_clip_flags == 0)
+ {
+ m_x[0] = x;
+ m_y[0] = y;
+ m_num_vertices = 1;
+ }
+ m_x1 = x;
+ m_y1 = y;
+ m_cmd = path_cmd_move_to;
+ }
+
+
+ //----------------------------------------------------------------------------
+ void vpgen_clip_polygon::line_to(double x, double y)
+ {
+ m_vertex = 0;
+ m_num_vertices = 0;
+ unsigned flags = clipping_flags(x, y);
+
+ if(m_clip_flags == flags)
+ {
+ if(flags == 0)
+ {
+ m_x[0] = x;
+ m_y[0] = y;
+ m_num_vertices = 1;
+ }
+ }
+ else
+ {
+ m_num_vertices = clip_liang_barsky(m_x1, m_y1,
+ x, y,
+ m_clip_box,
+ m_x, m_y);
+ }
+
+ m_clip_flags = flags;
+ m_x1 = x;
+ m_y1 = y;
+ }
+
+
+ //----------------------------------------------------------------------------
+ unsigned vpgen_clip_polygon::vertex(double* x, double* y)
+ {
+ if(m_vertex < m_num_vertices)
+ {
+ *x = m_x[m_vertex];
+ *y = m_y[m_vertex];
+ ++m_vertex;
+ unsigned cmd = m_cmd;
+ m_cmd = path_cmd_line_to;
+ return cmd;
+ }
+ return path_cmd_stop;
+ }
+
+
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_vpgen_clip_polyline.cpp b/plugins/Clist_ng/AGG/src/agg_vpgen_clip_polyline.cpp new file mode 100644 index 0000000000..9b2f726807 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vpgen_clip_polyline.cpp @@ -0,0 +1,86 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "agg_vpgen_clip_polyline.h"
+#include "agg_clip_liang_barsky.h"
+
+namespace agg
+{
+ //----------------------------------------------------------------------------
+ void vpgen_clip_polyline::reset()
+ {
+ m_vertex = 0;
+ m_num_vertices = 0;
+ m_move_to = false;
+ }
+
+ //----------------------------------------------------------------------------
+ void vpgen_clip_polyline::move_to(double x, double y)
+ {
+ m_vertex = 0;
+ m_num_vertices = 0;
+ m_x1 = x;
+ m_y1 = y;
+ m_move_to = true;
+ }
+
+ //----------------------------------------------------------------------------
+ void vpgen_clip_polyline::line_to(double x, double y)
+ {
+ double x2 = x;
+ double y2 = y;
+ unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box);
+
+ m_vertex = 0;
+ m_num_vertices = 0;
+ if((flags & 4) == 0)
+ {
+ if((flags & 1) != 0 || m_move_to)
+ {
+ m_x[0] = m_x1;
+ m_y[0] = m_y1;
+ m_cmd[0] = path_cmd_move_to;
+ m_num_vertices = 1;
+ }
+ m_x[m_num_vertices] = x2;
+ m_y[m_num_vertices] = y2;
+ m_cmd[m_num_vertices++] = path_cmd_line_to;
+ m_move_to = (flags & 2) != 0;
+ }
+ m_x1 = x;
+ m_y1 = y;
+ }
+
+ //----------------------------------------------------------------------------
+ unsigned vpgen_clip_polyline::vertex(double* x, double* y)
+ {
+ if(m_vertex < m_num_vertices)
+ {
+ *x = m_x[m_vertex];
+ *y = m_y[m_vertex];
+ return m_cmd[m_vertex++];
+ }
+ return path_cmd_stop;
+ }
+}
diff --git a/plugins/Clist_ng/AGG/src/agg_vpgen_segmentator.cpp b/plugins/Clist_ng/AGG/src/agg_vpgen_segmentator.cpp new file mode 100644 index 0000000000..eb5df3f34a --- /dev/null +++ b/plugins/Clist_ng/AGG/src/agg_vpgen_segmentator.cpp @@ -0,0 +1,76 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+#include "agg_vpgen_segmentator.h"
+
+namespace agg
+{
+
+ void vpgen_segmentator::move_to(double x, double y)
+ {
+ m_x1 = x;
+ m_y1 = y;
+ m_dx = 0.0;
+ m_dy = 0.0;
+ m_dl = 2.0;
+ m_ddl = 2.0;
+ m_cmd = path_cmd_move_to;
+ }
+
+ void vpgen_segmentator::line_to(double x, double y)
+ {
+ m_x1 += m_dx;
+ m_y1 += m_dy;
+ m_dx = x - m_x1;
+ m_dy = y - m_y1;
+ double len = sqrt(m_dx * m_dx + m_dy * m_dy) * m_approximation_scale;
+ if(len < 1e-30) len = 1e-30;
+ m_ddl = 1.0 / len;
+ m_dl = (m_cmd == path_cmd_move_to) ? 0.0 : m_ddl;
+ if(m_cmd == path_cmd_stop) m_cmd = path_cmd_line_to;
+ }
+
+ unsigned vpgen_segmentator::vertex(double* x, double* y)
+ {
+ if(m_cmd == path_cmd_stop) return path_cmd_stop;
+
+ unsigned cmd = m_cmd;
+ m_cmd = path_cmd_line_to;
+ if(m_dl >= 1.0 - m_ddl)
+ {
+ m_dl = 1.0;
+ m_cmd = path_cmd_stop;
+ *x = m_x1 + m_dx;
+ *y = m_y1 + m_dy;
+ return cmd;
+ }
+ *x = m_x1 + m_dx * m_dl;
+ *y = m_y1 + m_dy * m_dl;
+ m_dl += m_ddl;
+ return cmd;
+ }
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/authors b/plugins/Clist_ng/AGG/src/authors new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/authors diff --git a/plugins/Clist_ng/AGG/src/autogen.sh b/plugins/Clist_ng/AGG/src/autogen.sh new file mode 100644 index 0000000000..d37d8e2b9f --- /dev/null +++ b/plugins/Clist_ng/AGG/src/autogen.sh @@ -0,0 +1,20 @@ +# autogen.sh
+#
+# invoke the auto* tools to create the configureation system
+
+# build aclocal.m4
+aclocal
+
+# build the configure script
+autoconf
+
+# set up libtool
+libtoolize --force
+
+# invoke automake
+automake --foreign --add-missing
+
+# and finally invoke our new configure
+./configure $*
+
+# end
diff --git a/plugins/Clist_ng/AGG/src/configure.in b/plugins/Clist_ng/AGG/src/configure.in new file mode 100644 index 0000000000..fe58b42909 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/configure.in @@ -0,0 +1,15 @@ +AC_INIT(src/agg_arc.cpp) # give me a source file, any source file...
+AM_INIT_AUTOMAKE(agg, 2.0.0)
+
+AC_PROG_LN_S
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+
+AC_OUTPUT(
+ Makefile
+ gpc/Makefile
+ src/Makefile
+ src/ctrl/Makefile
+)
diff --git a/plugins/Clist_ng/AGG/src/copying b/plugins/Clist_ng/AGG/src/copying new file mode 100644 index 0000000000..a88fd34d76 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/copying @@ -0,0 +1,21 @@ +Anti-Grain Geometry (AGG) - Version 2.5
+A high quality rendering engine for C++
+Copyright (C) 2002-2006 Maxim Shemanarev
+Contact: mcseem@antigrain.com
+ mcseemagg@yahoo.com
+ http://antigrain.com
+
+AGG 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.
+
+AGG 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 AGG; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301, USA.
diff --git a/plugins/Clist_ng/AGG/src/ctrl/Makefile.am b/plugins/Clist_ng/AGG/src/ctrl/Makefile.am new file mode 100644 index 0000000000..2930b9dd5e --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/Makefile.am @@ -0,0 +1,11 @@ +if ENABLE_CTRL
+INCLUDES = -I$(top_srcdir)/include
+
+noinst_LTLIBRARIES = libaggctrl.la
+
+libaggctrl_la_LDFLAGS = -no-undefined -version-info @AGG_LIB_VERSION@
+libaggctrl_la_SOURCES = agg_cbox_ctrl.cpp agg_gamma_ctrl.cpp agg_gamma_spline.cpp agg_rbox_ctrl.cpp \
+ agg_slider_ctrl.cpp agg_spline_ctrl.cpp agg_scale_ctrl.cpp \
+ agg_bezier_ctrl.cpp agg_polygon_ctrl.cpp
+
+endif
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_bezier_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_bezier_ctrl.cpp new file mode 100644 index 0000000000..ff278bd49a --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_bezier_ctrl.cpp @@ -0,0 +1,375 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <string.h>
+#include <stdio.h>
+#include "ctrl/agg_bezier_ctrl.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ bezier_ctrl_impl::bezier_ctrl_impl() :
+ ctrl(0,0,1,1,false),
+ m_stroke(m_curve),
+ m_poly(4, 5.0),
+ m_idx(0)
+ {
+ m_poly.in_polygon_check(false);
+ m_poly.xn(0) = 100.0;
+ m_poly.yn(0) = 0.0;
+ m_poly.xn(1) = 100.0;
+ m_poly.yn(1) = 50.0;
+ m_poly.xn(2) = 50.0;
+ m_poly.yn(2) = 100.0;
+ m_poly.xn(3) = 0.0;
+ m_poly.yn(3) = 100.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void bezier_ctrl_impl::curve(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ m_poly.xn(0) = x1;
+ m_poly.yn(0) = y1;
+ m_poly.xn(1) = x2;
+ m_poly.yn(1) = y2;
+ m_poly.xn(2) = x3;
+ m_poly.yn(2) = y3;
+ m_poly.xn(3) = x4;
+ m_poly.yn(3) = y4;
+ curve();
+ }
+
+ //------------------------------------------------------------------------
+ curve4& bezier_ctrl_impl::curve()
+ {
+ m_curve.init(m_poly.xn(0), m_poly.yn(0),
+ m_poly.xn(1), m_poly.yn(1),
+ m_poly.xn(2), m_poly.yn(2),
+ m_poly.xn(3), m_poly.yn(3));
+ return m_curve;
+ }
+
+ //------------------------------------------------------------------------
+ void bezier_ctrl_impl::rewind(unsigned idx)
+ {
+ m_idx = idx;
+
+ m_curve.approximation_scale(scale());
+ switch(idx)
+ {
+ default:
+ case 0: // Control line 1
+ m_curve.init(m_poly.xn(0), m_poly.yn(0),
+ (m_poly.xn(0) + m_poly.xn(1)) * 0.5,
+ (m_poly.yn(0) + m_poly.yn(1)) * 0.5,
+ (m_poly.xn(0) + m_poly.xn(1)) * 0.5,
+ (m_poly.yn(0) + m_poly.yn(1)) * 0.5,
+ m_poly.xn(1), m_poly.yn(1));
+ m_stroke.rewind(0);
+ break;
+
+ case 1: // Control line 2
+ m_curve.init(m_poly.xn(2), m_poly.yn(2),
+ (m_poly.xn(2) + m_poly.xn(3)) * 0.5,
+ (m_poly.yn(2) + m_poly.yn(3)) * 0.5,
+ (m_poly.xn(2) + m_poly.xn(3)) * 0.5,
+ (m_poly.yn(2) + m_poly.yn(3)) * 0.5,
+ m_poly.xn(3), m_poly.yn(3));
+ m_stroke.rewind(0);
+ break;
+
+ case 2: // Curve itself
+ m_curve.init(m_poly.xn(0), m_poly.yn(0),
+ m_poly.xn(1), m_poly.yn(1),
+ m_poly.xn(2), m_poly.yn(2),
+ m_poly.xn(3), m_poly.yn(3));
+ m_stroke.rewind(0);
+ break;
+
+ case 3: // Point 1
+ m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20);
+ m_ellipse.rewind(0);
+ break;
+
+ case 4: // Point 2
+ m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20);
+ m_ellipse.rewind(0);
+ break;
+
+ case 5: // Point 3
+ m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20);
+ m_ellipse.rewind(0);
+ break;
+
+ case 6: // Point 4
+ m_ellipse.init(m_poly.xn(3), m_poly.yn(3), point_radius(), point_radius(), 20);
+ m_ellipse.rewind(0);
+ break;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned bezier_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_stop;
+ switch(m_idx)
+ {
+ case 0:
+ case 1:
+ case 2:
+ cmd = m_stroke.vertex(x, y);
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ cmd = m_ellipse.vertex(x, y);
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+ return cmd;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool bezier_ctrl_impl::in_rect(double x, double y) const
+ {
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool bezier_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+ return m_poly.on_mouse_button_down(x, y);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool bezier_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
+ {
+ inverse_transform_xy(&x, &y);
+ return m_poly.on_mouse_move(x, y, button_flag);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool bezier_ctrl_impl::on_mouse_button_up(double x, double y)
+ {
+ return m_poly.on_mouse_button_up(x, y);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool bezier_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+ return m_poly.on_arrow_keys(left, right, down, up);
+ }
+
+
+
+
+
+
+ //------------------------------------------------------------------------
+ curve3_ctrl_impl::curve3_ctrl_impl() :
+ ctrl(0,0,1,1,false),
+ m_stroke(m_curve),
+ m_poly(3, 5.0),
+ m_idx(0)
+ {
+ m_poly.in_polygon_check(false);
+ m_poly.xn(0) = 100.0;
+ m_poly.yn(0) = 0.0;
+ m_poly.xn(1) = 100.0;
+ m_poly.yn(1) = 50.0;
+ m_poly.xn(2) = 50.0;
+ m_poly.yn(2) = 100.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void curve3_ctrl_impl::curve(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ m_poly.xn(0) = x1;
+ m_poly.yn(0) = y1;
+ m_poly.xn(1) = x2;
+ m_poly.yn(1) = y2;
+ m_poly.xn(2) = x3;
+ m_poly.yn(2) = y3;
+ curve();
+ }
+
+ //------------------------------------------------------------------------
+ curve3& curve3_ctrl_impl::curve()
+ {
+ m_curve.init(m_poly.xn(0), m_poly.yn(0),
+ m_poly.xn(1), m_poly.yn(1),
+ m_poly.xn(2), m_poly.yn(2));
+ return m_curve;
+ }
+
+ //------------------------------------------------------------------------
+ void curve3_ctrl_impl::rewind(unsigned idx)
+ {
+ m_idx = idx;
+
+ switch(idx)
+ {
+ default:
+ case 0: // Control line
+ m_curve.init(m_poly.xn(0), m_poly.yn(0),
+ (m_poly.xn(0) + m_poly.xn(1)) * 0.5,
+ (m_poly.yn(0) + m_poly.yn(1)) * 0.5,
+ m_poly.xn(1), m_poly.yn(1));
+ m_stroke.rewind(0);
+ break;
+
+ case 1: // Control line 2
+ m_curve.init(m_poly.xn(1), m_poly.yn(1),
+ (m_poly.xn(1) + m_poly.xn(2)) * 0.5,
+ (m_poly.yn(1) + m_poly.yn(2)) * 0.5,
+ m_poly.xn(2), m_poly.yn(2));
+ m_stroke.rewind(0);
+ break;
+
+ case 2: // Curve itself
+ m_curve.init(m_poly.xn(0), m_poly.yn(0),
+ m_poly.xn(1), m_poly.yn(1),
+ m_poly.xn(2), m_poly.yn(2));
+ m_stroke.rewind(0);
+ break;
+
+ case 3: // Point 1
+ m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20);
+ m_ellipse.rewind(0);
+ break;
+
+ case 4: // Point 2
+ m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20);
+ m_ellipse.rewind(0);
+ break;
+
+ case 5: // Point 3
+ m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20);
+ m_ellipse.rewind(0);
+ break;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned curve3_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_stop;
+ switch(m_idx)
+ {
+ case 0:
+ case 1:
+ case 2:
+ cmd = m_stroke.vertex(x, y);
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ cmd = m_ellipse.vertex(x, y);
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+ return cmd;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool curve3_ctrl_impl::in_rect(double x, double y) const
+ {
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool curve3_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+ return m_poly.on_mouse_button_down(x, y);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool curve3_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
+ {
+ inverse_transform_xy(&x, &y);
+ return m_poly.on_mouse_move(x, y, button_flag);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool curve3_ctrl_impl::on_mouse_button_up(double x, double y)
+ {
+ return m_poly.on_mouse_button_up(x, y);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool curve3_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+ return m_poly.on_arrow_keys(left, right, down, up);
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_cbox_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_cbox_ctrl.cpp new file mode 100644 index 0000000000..3753475ca6 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_cbox_ctrl.cpp @@ -0,0 +1,219 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <string.h>
+#include "ctrl/agg_cbox_ctrl.h"
+
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ cbox_ctrl_impl::cbox_ctrl_impl(double x, double y,
+ const char* l,
+ bool flip_y) :
+ ctrl(x, y, x + 9.0 * 1.5, y + 9.0 * 1.5, flip_y),
+ m_text_thickness(1.5),
+ m_text_height(9.0),
+ m_text_width(0.0),
+ m_status(false),
+ m_text_poly(m_text)
+ {
+ label(l);
+ }
+
+
+ //------------------------------------------------------------------------
+ void cbox_ctrl_impl::text_size(double h, double w)
+ {
+ m_text_width = w;
+ m_text_height = h;
+ }
+
+ //------------------------------------------------------------------------
+ void cbox_ctrl_impl::label(const char* l)
+ {
+ unsigned len = strlen(l);
+ if(len > 127) len = 127;
+ memcpy(m_label, l, len);
+ m_label[len] = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool cbox_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+ if(x >= m_x1 && y >= m_y1 && x <= m_x2 && y <= m_y2)
+ {
+ m_status = !m_status;
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool cbox_ctrl_impl::on_mouse_move(double, double, bool)
+ {
+ return false;
+ }
+
+ //------------------------------------------------------------------------
+ bool cbox_ctrl_impl::in_rect(double x, double y) const
+ {
+ inverse_transform_xy(&x, &y);
+ return x >= m_x1 && y >= m_y1 && x <= m_x2 && y <= m_y2;
+ }
+
+ //------------------------------------------------------------------------
+ bool cbox_ctrl_impl::on_mouse_button_up(double, double)
+ {
+ return false;
+ }
+
+ //------------------------------------------------------------------------
+ bool cbox_ctrl_impl::on_arrow_keys(bool, bool, bool, bool)
+ {
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ void cbox_ctrl_impl::rewind(unsigned idx)
+ {
+ m_idx = idx;
+
+ double d2;
+ double t;
+
+ switch(idx)
+ {
+ default:
+ case 0: // Border
+ m_vertex = 0;
+ m_vx[0] = m_x1;
+ m_vy[0] = m_y1;
+ m_vx[1] = m_x2;
+ m_vy[1] = m_y1;
+ m_vx[2] = m_x2;
+ m_vy[2] = m_y2;
+ m_vx[3] = m_x1;
+ m_vy[3] = m_y2;
+ m_vx[4] = m_x1 + m_text_thickness;
+ m_vy[4] = m_y1 + m_text_thickness;
+ m_vx[5] = m_x1 + m_text_thickness;
+ m_vy[5] = m_y2 - m_text_thickness;
+ m_vx[6] = m_x2 - m_text_thickness;
+ m_vy[6] = m_y2 - m_text_thickness;
+ m_vx[7] = m_x2 - m_text_thickness;
+ m_vy[7] = m_y1 + m_text_thickness;
+ break;
+
+ case 1: // Text
+ m_text.text(m_label);
+ m_text.start_point(m_x1 + m_text_height * 2.0, m_y1 + m_text_height / 5.0);
+ m_text.size(m_text_height, m_text_width);
+ m_text_poly.width(m_text_thickness);
+ m_text_poly.line_join(round_join);
+ m_text_poly.line_cap(round_cap);
+ m_text_poly.rewind(0);
+ break;
+
+ case 2: // Active item
+ m_vertex = 0;
+ d2 = (m_y2 - m_y1) / 2.0;
+ t = m_text_thickness * 1.5;
+ m_vx[0] = m_x1 + m_text_thickness;
+ m_vy[0] = m_y1 + m_text_thickness;
+ m_vx[1] = m_x1 + d2;
+ m_vy[1] = m_y1 + d2 - t;
+ m_vx[2] = m_x2 - m_text_thickness;
+ m_vy[2] = m_y1 + m_text_thickness;
+ m_vx[3] = m_x1 + d2 + t;
+ m_vy[3] = m_y1 + d2;
+ m_vx[4] = m_x2 - m_text_thickness;
+ m_vy[4] = m_y2 - m_text_thickness;
+ m_vx[5] = m_x1 + d2;
+ m_vy[5] = m_y1 + d2 + t;
+ m_vx[6] = m_x1 + m_text_thickness;
+ m_vy[6] = m_y2 - m_text_thickness;
+ m_vx[7] = m_x1 + d2 - t;
+ m_vy[7] = m_y1 + d2;
+ break;
+
+ }
+ }
+
+
+
+
+ //------------------------------------------------------------------------
+ unsigned cbox_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ switch(m_idx)
+ {
+ case 0:
+ if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to;
+ if(m_vertex >= 8) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 1:
+ cmd = m_text_poly.vertex(x, y);
+ break;
+
+ case 2:
+ if(m_status)
+ {
+ if(m_vertex == 0) cmd = path_cmd_move_to;
+ if(m_vertex >= 8) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ }
+ else
+ {
+ cmd = path_cmd_stop;
+ }
+ break;
+
+ default:
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+ return cmd;
+ }
+}
+
+
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_gamma_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_gamma_ctrl.cpp new file mode 100644 index 0000000000..9521bab9fd --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_gamma_ctrl.cpp @@ -0,0 +1,438 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include "agg_math.h"
+#include "ctrl/agg_gamma_ctrl.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ gamma_ctrl_impl::gamma_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y) :
+ ctrl(x1, y1, x2, y2, flip_y),
+ m_border_width(2.0),
+ m_border_extra(0.0),
+ m_curve_width(2.0),
+ m_grid_width(0.2),
+ m_text_thickness(1.5),
+ m_point_size(5.0),
+ m_text_height(9.0),
+ m_text_width(0.0),
+ m_xc1(x1),
+ m_yc1(y1),
+ m_xc2(x2),
+ m_yc2(y2 - m_text_height * 2.0),
+ m_xt1(x1),
+ m_yt1(y2 - m_text_height * 2.0),
+ m_xt2(x2),
+ m_yt2(y2),
+ m_curve_poly(m_gamma_spline),
+ m_text_poly(m_text),
+ m_idx(0),
+ m_vertex(0),
+ m_p1_active(true),
+ m_mouse_point(0),
+ m_pdx(0.0),
+ m_pdy(0.0)
+ {
+ calc_spline_box();
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::calc_spline_box()
+ {
+ m_xs1 = m_xc1 + m_border_width;
+ m_ys1 = m_yc1 + m_border_width;
+ m_xs2 = m_xc2 - m_border_width;
+ m_ys2 = m_yc2 - m_border_width * 0.5;
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::calc_points()
+ {
+ double kx1, ky1, kx2, ky2;
+ m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2);
+ m_xp1 = m_xs1 + (m_xs2 - m_xs1) * kx1 * 0.25;
+ m_yp1 = m_ys1 + (m_ys2 - m_ys1) * ky1 * 0.25;
+ m_xp2 = m_xs2 - (m_xs2 - m_xs1) * kx2 * 0.25;
+ m_yp2 = m_ys2 - (m_ys2 - m_ys1) * ky2 * 0.25;
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::calc_values()
+ {
+ double kx1, ky1, kx2, ky2;
+
+ kx1 = (m_xp1 - m_xs1) * 4.0 / (m_xs2 - m_xs1);
+ ky1 = (m_yp1 - m_ys1) * 4.0 / (m_ys2 - m_ys1);
+ kx2 = (m_xs2 - m_xp2) * 4.0 / (m_xs2 - m_xs1);
+ ky2 = (m_ys2 - m_yp2) * 4.0 / (m_ys2 - m_ys1);
+ m_gamma_spline.values(kx1, ky1, kx2, ky2);
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::text_size(double h, double w)
+ {
+ m_text_width = w;
+ m_text_height = h;
+ m_yc2 = m_y2 - m_text_height * 2.0;
+ m_yt1 = m_y2 - m_text_height * 2.0;
+ calc_spline_box();
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::border_width(double t, double extra)
+ {
+ m_border_width = t;
+ m_border_extra = extra;
+ calc_spline_box();
+ }
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::values(double kx1, double ky1, double kx2, double ky2)
+ {
+ m_gamma_spline.values(kx1, ky1, kx2, ky2);
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::values(double* kx1, double* ky1, double* kx2, double* ky2) const
+ {
+ m_gamma_spline.values(kx1, ky1, kx2, ky2);
+ }
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::rewind(unsigned idx)
+ {
+ double kx1, ky1, kx2, ky2;
+ char tbuf[32];
+
+ m_idx = idx;
+
+ switch(idx)
+ {
+ default:
+
+ case 0: // Background
+ m_vertex = 0;
+ m_vx[0] = m_x1 - m_border_extra;
+ m_vy[0] = m_y1 - m_border_extra;
+ m_vx[1] = m_x2 + m_border_extra;
+ m_vy[1] = m_y1 - m_border_extra;
+ m_vx[2] = m_x2 + m_border_extra;
+ m_vy[2] = m_y2 + m_border_extra;
+ m_vx[3] = m_x1 - m_border_extra;
+ m_vy[3] = m_y2 + m_border_extra;
+ break;
+
+ case 1: // Border
+ m_vertex = 0;
+ m_vx[0] = m_x1;
+ m_vy[0] = m_y1;
+ m_vx[1] = m_x2;
+ m_vy[1] = m_y1;
+ m_vx[2] = m_x2;
+ m_vy[2] = m_y2;
+ m_vx[3] = m_x1;
+ m_vy[3] = m_y2;
+ m_vx[4] = m_x1 + m_border_width;
+ m_vy[4] = m_y1 + m_border_width;
+ m_vx[5] = m_x1 + m_border_width;
+ m_vy[5] = m_y2 - m_border_width;
+ m_vx[6] = m_x2 - m_border_width;
+ m_vy[6] = m_y2 - m_border_width;
+ m_vx[7] = m_x2 - m_border_width;
+ m_vy[7] = m_y1 + m_border_width;
+ m_vx[8] = m_xc1 + m_border_width;
+ m_vy[8] = m_yc2 - m_border_width * 0.5;
+ m_vx[9] = m_xc2 - m_border_width;
+ m_vy[9] = m_yc2 - m_border_width * 0.5;
+ m_vx[10] = m_xc2 - m_border_width;
+ m_vy[10] = m_yc2 + m_border_width * 0.5;
+ m_vx[11] = m_xc1 + m_border_width;
+ m_vy[11] = m_yc2 + m_border_width * 0.5;
+ break;
+
+ case 2: // Curve
+ m_gamma_spline.box(m_xs1, m_ys1, m_xs2, m_ys2);
+ m_curve_poly.width(m_curve_width);
+ m_curve_poly.rewind(0);
+ break;
+
+ case 3: // Grid
+ m_vertex = 0;
+ m_vx[0] = m_xs1;
+ m_vy[0] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5;
+ m_vx[1] = m_xs2;
+ m_vy[1] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5;
+ m_vx[2] = m_xs2;
+ m_vy[2] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5;
+ m_vx[3] = m_xs1;
+ m_vy[3] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5;
+ m_vx[4] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5;
+ m_vy[4] = m_ys1;
+ m_vx[5] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5;
+ m_vy[5] = m_ys2;
+ m_vx[6] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5;
+ m_vy[6] = m_ys2;
+ m_vx[7] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5;
+ m_vy[7] = m_ys1;
+ calc_points();
+ m_vx[8] = m_xs1;
+ m_vy[8] = m_yp1 - m_grid_width * 0.5;
+ m_vx[9] = m_xp1 - m_grid_width * 0.5;
+ m_vy[9] = m_yp1 - m_grid_width * 0.5;
+ m_vx[10] = m_xp1 - m_grid_width * 0.5;
+ m_vy[10] = m_ys1;
+ m_vx[11] = m_xp1 + m_grid_width * 0.5;
+ m_vy[11] = m_ys1;
+ m_vx[12] = m_xp1 + m_grid_width * 0.5;
+ m_vy[12] = m_yp1 + m_grid_width * 0.5;
+ m_vx[13] = m_xs1;
+ m_vy[13] = m_yp1 + m_grid_width * 0.5;
+ m_vx[14] = m_xs2;
+ m_vy[14] = m_yp2 + m_grid_width * 0.5;
+ m_vx[15] = m_xp2 + m_grid_width * 0.5;
+ m_vy[15] = m_yp2 + m_grid_width * 0.5;
+ m_vx[16] = m_xp2 + m_grid_width * 0.5;
+ m_vy[16] = m_ys2;
+ m_vx[17] = m_xp2 - m_grid_width * 0.5;
+ m_vy[17] = m_ys2;
+ m_vx[18] = m_xp2 - m_grid_width * 0.5;
+ m_vy[18] = m_yp2 - m_grid_width * 0.5;
+ m_vx[19] = m_xs2;
+ m_vy[19] = m_yp2 - m_grid_width * 0.5;
+ break;
+
+ case 4: // Point1
+ calc_points();
+ if(m_p1_active) m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32);
+ else m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32);
+ break;
+
+ case 5: // Point2
+ calc_points();
+ if(m_p1_active) m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32);
+ else m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32);
+ break;
+
+ case 6: // Text
+ m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2);
+ sprintf(tbuf, "%5.3f %5.3f %5.3f %5.3f", kx1, ky1, kx2, ky2);
+ m_text.text(tbuf);
+ m_text.size(m_text_height, m_text_width);
+ m_text.start_point(m_xt1 + m_border_width * 2.0, (m_yt1 + m_yt2) * 0.5 - m_text_height * 0.5);
+ m_text_poly.width(m_text_thickness);
+ m_text_poly.line_join(round_join);
+ m_text_poly.line_cap(round_cap);
+ m_text_poly.rewind(0);
+ break;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned gamma_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ switch(m_idx)
+ {
+ case 0:
+ if(m_vertex == 0) cmd = path_cmd_move_to;
+ if(m_vertex >= 4) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 1:
+ if(m_vertex == 0 || m_vertex == 4 || m_vertex == 8) cmd = path_cmd_move_to;
+ if(m_vertex >= 12) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 2:
+ cmd = m_curve_poly.vertex(x, y);
+ break;
+
+ case 3:
+ if(m_vertex == 0 ||
+ m_vertex == 4 ||
+ m_vertex == 8 ||
+ m_vertex == 14) cmd = path_cmd_move_to;
+
+ if(m_vertex >= 20) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 4: // Point1
+ case 5: // Point2
+ cmd = m_ellipse.vertex(x, y);
+ break;
+
+ case 6:
+ cmd = m_text_poly.vertex(x, y);
+ break;
+
+ default:
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+
+ return cmd;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool gamma_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+ double kx1, ky1, kx2, ky2;
+ bool ret = false;
+ m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2);
+ if(m_p1_active)
+ {
+ if(left) { kx1 -= 0.005; ret = true; }
+ if(right) { kx1 += 0.005; ret = true; }
+ if(down) { ky1 -= 0.005; ret = true; }
+ if(up) { ky1 += 0.005; ret = true; }
+ }
+ else
+ {
+ if(left) { kx2 += 0.005; ret = true; }
+ if(right) { kx2 -= 0.005; ret = true; }
+ if(down) { ky2 += 0.005; ret = true; }
+ if(up) { ky2 -= 0.005; ret = true; }
+ }
+ if(ret)
+ {
+ m_gamma_spline.values(kx1, ky1, kx2, ky2);
+ }
+ return ret;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void gamma_ctrl_impl::change_active_point()
+ {
+ m_p1_active = m_p1_active ? false : true;
+ }
+
+
+
+
+ //------------------------------------------------------------------------
+ bool gamma_ctrl_impl::in_rect(double x, double y) const
+ {
+ inverse_transform_xy(&x, &y);
+ return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool gamma_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+ calc_points();
+
+ if(calc_distance(x, y, m_xp1, m_yp1) <= m_point_size + 1)
+ {
+ m_mouse_point = 1;
+ m_pdx = m_xp1 - x;
+ m_pdy = m_yp1 - y;
+ m_p1_active = true;
+ return true;
+ }
+
+ if(calc_distance(x, y, m_xp2, m_yp2) <= m_point_size + 1)
+ {
+ m_mouse_point = 2;
+ m_pdx = m_xp2 - x;
+ m_pdy = m_yp2 - y;
+ m_p1_active = false;
+ return true;
+ }
+
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool gamma_ctrl_impl::on_mouse_button_up(double, double)
+ {
+ if(m_mouse_point)
+ {
+ m_mouse_point = 0;
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool gamma_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
+ {
+ inverse_transform_xy(&x, &y);
+ if(!button_flag)
+ {
+ return on_mouse_button_up(x, y);
+ }
+
+ if(m_mouse_point == 1)
+ {
+ m_xp1 = x + m_pdx;
+ m_yp1 = y + m_pdy;
+ calc_values();
+ return true;
+ }
+ if(m_mouse_point == 2)
+ {
+ m_xp2 = x + m_pdx;
+ m_yp2 = y + m_pdy;
+ calc_values();
+ return true;
+ }
+ return false;
+ }
+
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_gamma_spline.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_gamma_spline.cpp new file mode 100644 index 0000000000..10de9c397e --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_gamma_spline.cpp @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "ctrl/agg_gamma_spline.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ gamma_spline::gamma_spline() :
+ m_x1(0), m_y1(0), m_x2(10), m_y2(10), m_cur_x(0.0)
+ {
+ values(1.0, 1.0, 1.0, 1.0);
+ }
+
+
+ //------------------------------------------------------------------------
+ double gamma_spline::y(double x) const
+ {
+ if(x < 0.0) x = 0.0;
+ if(x > 1.0) x = 1.0;
+ double val = m_spline.get(x);
+ if(val < 0.0) val = 0.0;
+ if(val > 1.0) val = 1.0;
+ return val;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void gamma_spline::values(double kx1, double ky1, double kx2, double ky2)
+ {
+ if(kx1 < 0.001) kx1 = 0.001;
+ if(kx1 > 1.999) kx1 = 1.999;
+ if(ky1 < 0.001) ky1 = 0.001;
+ if(ky1 > 1.999) ky1 = 1.999;
+ if(kx2 < 0.001) kx2 = 0.001;
+ if(kx2 > 1.999) kx2 = 1.999;
+ if(ky2 < 0.001) ky2 = 0.001;
+ if(ky2 > 1.999) ky2 = 1.999;
+
+ m_x[0] = 0.0;
+ m_y[0] = 0.0;
+ m_x[1] = kx1 * 0.25;
+ m_y[1] = ky1 * 0.25;
+ m_x[2] = 1.0 - kx2 * 0.25;
+ m_y[2] = 1.0 - ky2 * 0.25;
+ m_x[3] = 1.0;
+ m_y[3] = 1.0;
+
+ m_spline.init(4, m_x, m_y);
+
+ int i;
+ for(i = 0; i < 256; i++)
+ {
+ m_gamma[i] = (unsigned char)(y(double(i) / 255.0) * 255.0);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_spline::values(double* kx1, double* ky1, double* kx2, double* ky2) const
+ {
+ *kx1 = m_x[1] * 4.0;
+ *ky1 = m_y[1] * 4.0;
+ *kx2 = (1.0 - m_x[2]) * 4.0;
+ *ky2 = (1.0 - m_y[2]) * 4.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_spline::box(double x1, double y1, double x2, double y2)
+ {
+ m_x1 = x1;
+ m_y1 = y1;
+ m_x2 = x2;
+ m_y2 = y2;
+ }
+
+
+ //------------------------------------------------------------------------
+ void gamma_spline::rewind(unsigned)
+ {
+ m_cur_x = 0.0;
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned gamma_spline::vertex(double* vx, double* vy)
+ {
+ if(m_cur_x == 0.0)
+ {
+ *vx = m_x1;
+ *vy = m_y1;
+ m_cur_x += 1.0 / (m_x2 - m_x1);
+ return path_cmd_move_to;
+ }
+
+ if(m_cur_x > 1.0)
+ {
+ return path_cmd_stop;
+ }
+
+ *vx = m_x1 + m_cur_x * (m_x2 - m_x1);
+ *vy = m_y1 + y(m_cur_x) * (m_y2 - m_y1);
+
+ m_cur_x += 1.0 / (m_x2 - m_x1);
+ return path_cmd_line_to;
+ }
+
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_polygon_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_polygon_ctrl.cpp new file mode 100644 index 0000000000..4dde1b7f89 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_polygon_ctrl.cpp @@ -0,0 +1,337 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "ctrl/agg_polygon_ctrl.h"
+
+namespace agg
+{
+
+ polygon_ctrl_impl::polygon_ctrl_impl(unsigned np, double point_radius) :
+ ctrl(0, 0, 1, 1, false),
+ m_polygon(np * 2),
+ m_num_points(np),
+ m_node(-1),
+ m_edge(-1),
+ m_vs(&m_polygon[0], m_num_points, false),
+ m_stroke(m_vs),
+ m_point_radius(point_radius),
+ m_status(0),
+ m_dx(0.0),
+ m_dy(0.0),
+ m_in_polygon_check(true)
+ {
+ m_stroke.width(1.0);
+ }
+
+
+ void polygon_ctrl_impl::rewind(unsigned)
+ {
+ m_status = 0;
+ m_stroke.rewind(0);
+ }
+
+ unsigned polygon_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_stop;
+ double r = m_point_radius;
+ if(m_status == 0)
+ {
+ cmd = m_stroke.vertex(x, y);
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ return cmd;
+ }
+ if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
+ m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
+ ++m_status;
+ }
+ cmd = m_ellipse.vertex(x, y);
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ return cmd;
+ }
+ if(m_status >= m_num_points) return path_cmd_stop;
+ if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
+ m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
+ ++m_status;
+ cmd = m_ellipse.vertex(x, y);
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+ return cmd;
+ }
+
+
+ bool polygon_ctrl_impl::check_edge(unsigned i, double x, double y) const
+ {
+ bool ret = false;
+
+ unsigned n1 = i;
+ unsigned n2 = (i + m_num_points - 1) % m_num_points;
+ double x1 = xn(n1);
+ double y1 = yn(n1);
+ double x2 = xn(n2);
+ double y2 = yn(n2);
+
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+
+ if(sqrt(dx*dx + dy*dy) > 0.0000001)
+ {
+ double x3 = x;
+ double y3 = y;
+ double x4 = x3 - dy;
+ double y4 = y3 + dx;
+
+ double den = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1);
+ double u1 = ((x4-x3) * (y1-y3) - (y4-y3) * (x1-x3)) / den;
+
+ double xi = x1 + u1 * (x2 - x1);
+ double yi = y1 + u1 * (y2 - y1);
+
+ dx = xi - x;
+ dy = yi - y;
+
+ if (u1 > 0.0 && u1 < 1.0 && sqrt(dx*dx + dy*dy) <= m_point_radius)
+ {
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
+
+
+ bool polygon_ctrl_impl::in_rect(double x, double y) const
+ {
+ return false;
+ }
+
+
+ bool polygon_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ unsigned i;
+ bool ret = false;
+ m_node = -1;
+ m_edge = -1;
+ inverse_transform_xy(&x, &y);
+ for (i = 0; i < m_num_points; i++)
+ {
+ if(sqrt( (x-xn(i)) * (x-xn(i)) + (y-yn(i)) * (y-yn(i)) ) < m_point_radius)
+ {
+ m_dx = x - xn(i);
+ m_dy = y - yn(i);
+ m_node = int(i);
+ ret = true;
+ break;
+ }
+ }
+
+ if(!ret)
+ {
+ for (i = 0; i < m_num_points; i++)
+ {
+ if(check_edge(i, x, y))
+ {
+ m_dx = x;
+ m_dy = y;
+ m_edge = int(i);
+ ret = true;
+ break;
+ }
+ }
+ }
+
+ if(!ret)
+ {
+ if(point_in_polygon(x, y))
+ {
+ m_dx = x;
+ m_dy = y;
+ m_node = int(m_num_points);
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
+
+ bool polygon_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
+ {
+ bool ret = false;
+ double dx;
+ double dy;
+ inverse_transform_xy(&x, &y);
+ if(m_node == int(m_num_points))
+ {
+ dx = x - m_dx;
+ dy = y - m_dy;
+ unsigned i;
+ for(i = 0; i < m_num_points; i++)
+ {
+ xn(i) += dx;
+ yn(i) += dy;
+ }
+ m_dx = x;
+ m_dy = y;
+ ret = true;
+ }
+ else
+ {
+ if(m_edge >= 0)
+ {
+ unsigned n1 = m_edge;
+ unsigned n2 = (n1 + m_num_points - 1) % m_num_points;
+ dx = x - m_dx;
+ dy = y - m_dy;
+ xn(n1) += dx;
+ yn(n1) += dy;
+ xn(n2) += dx;
+ yn(n2) += dy;
+ m_dx = x;
+ m_dy = y;
+ ret = true;
+ }
+ else
+ {
+ if(m_node >= 0)
+ {
+ xn(m_node) = x - m_dx;
+ yn(m_node) = y - m_dy;
+ ret = true;
+ }
+ }
+ }
+ return ret;
+ }
+
+ bool polygon_ctrl_impl::on_mouse_button_up(double x, double y)
+ {
+ bool ret = (m_node >= 0) || (m_edge >= 0);
+ m_node = -1;
+ m_edge = -1;
+ return ret;
+ }
+
+
+ bool polygon_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+ return false;
+ }
+
+
+ //======= Crossings Multiply algorithm of InsideTest ========================
+ //
+ // By Eric Haines, 3D/Eye Inc, erich@eye.com
+ //
+ // This version is usually somewhat faster than the original published in
+ // Graphics Gems IV; by turning the division for testing the X axis crossing
+ // into a tricky multiplication test this part of the test became faster,
+ // which had the additional effect of making the test for "both to left or
+ // both to right" a bit slower for triangles than simply computing the
+ // intersection each time. The main increase is in triangle testing speed,
+ // which was about 15% faster; all other polygon complexities were pretty much
+ // the same as before. On machines where division is very expensive (not the
+ // case on the HP 9000 series on which I tested) this test should be much
+ // faster overall than the old code. Your mileage may (in fact, will) vary,
+ // depending on the machine and the test data, but in general I believe this
+ // code is both shorter and faster. This test was inspired by unpublished
+ // Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
+ // Related work by Samosky is in:
+ //
+ // Samosky, Joseph, "SectionView: A system for interactively specifying and
+ // visualizing sections through three-dimensional medical image data",
+ // M.S. Thesis, Department of Electrical Engineering and Computer Science,
+ // Massachusetts Institute of Technology, 1993.
+ //
+ // Shoot a test ray along +X axis. The strategy is to compare vertex Y values
+ // to the testing point's Y and quickly discard edges which are entirely to one
+ // side of the test ray. Note that CONVEX and WINDING code can be added as
+ // for the CrossingsTest() code; it is left out here for clarity.
+ //
+ // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
+ // _point_, returns 1 if inside, 0 if outside.
+ bool polygon_ctrl_impl::point_in_polygon(double tx, double ty) const
+ {
+ if(m_num_points < 3) return false;
+ if(!m_in_polygon_check) return false;
+
+ unsigned j;
+ int yflag0, yflag1, inside_flag;
+ double vtx0, vty0, vtx1, vty1;
+
+ vtx0 = xn(m_num_points - 1);
+ vty0 = yn(m_num_points - 1);
+
+ // get test bit for above/below X axis
+ yflag0 = (vty0 >= ty);
+
+ vtx1 = xn(0);
+ vty1 = yn(0);
+
+ inside_flag = 0;
+ for (j = 1; j <= m_num_points; ++j)
+ {
+ yflag1 = (vty1 >= ty);
+ // Check if endpoints straddle (are on opposite sides) of X axis
+ // (i.e. the Y's differ); if so, +X ray could intersect this edge.
+ // The old test also checked whether the endpoints are both to the
+ // right or to the left of the test point. However, given the faster
+ // intersection point computation used below, this test was found to
+ // be a break-even proposition for most polygons and a loser for
+ // triangles (where 50% or more of the edges which survive this test
+ // will cross quadrants and so have to have the X intersection computed
+ // anyway). I credit Joseph Samosky with inspiring me to try dropping
+ // the "both left or both right" part of my code.
+ if (yflag0 != yflag1)
+ {
+ // Check intersection of pgon segment with +X ray.
+ // Note if >= point's X; if so, the ray hits it.
+ // The division operation is avoided for the ">=" test by checking
+ // the sign of the first vertex wrto the test point; idea inspired
+ // by Joseph Samosky's and Mark Haigh-Hutchinson's different
+ // polygon inclusion tests.
+ if ( ((vty1-ty) * (vtx0-vtx1) >=
+ (vtx1-tx) * (vty0-vty1)) == yflag1 )
+ {
+ inside_flag ^= 1;
+ }
+ }
+
+ // Move to the next pair of vertices, retaining info as possible.
+ yflag0 = yflag1;
+ vtx0 = vtx1;
+ vty0 = vty1;
+
+ unsigned k = (j >= m_num_points) ? j - m_num_points : j;
+ vtx1 = xn(k);
+ vty1 = yn(k);
+ }
+ return inside_flag != 0;
+ }
+}
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_rbox_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_rbox_ctrl.cpp new file mode 100644 index 0000000000..c643fec387 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_rbox_ctrl.cpp @@ -0,0 +1,330 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <string.h>
+#include "ctrl/agg_rbox_ctrl.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ rbox_ctrl_impl::rbox_ctrl_impl(double x1, double y1,
+ double x2, double y2, bool flip_y) :
+ ctrl(x1, y1, x2, y2, flip_y),
+ m_border_width(1.0),
+ m_border_extra(0.0),
+ m_text_thickness(1.5),
+ m_text_height(9.0),
+ m_text_width(0.0),
+ m_num_items(0),
+ m_cur_item(-1),
+ m_ellipse_poly(m_ellipse),
+ m_text_poly(m_text),
+ m_idx(0),
+ m_vertex(0)
+ {
+ calc_rbox();
+ }
+
+
+ //------------------------------------------------------------------------
+ void rbox_ctrl_impl::calc_rbox()
+ {
+ m_xs1 = m_x1 + m_border_width;
+ m_ys1 = m_y1 + m_border_width;
+ m_xs2 = m_x2 - m_border_width;
+ m_ys2 = m_y2 - m_border_width;
+ }
+
+
+ //------------------------------------------------------------------------
+ void rbox_ctrl_impl::add_item(const char* text)
+ {
+ if(m_num_items < 32)
+ {
+ m_items[m_num_items].resize(strlen(text) + 1);
+ strcpy(&m_items[m_num_items][0], text);
+ m_num_items++;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void rbox_ctrl_impl::border_width(double t, double extra)
+ {
+ m_border_width = t;
+ m_border_extra = extra;
+ calc_rbox();
+ }
+
+
+ //------------------------------------------------------------------------
+ void rbox_ctrl_impl::text_size(double h, double w)
+ {
+ m_text_width = w;
+ m_text_height = h;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void rbox_ctrl_impl::rewind(unsigned idx)
+ {
+ m_idx = idx;
+ m_dy = m_text_height * 2.0;
+ m_draw_item = 0;
+
+ switch(idx)
+ {
+ default:
+
+ case 0: // Background
+ m_vertex = 0;
+ m_vx[0] = m_x1 - m_border_extra;
+ m_vy[0] = m_y1 - m_border_extra;
+ m_vx[1] = m_x2 + m_border_extra;
+ m_vy[1] = m_y1 - m_border_extra;
+ m_vx[2] = m_x2 + m_border_extra;
+ m_vy[2] = m_y2 + m_border_extra;
+ m_vx[3] = m_x1 - m_border_extra;
+ m_vy[3] = m_y2 + m_border_extra;
+ break;
+
+ case 1: // Border
+ m_vertex = 0;
+ m_vx[0] = m_x1;
+ m_vy[0] = m_y1;
+ m_vx[1] = m_x2;
+ m_vy[1] = m_y1;
+ m_vx[2] = m_x2;
+ m_vy[2] = m_y2;
+ m_vx[3] = m_x1;
+ m_vy[3] = m_y2;
+ m_vx[4] = m_x1 + m_border_width;
+ m_vy[4] = m_y1 + m_border_width;
+ m_vx[5] = m_x1 + m_border_width;
+ m_vy[5] = m_y2 - m_border_width;
+ m_vx[6] = m_x2 - m_border_width;
+ m_vy[6] = m_y2 - m_border_width;
+ m_vx[7] = m_x2 - m_border_width;
+ m_vy[7] = m_y1 + m_border_width;
+ break;
+
+ case 2: // Text
+ m_text.text(&m_items[0][0]);
+ m_text.start_point(m_xs1 + m_dy * 1.5, m_ys1 + m_dy / 2.0);
+ m_text.size(m_text_height, m_text_width);
+ m_text_poly.width(m_text_thickness);
+ m_text_poly.line_join(round_join);
+ m_text_poly.line_cap(round_cap);
+ m_text_poly.rewind(0);
+ break;
+
+ case 3: // Inactive items
+ m_ellipse.init(m_xs1 + m_dy / 1.3,
+ m_ys1 + m_dy / 1.3,
+ m_text_height / 1.5,
+ m_text_height / 1.5, 32);
+ m_ellipse_poly.width(m_text_thickness);
+ m_ellipse_poly.rewind(0);
+ break;
+
+
+ case 4: // Active Item
+ if(m_cur_item >= 0)
+ {
+ m_ellipse.init(m_xs1 + m_dy / 1.3,
+ m_ys1 + m_dy * m_cur_item + m_dy / 1.3,
+ m_text_height / 2.0,
+ m_text_height / 2.0, 32);
+ m_ellipse.rewind(0);
+ }
+ break;
+
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned rbox_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ switch(m_idx)
+ {
+ case 0:
+ if(m_vertex == 0) cmd = path_cmd_move_to;
+ if(m_vertex >= 4) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 1:
+ if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to;
+ if(m_vertex >= 8) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 2:
+ cmd = m_text_poly.vertex(x, y);
+ if(is_stop(cmd))
+ {
+ m_draw_item++;
+ if(m_draw_item >= m_num_items)
+ {
+ break;
+ }
+ else
+ {
+ m_text.text(&m_items[m_draw_item][0]);
+ m_text.start_point(m_xs1 + m_dy * 1.5,
+ m_ys1 + m_dy * (m_draw_item + 1) - m_dy / 2.0);
+
+ m_text_poly.rewind(0);
+ cmd = m_text_poly.vertex(x, y);
+ }
+ }
+ break;
+
+ case 3:
+ cmd = m_ellipse_poly.vertex(x, y);
+ if(is_stop(cmd))
+ {
+ m_draw_item++;
+ if(m_draw_item >= m_num_items)
+ {
+ break;
+ }
+ else
+ {
+ m_ellipse.init(m_xs1 + m_dy / 1.3,
+ m_ys1 + m_dy * m_draw_item + m_dy / 1.3,
+ m_text_height / 1.5,
+ m_text_height / 1.5, 32);
+ m_ellipse_poly.rewind(0);
+ cmd = m_ellipse_poly.vertex(x, y);
+ }
+ }
+ break;
+
+
+ case 4:
+ if(m_cur_item >= 0)
+ {
+ cmd = m_ellipse.vertex(x, y);
+ }
+ else
+ {
+ cmd = path_cmd_stop;
+ }
+ break;
+
+ default:
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+
+ return cmd;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool rbox_ctrl_impl::in_rect(double x, double y) const
+ {
+ inverse_transform_xy(&x, &y);
+ return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool rbox_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+ unsigned i;
+ for(i = 0; i < m_num_items; i++)
+ {
+ double xp = m_xs1 + m_dy / 1.3;
+ double yp = m_ys1 + m_dy * i + m_dy / 1.3;
+ if(calc_distance(x, y, xp, yp) <= m_text_height / 1.5)
+ {
+ m_cur_item = int(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool rbox_ctrl_impl::on_mouse_move(double, double, bool)
+ {
+ return false;
+ }
+
+ //------------------------------------------------------------------------
+ bool rbox_ctrl_impl::on_mouse_button_up(double, double)
+ {
+ return false;
+ }
+
+ //------------------------------------------------------------------------
+ bool rbox_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+ if(m_cur_item >= 0)
+ {
+ if(up || right)
+ {
+ m_cur_item++;
+ if(m_cur_item >= int(m_num_items))
+ {
+ m_cur_item = 0;
+ }
+ return true;
+ }
+
+ if(down || left)
+ {
+ m_cur_item--;
+ if(m_cur_item < 0)
+ {
+ m_cur_item = m_num_items - 1;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+}
+
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_scale_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_scale_ctrl.cpp new file mode 100644 index 0000000000..974a4fc727 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_scale_ctrl.cpp @@ -0,0 +1,459 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "ctrl/agg_scale_ctrl.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ scale_ctrl_impl::scale_ctrl_impl(double x1, double y1,
+ double x2, double y2, bool flip_y) :
+ ctrl(x1, y1, x2, y2, flip_y),
+ m_border_thickness(1.0),
+ m_border_extra((fabs(x2 - x1) > fabs(y2 - y1)) ? (y2 - y1) / 2 : (x2 - x1) / 2),
+ m_pdx(0.0),
+ m_pdy(0.0),
+ m_move_what(move_nothing),
+ m_value1(0.3),
+ m_value2(0.7),
+ m_min_d(0.01)
+ {
+ calc_box();
+ }
+
+
+ //------------------------------------------------------------------------
+ void scale_ctrl_impl::calc_box()
+ {
+ m_xs1 = m_x1 + m_border_thickness;
+ m_ys1 = m_y1 + m_border_thickness;
+ m_xs2 = m_x2 - m_border_thickness;
+ m_ys2 = m_y2 - m_border_thickness;
+ }
+
+
+ //------------------------------------------------------------------------
+ void scale_ctrl_impl::border_thickness(double t, double extra)
+ {
+ m_border_thickness = t;
+ m_border_extra = extra;
+ calc_box();
+ }
+
+
+ //------------------------------------------------------------------------
+ void scale_ctrl_impl::resize(double x1, double y1, double x2, double y2)
+ {
+ m_x1 = x1;
+ m_y1 = y1;
+ m_x2 = x2;
+ m_y2 = y2;
+ calc_box();
+ m_border_extra = (fabs(x2 - x1) > fabs(y2 - y1)) ?
+ (y2 - y1) / 2 :
+ (x2 - x1) / 2;
+ }
+
+
+ //------------------------------------------------------------------------
+ void scale_ctrl_impl::value1(double value)
+ {
+ if(value < 0.0) value = 0.0;
+ if(value > 1.0) value = 1.0;
+ if(m_value2 - value < m_min_d) value = m_value2 - m_min_d;
+ m_value1 = value;
+ }
+
+
+ //------------------------------------------------------------------------
+ void scale_ctrl_impl::value2(double value)
+ {
+ if(value < 0.0) value = 0.0;
+ if(value > 1.0) value = 1.0;
+ if(m_value1 + value < m_min_d) value = m_value1 + m_min_d;
+ m_value2 = value;
+ }
+
+
+ //------------------------------------------------------------------------
+ void scale_ctrl_impl::move(double d)
+ {
+ m_value1 += d;
+ m_value2 += d;
+ if(m_value1 < 0.0)
+ {
+ m_value2 -= m_value1;
+ m_value1 = 0.0;
+ }
+ if(m_value2 > 1.0)
+ {
+ m_value1 -= m_value2 - 1.0;
+ m_value2 = 1.0;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void scale_ctrl_impl::rewind(unsigned idx)
+ {
+ m_idx = idx;
+
+ switch(idx)
+ {
+ default:
+
+ case 0: // Background
+ m_vertex = 0;
+ m_vx[0] = m_x1 - m_border_extra;
+ m_vy[0] = m_y1 - m_border_extra;
+ m_vx[1] = m_x2 + m_border_extra;
+ m_vy[1] = m_y1 - m_border_extra;
+ m_vx[2] = m_x2 + m_border_extra;
+ m_vy[2] = m_y2 + m_border_extra;
+ m_vx[3] = m_x1 - m_border_extra;
+ m_vy[3] = m_y2 + m_border_extra;
+ break;
+
+ case 1: // Border
+ m_vertex = 0;
+ m_vx[0] = m_x1;
+ m_vy[0] = m_y1;
+ m_vx[1] = m_x2;
+ m_vy[1] = m_y1;
+ m_vx[2] = m_x2;
+ m_vy[2] = m_y2;
+ m_vx[3] = m_x1;
+ m_vy[3] = m_y2;
+ m_vx[4] = m_x1 + m_border_thickness;
+ m_vy[4] = m_y1 + m_border_thickness;
+ m_vx[5] = m_x1 + m_border_thickness;
+ m_vy[5] = m_y2 - m_border_thickness;
+ m_vx[6] = m_x2 - m_border_thickness;
+ m_vy[6] = m_y2 - m_border_thickness;
+ m_vx[7] = m_x2 - m_border_thickness;
+ m_vy[7] = m_y1 + m_border_thickness;
+ break;
+
+ case 2: // pointer1
+ if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
+ {
+ m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value1,
+ (m_ys1 + m_ys2) / 2.0,
+ m_y2 - m_y1,
+ m_y2 - m_y1,
+ 32);
+ }
+ else
+ {
+ m_ellipse.init((m_xs1 + m_xs2) / 2.0,
+ m_ys1 + (m_ys2 - m_ys1) * m_value1,
+ m_x2 - m_x1,
+ m_x2 - m_x1,
+ 32);
+ }
+ m_ellipse.rewind(0);
+ break;
+
+ case 3: // pointer2
+ if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
+ {
+ m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value2,
+ (m_ys1 + m_ys2) / 2.0,
+ m_y2 - m_y1,
+ m_y2 - m_y1,
+ 32);
+ }
+ else
+ {
+ m_ellipse.init((m_xs1 + m_xs2) / 2.0,
+ m_ys1 + (m_ys2 - m_ys1) * m_value2,
+ m_x2 - m_x1,
+ m_x2 - m_x1,
+ 32);
+ }
+ m_ellipse.rewind(0);
+ break;
+
+ case 4: // slider
+ m_vertex = 0;
+ if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
+ {
+ m_vx[0] = m_xs1 + (m_xs2 - m_xs1) * m_value1;
+ m_vy[0] = m_y1 - m_border_extra / 2.0;
+ m_vx[1] = m_xs1 + (m_xs2 - m_xs1) * m_value2;
+ m_vy[1] = m_vy[0];
+ m_vx[2] = m_vx[1];
+ m_vy[2] = m_y2 + m_border_extra / 2.0;
+ m_vx[3] = m_vx[0];
+ m_vy[3] = m_vy[2];
+ }
+ else
+ {
+ m_vx[0] = m_x1 - m_border_extra / 2.0;
+ m_vy[0] = m_ys1 + (m_ys2 - m_ys1) * m_value1;
+ m_vx[1] = m_vx[0];
+ m_vy[1] = m_ys1 + (m_ys2 - m_ys1) * m_value2;
+ m_vx[2] = m_x2 + m_border_extra / 2.0;
+ m_vy[2] = m_vy[1];
+ m_vx[3] = m_vx[2];
+ m_vy[3] = m_vy[0];
+ }
+ break;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned scale_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ switch(m_idx)
+ {
+ case 0:
+ case 4:
+ if(m_vertex == 0) cmd = path_cmd_move_to;
+ if(m_vertex >= 4) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 1:
+ if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to;
+ if(m_vertex >= 8) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 2:
+ case 3:
+ cmd = m_ellipse.vertex(x, y);
+ break;
+
+ default:
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+
+ return cmd;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool scale_ctrl_impl::in_rect(double x, double y) const
+ {
+ inverse_transform_xy(&x, &y);
+ return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool scale_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+
+ double xp1;
+ double xp2;
+ double ys1;
+ double ys2;
+ double xp;
+ double yp;
+
+ if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
+ {
+ xp1 = m_xs1 + (m_xs2 - m_xs1) * m_value1;
+ xp2 = m_xs1 + (m_xs2 - m_xs1) * m_value2;
+ ys1 = m_y1 - m_border_extra / 2.0;
+ ys2 = m_y2 + m_border_extra / 2.0;
+ yp = (m_ys1 + m_ys2) / 2.0;
+
+ if(x > xp1 && y > ys1 && x < xp2 && y < ys2)
+ {
+ m_pdx = xp1 - x;
+ m_move_what = move_slider;
+ return true;
+ }
+
+ //if(x < xp1 && calc_distance(x, y, xp1, yp) <= m_y2 - m_y1)
+ if(calc_distance(x, y, xp1, yp) <= m_y2 - m_y1)
+ {
+ m_pdx = xp1 - x;
+ m_move_what = move_value1;
+ return true;
+ }
+
+ //if(x > xp2 && calc_distance(x, y, xp2, yp) <= m_y2 - m_y1)
+ if(calc_distance(x, y, xp2, yp) <= m_y2 - m_y1)
+ {
+ m_pdx = xp2 - x;
+ m_move_what = move_value2;
+ return true;
+ }
+ }
+ else
+ {
+ xp1 = m_x1 - m_border_extra / 2.0;
+ xp2 = m_x2 + m_border_extra / 2.0;
+ ys1 = m_ys1 + (m_ys2 - m_ys1) * m_value1;
+ ys2 = m_ys1 + (m_ys2 - m_ys1) * m_value2;
+ xp = (m_xs1 + m_xs2) / 2.0;
+
+ if(x > xp1 && y > ys1 && x < xp2 && y < ys2)
+ {
+ m_pdy = ys1 - y;
+ m_move_what = move_slider;
+ return true;
+ }
+
+ //if(y < ys1 && calc_distance(x, y, xp, ys1) <= m_x2 - m_x1)
+ if(calc_distance(x, y, xp, ys1) <= m_x2 - m_x1)
+ {
+ m_pdy = ys1 - y;
+ m_move_what = move_value1;
+ return true;
+ }
+
+ //if(y > ys2 && calc_distance(x, y, xp, ys2) <= m_x2 - m_x1)
+ if(calc_distance(x, y, xp, ys2) <= m_x2 - m_x1)
+ {
+ m_pdy = ys2 - y;
+ m_move_what = move_value2;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool scale_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
+ {
+ inverse_transform_xy(&x, &y);
+ if(!button_flag)
+ {
+ return on_mouse_button_up(x, y);
+ }
+
+ double xp = x + m_pdx;
+ double yp = y + m_pdy;
+ double dv;
+
+ switch(m_move_what)
+ {
+ case move_value1:
+ if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
+ {
+ m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1);
+ }
+ else
+ {
+ m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1);
+ }
+ if(m_value1 < 0.0) m_value1 = 0.0;
+ if(m_value1 > m_value2 - m_min_d) m_value1 = m_value2 - m_min_d;
+ return true;
+
+ case move_value2:
+ if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
+ {
+ m_value2 = (xp - m_xs1) / (m_xs2 - m_xs1);
+ }
+ else
+ {
+ m_value2 = (yp - m_ys1) / (m_ys2 - m_ys1);
+ }
+ if(m_value2 > 1.0) m_value2 = 1.0;
+ if(m_value2 < m_value1 + m_min_d) m_value2 = m_value1 + m_min_d;
+ return true;
+
+ case move_slider:
+ dv = m_value2 - m_value1;
+ if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1))
+ {
+ m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1);
+ }
+ else
+ {
+ m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1);
+ }
+ m_value2 = m_value1 + dv;
+ if(m_value1 < 0.0)
+ {
+ dv = m_value2 - m_value1;
+ m_value1 = 0.0;
+ m_value2 = m_value1 + dv;
+ }
+ if(m_value2 > 1.0)
+ {
+ dv = m_value2 - m_value1;
+ m_value2 = 1.0;
+ m_value1 = m_value2 - dv;
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool scale_ctrl_impl::on_mouse_button_up(double, double)
+ {
+ m_move_what = move_nothing;
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool scale_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+/*
+ if(right || up)
+ {
+ m_value += 0.005;
+ if(m_value > 1.0) m_value = 1.0;
+ return true;
+ }
+
+ if(left || down)
+ {
+ m_value -= 0.005;
+ if(m_value < 0.0) m_value = 0.0;
+ return true;
+ }
+*/
+ return false;
+ }
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_slider_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_slider_ctrl.cpp new file mode 100644 index 0000000000..113b7ac08e --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_slider_ctrl.cpp @@ -0,0 +1,354 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <string.h>
+#include <stdio.h>
+#include "ctrl/agg_slider_ctrl.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ slider_ctrl_impl::slider_ctrl_impl(double x1, double y1,
+ double x2, double y2, bool flip_y) :
+ ctrl(x1, y1, x2, y2, flip_y),
+ m_border_width(1.0),
+ m_border_extra((y2 - y1) / 2),
+ m_text_thickness(1.0),
+ m_pdx(0.0),
+ m_mouse_move(false),
+ m_value(0.5),
+ m_preview_value(0.5),
+ m_min(0.0),
+ m_max(1.0),
+ m_num_steps(0),
+ m_descending(false),
+ m_text_poly(m_text)
+ {
+ m_label[0] = 0;
+ calc_box();
+ }
+
+
+ //------------------------------------------------------------------------
+ void slider_ctrl_impl::calc_box()
+ {
+ m_xs1 = m_x1 + m_border_width;
+ m_ys1 = m_y1 + m_border_width;
+ m_xs2 = m_x2 - m_border_width;
+ m_ys2 = m_y2 - m_border_width;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool slider_ctrl_impl::normalize_value(bool preview_value_flag)
+ {
+ bool ret = true;
+ if(m_num_steps)
+ {
+ int step = int(m_preview_value * m_num_steps + 0.5);
+ ret = m_value != step / double(m_num_steps);
+ m_value = step / double(m_num_steps);
+ }
+ else
+ {
+ m_value = m_preview_value;
+ }
+
+ if(preview_value_flag)
+ {
+ m_preview_value = m_value;
+ }
+ return ret;
+ }
+
+
+ //------------------------------------------------------------------------
+ void slider_ctrl_impl::border_width(double t, double extra)
+ {
+ m_border_width = t;
+ m_border_extra = extra;
+ calc_box();
+ }
+
+
+ //------------------------------------------------------------------------
+ void slider_ctrl_impl::value(double value)
+ {
+ m_preview_value = (value - m_min) / (m_max - m_min);
+ if(m_preview_value > 1.0) m_preview_value = 1.0;
+ if(m_preview_value < 0.0) m_preview_value = 0.0;
+ normalize_value(true);
+ }
+
+ //------------------------------------------------------------------------
+ void slider_ctrl_impl::label(const char* fmt)
+ {
+ m_label[0] = 0;
+ if(fmt)
+ {
+ unsigned len = strlen(fmt);
+ if(len > 63) len = 63;
+ memcpy(m_label, fmt, len);
+ m_label[len] = 0;
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void slider_ctrl_impl::rewind(unsigned idx)
+ {
+ m_idx = idx;
+
+ switch(idx)
+ {
+ default:
+
+ case 0: // Background
+ m_vertex = 0;
+ m_vx[0] = m_x1 - m_border_extra;
+ m_vy[0] = m_y1 - m_border_extra;
+ m_vx[1] = m_x2 + m_border_extra;
+ m_vy[1] = m_y1 - m_border_extra;
+ m_vx[2] = m_x2 + m_border_extra;
+ m_vy[2] = m_y2 + m_border_extra;
+ m_vx[3] = m_x1 - m_border_extra;
+ m_vy[3] = m_y2 + m_border_extra;
+ break;
+
+ case 1: // Triangle
+ m_vertex = 0;
+ if(m_descending)
+ {
+ m_vx[0] = m_x1;
+ m_vy[0] = m_y1;
+ m_vx[1] = m_x2;
+ m_vy[1] = m_y1;
+ m_vx[2] = m_x1;
+ m_vy[2] = m_y2;
+ m_vx[3] = m_x1;
+ m_vy[3] = m_y1;
+ }
+ else
+ {
+ m_vx[0] = m_x1;
+ m_vy[0] = m_y1;
+ m_vx[1] = m_x2;
+ m_vy[1] = m_y1;
+ m_vx[2] = m_x2;
+ m_vy[2] = m_y2;
+ m_vx[3] = m_x1;
+ m_vy[3] = m_y1;
+ }
+ break;
+
+ case 2:
+ m_text.text(m_label);
+ if(m_label[0])
+ {
+ char buf[256];
+ sprintf(buf, m_label, value());
+ m_text.text(buf);
+ }
+ m_text.start_point(m_x1, m_y1);
+ m_text.size((m_y2 - m_y1) * 1.2, m_y2 - m_y1);
+ m_text_poly.width(m_text_thickness);
+ m_text_poly.line_join(round_join);
+ m_text_poly.line_cap(round_cap);
+ m_text_poly.rewind(0);
+ break;
+
+ case 3: // pointer preview
+ m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_preview_value,
+ (m_ys1 + m_ys2) / 2.0,
+ m_y2 - m_y1,
+ m_y2 - m_y1,
+ 32);
+ break;
+
+
+ case 4: // pointer
+ normalize_value(false);
+ m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value,
+ (m_ys1 + m_ys2) / 2.0,
+ m_y2 - m_y1,
+ m_y2 - m_y1,
+ 32);
+ m_ellipse.rewind(0);
+ break;
+
+ case 5:
+ m_storage.remove_all();
+ if(m_num_steps)
+ {
+ unsigned i;
+ double d = (m_xs2 - m_xs1) / m_num_steps;
+ if(d > 0.004) d = 0.004;
+ for(i = 0; i < m_num_steps + 1; i++)
+ {
+ double x = m_xs1 + (m_xs2 - m_xs1) * i / m_num_steps;
+ m_storage.move_to(x, m_y1);
+ m_storage.line_to(x - d * (m_x2 - m_x1), m_y1 - m_border_extra);
+ m_storage.line_to(x + d * (m_x2 - m_x1), m_y1 - m_border_extra);
+ }
+ }
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned slider_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ switch(m_idx)
+ {
+ case 0:
+ if(m_vertex == 0) cmd = path_cmd_move_to;
+ if(m_vertex >= 4) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 1:
+ if(m_vertex == 0) cmd = path_cmd_move_to;
+ if(m_vertex >= 4) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 2:
+ cmd = m_text_poly.vertex(x, y);
+ break;
+
+ case 3:
+ case 4:
+ cmd = m_ellipse.vertex(x, y);
+ break;
+
+ case 5:
+ cmd = m_storage.vertex(x, y);
+ break;
+
+ default:
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+
+ return cmd;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool slider_ctrl_impl::in_rect(double x, double y) const
+ {
+ inverse_transform_xy(&x, &y);
+ return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool slider_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+
+ double xp = m_xs1 + (m_xs2 - m_xs1) * m_value;
+ double yp = (m_ys1 + m_ys2) / 2.0;
+
+ if(calc_distance(x, y, xp, yp) <= m_y2 - m_y1)
+ {
+ m_pdx = xp - x;
+ m_mouse_move = true;
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool slider_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
+ {
+ inverse_transform_xy(&x, &y);
+ if(!button_flag)
+ {
+ on_mouse_button_up(x, y);
+ return false;
+ }
+
+ if(m_mouse_move)
+ {
+ double xp = x + m_pdx;
+ m_preview_value = (xp - m_xs1) / (m_xs2 - m_xs1);
+ if(m_preview_value < 0.0) m_preview_value = 0.0;
+ if(m_preview_value > 1.0) m_preview_value = 1.0;
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool slider_ctrl_impl::on_mouse_button_up(double, double)
+ {
+ m_mouse_move = false;
+ normalize_value(true);
+ return true;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool slider_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+ double d = 0.005;
+ if(m_num_steps)
+ {
+ d = 1.0 / m_num_steps;
+ }
+
+ if(right || up)
+ {
+ m_preview_value += d;
+ if(m_preview_value > 1.0) m_preview_value = 1.0;
+ normalize_value(true);
+ return true;
+ }
+
+ if(left || down)
+ {
+ m_preview_value -= d;
+ if(m_preview_value < 0.0) m_preview_value = 0.0;
+ normalize_value(true);
+ return true;
+ }
+ return false;
+ }
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/ctrl/agg_spline_ctrl.cpp b/plugins/Clist_ng/AGG/src/ctrl/agg_spline_ctrl.cpp new file mode 100644 index 0000000000..6716607c65 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/ctrl/agg_spline_ctrl.cpp @@ -0,0 +1,412 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include "ctrl/agg_spline_ctrl.h"
+
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ spline_ctrl_impl::spline_ctrl_impl(double x1, double y1, double x2, double y2,
+ unsigned num_pnt, bool flip_y) :
+ ctrl(x1, y1, x2, y2, flip_y),
+ m_num_pnt(num_pnt),
+ m_border_width(1.0),
+ m_border_extra(0.0),
+ m_curve_width(1.0),
+ m_point_size(3.0),
+ m_curve_poly(m_curve_pnt),
+ m_idx(0),
+ m_vertex(0),
+ m_active_pnt(-1),
+ m_move_pnt(-1),
+ m_pdx(0.0),
+ m_pdy(0.0)
+ {
+ if(m_num_pnt < 4) m_num_pnt = 4;
+ if(m_num_pnt > 32) m_num_pnt = 32;
+
+ unsigned i;
+ for(i = 0; i < m_num_pnt; i++)
+ {
+ m_xp[i] = double(i) / double(m_num_pnt - 1);
+ m_yp[i] = 0.5;
+ }
+ calc_spline_box();
+ update_spline();
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::border_width(double t, double extra)
+ {
+ m_border_width = t;
+ m_border_extra = extra;
+ calc_spline_box();
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::calc_spline_box()
+ {
+ m_xs1 = m_x1 + m_border_width;
+ m_ys1 = m_y1 + m_border_width;
+ m_xs2 = m_x2 - m_border_width;
+ m_ys2 = m_y2 - m_border_width;
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::update_spline()
+ {
+ int i;
+ m_spline.init(m_num_pnt, m_xp, m_yp);
+ for(i = 0; i < 256; i++)
+ {
+ m_spline_values[i] = m_spline.get(double(i) / 255.0);
+ if(m_spline_values[i] < 0.0) m_spline_values[i] = 0.0;
+ if(m_spline_values[i] > 1.0) m_spline_values[i] = 1.0;
+ m_spline_values8[i] = (int8u)(m_spline_values[i] * 255.0);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::calc_curve()
+ {
+ int i;
+ m_curve_pnt.remove_all();
+ m_curve_pnt.move_to(m_xs1, m_ys1 + (m_ys2 - m_ys1) * m_spline_values[0]);
+ for(i = 1; i < 256; i++)
+ {
+ m_curve_pnt.line_to(m_xs1 + (m_xs2 - m_xs1) * double(i) / 255.0,
+ m_ys1 + (m_ys2 - m_ys1) * m_spline_values[i]);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ double spline_ctrl_impl::calc_xp(unsigned idx)
+ {
+ return m_xs1 + (m_xs2 - m_xs1) * m_xp[idx];
+ }
+
+
+ //------------------------------------------------------------------------
+ double spline_ctrl_impl::calc_yp(unsigned idx)
+ {
+ return m_ys1 + (m_ys2 - m_ys1) * m_yp[idx];
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::set_xp(unsigned idx, double val)
+ {
+ if(val < 0.0) val = 0.0;
+ if(val > 1.0) val = 1.0;
+
+ if(idx == 0)
+ {
+ val = 0.0;
+ }
+ else if(idx == m_num_pnt - 1)
+ {
+ val = 1.0;
+ }
+ else
+ {
+ if(val < m_xp[idx - 1] + 0.001) val = m_xp[idx - 1] + 0.001;
+ if(val > m_xp[idx + 1] - 0.001) val = m_xp[idx + 1] - 0.001;
+ }
+ m_xp[idx] = val;
+ }
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::set_yp(unsigned idx, double val)
+ {
+ if(val < 0.0) val = 0.0;
+ if(val > 1.0) val = 1.0;
+ m_yp[idx] = val;
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::point(unsigned idx, double x, double y)
+ {
+ if(idx < m_num_pnt)
+ {
+ set_xp(idx, x);
+ set_yp(idx, y);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::value(unsigned idx, double y)
+ {
+ if(idx < m_num_pnt)
+ {
+ set_yp(idx, y);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ double spline_ctrl_impl::value(double x) const
+ {
+ x = m_spline.get(x);
+ if(x < 0.0) x = 0.0;
+ if(x > 1.0) x = 1.0;
+ return x;
+ }
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::rewind(unsigned idx)
+ {
+ unsigned i;
+
+ m_idx = idx;
+
+ switch(idx)
+ {
+ default:
+
+ case 0: // Background
+ m_vertex = 0;
+ m_vx[0] = m_x1 - m_border_extra;
+ m_vy[0] = m_y1 - m_border_extra;
+ m_vx[1] = m_x2 + m_border_extra;
+ m_vy[1] = m_y1 - m_border_extra;
+ m_vx[2] = m_x2 + m_border_extra;
+ m_vy[2] = m_y2 + m_border_extra;
+ m_vx[3] = m_x1 - m_border_extra;
+ m_vy[3] = m_y2 + m_border_extra;
+ break;
+
+ case 1: // Border
+ m_vertex = 0;
+ m_vx[0] = m_x1;
+ m_vy[0] = m_y1;
+ m_vx[1] = m_x2;
+ m_vy[1] = m_y1;
+ m_vx[2] = m_x2;
+ m_vy[2] = m_y2;
+ m_vx[3] = m_x1;
+ m_vy[3] = m_y2;
+ m_vx[4] = m_x1 + m_border_width;
+ m_vy[4] = m_y1 + m_border_width;
+ m_vx[5] = m_x1 + m_border_width;
+ m_vy[5] = m_y2 - m_border_width;
+ m_vx[6] = m_x2 - m_border_width;
+ m_vy[6] = m_y2 - m_border_width;
+ m_vx[7] = m_x2 - m_border_width;
+ m_vy[7] = m_y1 + m_border_width;
+ break;
+
+ case 2: // Curve
+ calc_curve();
+ m_curve_poly.width(m_curve_width);
+ m_curve_poly.rewind(0);
+ break;
+
+
+ case 3: // Inactive points
+ m_curve_pnt.remove_all();
+ for(i = 0; i < m_num_pnt; i++)
+ {
+ if(int(i) != m_active_pnt)
+ {
+ m_ellipse.init(calc_xp(i), calc_yp(i),
+ m_point_size, m_point_size, 32);
+ m_curve_pnt.concat_path(m_ellipse);
+ }
+ }
+ m_curve_poly.rewind(0);
+ break;
+
+
+ case 4: // Active point
+ m_curve_pnt.remove_all();
+ if(m_active_pnt >= 0)
+ {
+ m_ellipse.init(calc_xp(m_active_pnt), calc_yp(m_active_pnt),
+ m_point_size, m_point_size, 32);
+
+ m_curve_pnt.concat_path(m_ellipse);
+ }
+ m_curve_poly.rewind(0);
+ break;
+
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned spline_ctrl_impl::vertex(double* x, double* y)
+ {
+ unsigned cmd = path_cmd_line_to;
+ switch(m_idx)
+ {
+ case 0:
+ if(m_vertex == 0) cmd = path_cmd_move_to;
+ if(m_vertex >= 4) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 1:
+ if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to;
+ if(m_vertex >= 8) cmd = path_cmd_stop;
+ *x = m_vx[m_vertex];
+ *y = m_vy[m_vertex];
+ m_vertex++;
+ break;
+
+ case 2:
+ cmd = m_curve_poly.vertex(x, y);
+ break;
+
+ case 3:
+ case 4:
+ cmd = m_curve_pnt.vertex(x, y);
+ break;
+
+ default:
+ cmd = path_cmd_stop;
+ break;
+ }
+
+ if(!is_stop(cmd))
+ {
+ transform_xy(x, y);
+ }
+
+ return cmd;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void spline_ctrl_impl::active_point(int i)
+ {
+ m_active_pnt = i;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool spline_ctrl_impl::in_rect(double x, double y) const
+ {
+ inverse_transform_xy(&x, &y);
+ return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool spline_ctrl_impl::on_mouse_button_down(double x, double y)
+ {
+ inverse_transform_xy(&x, &y);
+ unsigned i;
+ for(i = 0; i < m_num_pnt; i++)
+ {
+ double xp = calc_xp(i);
+ double yp = calc_yp(i);
+ if(calc_distance(x, y, xp, yp) <= m_point_size + 1)
+ {
+ m_pdx = xp - x;
+ m_pdy = yp - y;
+ m_active_pnt = m_move_pnt = int(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool spline_ctrl_impl::on_mouse_button_up(double, double)
+ {
+ if(m_move_pnt >= 0)
+ {
+ m_move_pnt = -1;
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool spline_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
+ {
+ inverse_transform_xy(&x, &y);
+ if(!button_flag)
+ {
+ return on_mouse_button_up(x, y);
+ }
+
+ if(m_move_pnt >= 0)
+ {
+ double xp = x + m_pdx;
+ double yp = y + m_pdy;
+
+ set_xp(m_move_pnt, (xp - m_xs1) / (m_xs2 - m_xs1));
+ set_yp(m_move_pnt, (yp - m_ys1) / (m_ys2 - m_ys1));
+
+ update_spline();
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ bool spline_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
+ {
+ double kx = 0.0;
+ double ky = 0.0;
+ bool ret = false;
+ if(m_active_pnt >= 0)
+ {
+ kx = m_xp[m_active_pnt];
+ ky = m_yp[m_active_pnt];
+ if(left) { kx -= 0.001; ret = true; }
+ if(right) { kx += 0.001; ret = true; }
+ if(down) { ky -= 0.001; ret = true; }
+ if(up) { ky += 0.001; ret = true; }
+ }
+ if(ret)
+ {
+ set_xp(m_active_pnt, kx);
+ set_yp(m_active_pnt, ky);
+ update_spline();
+ }
+ return ret;
+ }
+
+
+
+
+}
+
diff --git a/plugins/Clist_ng/AGG/src/install b/plugins/Clist_ng/AGG/src/install new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/install diff --git a/plugins/Clist_ng/AGG/src/news b/plugins/Clist_ng/AGG/src/news new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/news diff --git a/plugins/Clist_ng/AGG/src/platform/Makefile.am b/plugins/Clist_ng/AGG/src/platform/Makefile.am new file mode 100644 index 0000000000..b68cc62b07 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/platform/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = X11 sdl win32 AmigaOS BeOS mac
diff --git a/plugins/Clist_ng/AGG/src/platform/sdl/Makefile.am b/plugins/Clist_ng/AGG/src/platform/sdl/Makefile.am new file mode 100644 index 0000000000..4394edf15f --- /dev/null +++ b/plugins/Clist_ng/AGG/src/platform/sdl/Makefile.am @@ -0,0 +1,10 @@ +if ENABLE_SDL
+
+lib_LTLIBRARIES = libaggplatformsdl.la
+
+libaggplatformsdl_la_LDFLAGS = -version-info @AGG_LIB_VERSION@
+libaggplatformsdl_la_SOURCES = agg_platform_support.cpp
+libaggplatformsdl_la_CXXFLAGS = -I$(top_srcdir)/include @SDL_CFLAGS@
+libaggplatformsdl_la_LIBADD = @SDL_LIBS@
+endif
+
diff --git a/plugins/Clist_ng/AGG/src/platform/sdl/agg_platform_support.cpp b/plugins/Clist_ng/AGG/src/platform/sdl/agg_platform_support.cpp new file mode 100644 index 0000000000..357230b3ef --- /dev/null +++ b/plugins/Clist_ng/AGG/src/platform/sdl/agg_platform_support.cpp @@ -0,0 +1,714 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Copyright (C) 2004 Mauricio Piacentini (SDL Support)
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <string.h>
+#include "platform/agg_platform_support.h"
+#include "SDL.h"
+#include "SDL_byteorder.h"
+
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ class platform_specific
+ {
+ public:
+ platform_specific(pix_format_e format, bool flip_y);
+ ~platform_specific();
+
+ pix_format_e m_format;
+ pix_format_e m_sys_format;
+ bool m_flip_y;
+ unsigned m_bpp;
+ unsigned m_sys_bpp;
+ unsigned m_rmask;
+ unsigned m_gmask;
+ unsigned m_bmask;
+ unsigned m_amask;
+ bool m_update_flag;
+ bool m_resize_flag;
+ bool m_initialized;
+ SDL_Surface* m_surf_screen;
+ SDL_Surface* m_surf_window;
+ SDL_Surface* m_surf_img[platform_support::max_images];
+ int m_cur_x;
+ int m_cur_y;
+ int m_sw_start;
+ };
+
+
+
+ //------------------------------------------------------------------------
+ platform_specific::platform_specific(pix_format_e format, bool flip_y) :
+ m_format(format),
+ m_sys_format(pix_format_undefined),
+ m_flip_y(flip_y),
+ m_bpp(0),
+ m_sys_bpp(0),
+ m_update_flag(true),
+ m_resize_flag(true),
+ m_initialized(false),
+ m_surf_screen(0),
+ m_surf_window(0),
+ m_cur_x(0),
+ m_cur_y(0)
+ {
+ memset(m_surf_img, 0, sizeof(m_surf_img));
+
+ switch(m_format)
+ {
+ case pix_format_gray8:
+ m_bpp = 8;
+ break;
+
+ case pix_format_rgb565:
+ m_rmask = 0xF800;
+ m_gmask = 0x7E0;
+ m_bmask = 0x1F;
+ m_amask = 0;
+ m_bpp = 16;
+ break;
+
+ case pix_format_rgb555:
+ m_rmask = 0x7C00;
+ m_gmask = 0x3E0;
+ m_bmask = 0x1F;
+ m_amask = 0;
+ m_bpp = 16;
+ break;
+
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ case pix_format_rgb24:
+ m_rmask = 0xFF;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF0000;
+ m_amask = 0;
+ m_bpp = 24;
+ break;
+
+ case pix_format_bgr24:
+ m_rmask = 0xFF0000;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF;
+ m_amask = 0;
+ m_bpp = 24;
+ break;
+
+ case pix_format_bgra32:
+ m_rmask = 0xFF0000;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF;
+ m_amask = 0xFF000000;
+ m_bpp = 32;
+ break;
+
+ case pix_format_abgr32:
+ m_rmask = 0xFF000000;
+ m_gmask = 0xFF0000;
+ m_bmask = 0xFF00;
+ m_amask = 0xFF;
+ m_bpp = 32;
+ break;
+
+ case pix_format_argb32:
+ m_rmask = 0xFF00;
+ m_gmask = 0xFF0000;
+ m_bmask = 0xFF000000;
+ m_amask = 0xFF;
+ m_bpp = 32;
+ break;
+
+ case pix_format_rgba32:
+ m_rmask = 0xFF;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF0000;
+ m_amask = 0xFF000000;
+ m_bpp = 32;
+ break;
+#else //SDL_BIG_ENDIAN (PPC)
+ case pix_format_rgb24:
+ m_rmask = 0xFF0000;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF;
+ m_amask = 0;
+ m_bpp = 24;
+ break;
+
+ case pix_format_bgr24:
+ m_rmask = 0xFF;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF0000;
+ m_amask = 0;
+ m_bpp = 24;
+ break;
+
+ case pix_format_bgra32:
+ m_rmask = 0xFF00;
+ m_gmask = 0xFF0000;
+ m_bmask = 0xFF000000;
+ m_amask = 0xFF;
+ m_bpp = 32;
+ break;
+
+ case pix_format_abgr32:
+ m_rmask = 0xFF;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF0000;
+ m_amask = 0xFF000000;
+ m_bpp = 32;
+ break;
+
+ case pix_format_argb32:
+ m_rmask = 0xFF0000;
+ m_gmask = 0xFF00;
+ m_bmask = 0xFF;
+ m_amask = 0xFF000000;
+ m_bpp = 32;
+ break;
+
+ case pix_format_rgba32:
+ m_rmask = 0xFF000000;
+ m_gmask = 0xFF0000;
+ m_bmask = 0xFF00;
+ m_amask = 0xFF;
+ m_bpp = 32;
+ break;
+#endif
+ }
+ }
+
+ //------------------------------------------------------------------------
+ platform_specific::~platform_specific()
+ {
+ int i;
+ for(i = platform_support::max_images - 1; i >= 0; --i)
+ {
+ if(m_surf_img[i]) SDL_FreeSurface(m_surf_img[i]);
+ }
+ if(m_surf_window) SDL_FreeSurface(m_surf_window);
+ if(m_surf_screen) SDL_FreeSurface(m_surf_screen);
+ }
+
+
+
+ //------------------------------------------------------------------------
+ platform_support::platform_support(pix_format_e format, bool flip_y) :
+ m_specific(new platform_specific(format, flip_y)),
+ m_format(format),
+ m_bpp(m_specific->m_bpp),
+ m_window_flags(0),
+ m_wait_mode(true),
+ m_flip_y(flip_y)
+ {
+ SDL_Init(SDL_INIT_VIDEO);
+ strcpy(m_caption, "Anti-Grain Geometry Application");
+ }
+
+
+ //------------------------------------------------------------------------
+ platform_support::~platform_support()
+ {
+ delete m_specific;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void platform_support::caption(const char* cap)
+ {
+ strcpy(m_caption, cap);
+ if(m_specific->m_initialized)
+ {
+ SDL_WM_SetCaption(cap, 0);
+ }
+ }
+
+
+
+
+
+ //------------------------------------------------------------------------
+ bool platform_support::init(unsigned width, unsigned height, unsigned flags)
+ {
+ m_window_flags = flags;
+ unsigned wflags = SDL_SWSURFACE;
+
+ if(m_window_flags & window_hw_buffer)
+ {
+ wflags = SDL_HWSURFACE;
+ }
+
+ if(m_window_flags & window_resize)
+ {
+ wflags |= SDL_RESIZABLE;
+ }
+
+ if(m_specific->m_surf_screen) SDL_FreeSurface(m_specific->m_surf_screen);
+
+ m_specific->m_surf_screen = SDL_SetVideoMode(width, height, m_bpp, wflags);
+ if(m_specific->m_surf_screen == 0)
+ {
+ fprintf(stderr,
+ "Unable to set %dx%d %d bpp video: %s\n",
+ width,
+ height,
+ m_bpp,
+ ::SDL_GetError());
+ return false;
+ }
+
+ SDL_WM_SetCaption(m_caption, 0);
+
+ if(m_specific->m_surf_window) SDL_FreeSurface(m_specific->m_surf_window);
+
+ m_specific->m_surf_window =
+ SDL_CreateRGBSurface(SDL_HWSURFACE,
+ m_specific->m_surf_screen->w,
+ m_specific->m_surf_screen->h,
+ m_specific->m_surf_screen->format->BitsPerPixel,
+ m_specific->m_rmask,
+ m_specific->m_gmask,
+ m_specific->m_bmask,
+ m_specific->m_amask);
+
+ if(m_specific->m_surf_window == 0)
+ {
+ fprintf(stderr,
+ "Unable to create image buffer %dx%d %d bpp: %s\n",
+ width,
+ height,
+ m_bpp,
+ SDL_GetError());
+ return false;
+ }
+
+ m_rbuf_window.attach((unsigned char*)m_specific->m_surf_window->pixels,
+ m_specific->m_surf_window->w,
+ m_specific->m_surf_window->h,
+ m_flip_y ? -m_specific->m_surf_window->pitch :
+ m_specific->m_surf_window->pitch);
+
+ if(!m_specific->m_initialized)
+ {
+ m_initial_width = width;
+ m_initial_height = height;
+ on_init();
+ m_specific->m_initialized = true;
+ }
+ on_resize(m_rbuf_window.width(), m_rbuf_window.height());
+ m_specific->m_update_flag = true;
+ return true;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void platform_support::update_window()
+ {
+ SDL_BlitSurface(m_specific->m_surf_window, 0, m_specific->m_surf_screen, 0);
+ SDL_UpdateRect(m_specific->m_surf_screen, 0, 0, 0, 0);
+ }
+
+
+ //------------------------------------------------------------------------
+ int platform_support::run()
+ {
+ SDL_Event event;
+ bool ev_flag = false;
+
+ for(;;)
+ {
+ if(m_specific->m_update_flag)
+ {
+ on_draw();
+ update_window();
+ m_specific->m_update_flag = false;
+ }
+
+ ev_flag = false;
+ if(m_wait_mode)
+ {
+ SDL_WaitEvent(&event);
+ ev_flag = true;
+ }
+ else
+ {
+ if(SDL_PollEvent(&event))
+ {
+ ev_flag = true;
+ }
+ else
+ {
+ on_idle();
+ }
+ }
+
+ if(ev_flag)
+ {
+ if(event.type == SDL_QUIT)
+ {
+ break;
+ }
+
+ int y;
+ unsigned flags = 0;
+
+ switch (event.type)
+ {
+ case SDL_VIDEORESIZE:
+ if(!init(event.resize.w, event.resize.h, m_window_flags)) return false;
+ on_resize(m_rbuf_window.width(), m_rbuf_window.height());
+ trans_affine_resizing(event.resize.w, event.resize.h);
+ m_specific->m_update_flag = true;
+ break;
+
+ case SDL_KEYDOWN:
+ {
+ flags = 0;
+ if(event.key.keysym.mod & KMOD_SHIFT) flags |= kbd_shift;
+ if(event.key.keysym.mod & KMOD_CTRL) flags |= kbd_ctrl;
+
+ bool left = false;
+ bool up = false;
+ bool right = false;
+ bool down = false;
+
+ switch(event.key.keysym.sym)
+ {
+ case key_left:
+ left = true;
+ break;
+
+ case key_up:
+ up = true;
+ break;
+
+ case key_right:
+ right = true;
+ break;
+
+ case key_down:
+ down = true;
+ break;
+ }
+
+ if(m_ctrls.on_arrow_keys(left, right, down, up))
+ {
+ on_ctrl_change();
+ force_redraw();
+ }
+ else
+ {
+ on_key(m_specific->m_cur_x,
+ m_specific->m_cur_y,
+ event.key.keysym.sym,
+ flags);
+ }
+ }
+ break;
+
+ case SDL_MOUSEMOTION:
+ y = m_flip_y ?
+ m_rbuf_window.height() - event.motion.y :
+ event.motion.y;
+
+ m_specific->m_cur_x = event.motion.x;
+ m_specific->m_cur_y = y;
+ flags = 0;
+ if(event.motion.state & SDL_BUTTON_LMASK) flags |= mouse_left;
+ if(event.motion.state & SDL_BUTTON_RMASK) flags |= mouse_right;
+
+ if(m_ctrls.on_mouse_move(m_specific->m_cur_x,
+ m_specific->m_cur_y,
+ (flags & mouse_left) != 0))
+ {
+ on_ctrl_change();
+ force_redraw();
+ }
+ else
+ {
+ on_mouse_move(m_specific->m_cur_x,
+ m_specific->m_cur_y,
+ flags);
+ }
+ SDL_Event eventtrash;
+ while (SDL_PeepEvents(&eventtrash, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEMOTION))!=0){;}
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ y = m_flip_y
+ ? m_rbuf_window.height() - event.button.y
+ : event.button.y;
+
+ m_specific->m_cur_x = event.button.x;
+ m_specific->m_cur_y = y;
+ flags = 0;
+ switch(event.button.button)
+ {
+ case SDL_BUTTON_LEFT:
+ {
+ flags = mouse_left;
+
+if(m_ctrls.on_mouse_button_down(m_specific->m_cur_x,
+ m_specific->m_cur_y))
+ {
+ m_ctrls.set_cur(m_specific->m_cur_x,
+ m_specific->m_cur_y);
+ on_ctrl_change();
+ force_redraw();
+ }
+ else
+ {
+ if(m_ctrls.in_rect(m_specific->m_cur_x,
+ m_specific->m_cur_y))
+ {
+ if(m_ctrls.set_cur(m_specific->m_cur_x,
+ m_specific->m_cur_y))
+ {
+ on_ctrl_change();
+ force_redraw();
+ }
+ }
+ else
+ {
+ on_mouse_button_down(m_specific->m_cur_x,
+ m_specific->m_cur_y,
+ flags);
+ }
+ }
+ }
+ break;
+ case SDL_BUTTON_RIGHT:
+ flags = mouse_right;
+ on_mouse_button_down(m_specific->m_cur_x,
+ m_specific->m_cur_y,
+ flags);
+ break;
+ } //switch(event.button.button)
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ y = m_flip_y
+ ? m_rbuf_window.height() - event.button.y
+ : event.button.y;
+
+ m_specific->m_cur_x = event.button.x;
+ m_specific->m_cur_y = y;
+ flags = 0;
+ if(m_ctrls.on_mouse_button_up(m_specific->m_cur_x,
+ m_specific->m_cur_y))
+ {
+ on_ctrl_change();
+ force_redraw();
+ }
+ on_mouse_button_up(m_specific->m_cur_x,
+ m_specific->m_cur_y,
+ flags);
+ break;
+ }
+ }
+ }
+ return 0;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ const char* platform_support::img_ext() const { return ".bmp"; }
+
+ //------------------------------------------------------------------------
+ const char* platform_support::full_file_name(const char* file_name)
+ {
+ return file_name;
+ }
+
+ //------------------------------------------------------------------------
+ bool platform_support::load_img(unsigned idx, const char* file)
+ {
+ if(idx < max_images)
+ {
+ if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]);
+
+ char fn[1024];
+ strcpy(fn, file);
+ int len = strlen(fn);
+ if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0)
+ {
+ strcat(fn, ".bmp");
+ }
+
+ SDL_Surface* tmp_surf = SDL_LoadBMP(fn);
+ if (tmp_surf == 0)
+ {
+ fprintf(stderr, "Couldn't load %s: %s\n", fn, SDL_GetError());
+ return false;
+ }
+
+ SDL_PixelFormat format;
+ format.palette = 0;
+ format.BitsPerPixel = m_bpp;
+ format.BytesPerPixel = m_bpp >> 8;
+ format.Rmask = m_specific->m_rmask;
+ format.Gmask = m_specific->m_gmask;
+ format.Bmask = m_specific->m_bmask;
+ format.Amask = m_specific->m_amask;
+ format.Rshift = 0;
+ format.Gshift = 0;
+ format.Bshift = 0;
+ format.Ashift = 0;
+ format.Rloss = 0;
+ format.Gloss = 0;
+ format.Bloss = 0;
+ format.Aloss = 0;
+ format.colorkey = 0;
+ format.alpha = 0;
+
+ m_specific->m_surf_img[idx] =
+ SDL_ConvertSurface(tmp_surf,
+ &format,
+ SDL_SWSURFACE);
+
+ SDL_FreeSurface(tmp_surf);
+
+ if(m_specific->m_surf_img[idx] == 0) return false;
+
+ m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels,
+ m_specific->m_surf_img[idx]->w,
+ m_specific->m_surf_img[idx]->h,
+ m_flip_y ? -m_specific->m_surf_img[idx]->pitch :
+ m_specific->m_surf_img[idx]->pitch);
+ return true;
+
+ }
+ return false;
+ }
+
+
+
+
+ //------------------------------------------------------------------------
+ bool platform_support::save_img(unsigned idx, const char* file)
+ {
+ if(idx < max_images && m_specific->m_surf_img[idx])
+ {
+ char fn[1024];
+ strcpy(fn, file);
+ int len = strlen(fn);
+ if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0)
+ {
+ strcat(fn, ".bmp");
+ }
+ return SDL_SaveBMP(m_specific->m_surf_img[idx], fn) == 0;
+ }
+ return false;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool platform_support::create_img(unsigned idx, unsigned width, unsigned height)
+ {
+ if(idx < max_images)
+ {
+
+ if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]);
+
+ m_specific->m_surf_img[idx] =
+ SDL_CreateRGBSurface(SDL_SWSURFACE,
+ width,
+ height,
+ m_specific->m_surf_screen->format->BitsPerPixel,
+ m_specific->m_rmask,
+ m_specific->m_gmask,
+ m_specific->m_bmask,
+ m_specific->m_amask);
+ if(m_specific->m_surf_img[idx] == 0)
+ {
+ fprintf(stderr, "Couldn't create image: %s\n", SDL_GetError());
+ return false;
+ }
+
+ m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels,
+ m_specific->m_surf_img[idx]->w,
+ m_specific->m_surf_img[idx]->h,
+ m_flip_y ? -m_specific->m_surf_img[idx]->pitch :
+ m_specific->m_surf_img[idx]->pitch);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ //------------------------------------------------------------------------
+ void platform_support::start_timer()
+ {
+ m_specific->m_sw_start = SDL_GetTicks();
+ }
+
+ //------------------------------------------------------------------------
+ double platform_support::elapsed_time() const
+ {
+ int stop = SDL_GetTicks();
+ return double(stop - m_specific->m_sw_start);
+ }
+
+ //------------------------------------------------------------------------
+ void platform_support::message(const char* msg)
+ {
+ fprintf(stderr, "%s\n", msg);
+ }
+
+ //------------------------------------------------------------------------
+ void platform_support::force_redraw()
+ {
+ m_specific->m_update_flag = true;
+ }
+
+
+ //------------------------------------------------------------------------
+ void platform_support::on_init() {}
+ void platform_support::on_resize(int sx, int sy) {}
+ void platform_support::on_idle() {}
+ void platform_support::on_mouse_move(int x, int y, unsigned flags) {}
+ void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {}
+ void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {}
+ void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {}
+ void platform_support::on_ctrl_change() {}
+ void platform_support::on_draw() {}
+ void platform_support::on_post_draw(void* raw_handler) {}
+
+
+}
+
+
+int agg_main(int argc, char* argv[]);
+
+int main(int argc, char* argv[])
+{
+ return agg_main(argc, argv);
+}
+
diff --git a/plugins/Clist_ng/AGG/src/platform/win32/Makefile.am b/plugins/Clist_ng/AGG/src/platform/win32/Makefile.am new file mode 100644 index 0000000000..5ad695a09c --- /dev/null +++ b/plugins/Clist_ng/AGG/src/platform/win32/Makefile.am @@ -0,0 +1,13 @@ +
+
+if ENABLE_WIN32
+lib_LTLIBRARIES = libaggplatformwin32.la
+
+libaggplatformwin32_la_LDFLAGS = -version-info @AGG_LIB_VERSION@
+libaggplatformwin32_la_SOURCES = agg_platform_support.cpp \
+ agg_win32_bmp.cpp
+
+libaggplatformwin32_la_CXXFLAGS = -I$(top_srcdir)/include @WINDOWS_CFLAGS@
+libaggplatformwin32_la_LIBADD = @WINDOWS_LIBS@ $(top_builddir)/src/libagg.la
+endif
+
diff --git a/plugins/Clist_ng/AGG/src/platform/win32/agg_platform_support.cpp b/plugins/Clist_ng/AGG/src/platform/win32/agg_platform_support.cpp new file mode 100644 index 0000000000..bf84a6c50c --- /dev/null +++ b/plugins/Clist_ng/AGG/src/platform/win32/agg_platform_support.cpp @@ -0,0 +1,1478 @@ +//----------------------------------------------------------------------------
+// Anti-Grain Geometry (AGG) - Version 2.5
+// A high quality rendering engine for C++
+// Copyright (C) 2002-2006 Maxim Shemanarev
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://antigrain.com
+//
+// AGG 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.
+//
+// AGG 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 AGG; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301, USA.
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <string.h>
+#include "platform/agg_platform_support.h"
+#include "platform/win32/agg_win32_bmp.h"
+#include "util/agg_color_conv_rgb8.h"
+#include "util/agg_color_conv_rgb16.h"
+
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ HINSTANCE g_windows_instance = 0;
+ int g_windows_cmd_show = 0;
+
+
+ //------------------------------------------------------------------------
+ class platform_specific
+ {
+ public:
+ platform_specific(pix_format_e format, bool flip_y);
+
+ void create_pmap(unsigned width, unsigned height,
+ rendering_buffer* wnd);
+
+ void display_pmap(HDC dc, const rendering_buffer* src);
+ bool load_pmap(const char* fn, unsigned idx,
+ rendering_buffer* dst);
+
+ bool save_pmap(const char* fn, unsigned idx,
+ const rendering_buffer* src);
+
+ unsigned translate(unsigned keycode);
+
+ pix_format_e m_format;
+ pix_format_e m_sys_format;
+ bool m_flip_y;
+ unsigned m_bpp;
+ unsigned m_sys_bpp;
+ HWND m_hwnd;
+ pixel_map m_pmap_window;
+ pixel_map m_pmap_img[platform_support::max_images];
+ unsigned m_keymap[256];
+ unsigned m_last_translated_key;
+ int m_cur_x;
+ int m_cur_y;
+ unsigned m_input_flags;
+ bool m_redraw_flag;
+ HDC m_current_dc;
+ LARGE_INTEGER m_sw_freq;
+ LARGE_INTEGER m_sw_start;
+ };
+
+
+ //------------------------------------------------------------------------
+ platform_specific::platform_specific(pix_format_e format, bool flip_y) :
+ m_format(format),
+ m_sys_format(pix_format_undefined),
+ m_flip_y(flip_y),
+ m_bpp(0),
+ m_sys_bpp(0),
+ m_hwnd(0),
+ m_last_translated_key(0),
+ m_cur_x(0),
+ m_cur_y(0),
+ m_input_flags(0),
+ m_redraw_flag(true),
+ m_current_dc(0)
+ {
+ memset(m_keymap, 0, sizeof(m_keymap));
+
+ m_keymap[VK_PAUSE] = key_pause;
+ m_keymap[VK_CLEAR] = key_clear;
+
+ m_keymap[VK_NUMPAD0] = key_kp0;
+ m_keymap[VK_NUMPAD1] = key_kp1;
+ m_keymap[VK_NUMPAD2] = key_kp2;
+ m_keymap[VK_NUMPAD3] = key_kp3;
+ m_keymap[VK_NUMPAD4] = key_kp4;
+ m_keymap[VK_NUMPAD5] = key_kp5;
+ m_keymap[VK_NUMPAD6] = key_kp6;
+ m_keymap[VK_NUMPAD7] = key_kp7;
+ m_keymap[VK_NUMPAD8] = key_kp8;
+ m_keymap[VK_NUMPAD9] = key_kp9;
+ m_keymap[VK_DECIMAL] = key_kp_period;
+ m_keymap[VK_DIVIDE] = key_kp_divide;
+ m_keymap[VK_MULTIPLY] = key_kp_multiply;
+ m_keymap[VK_SUBTRACT] = key_kp_minus;
+ m_keymap[VK_ADD] = key_kp_plus;
+
+ m_keymap[VK_UP] = key_up;
+ m_keymap[VK_DOWN] = key_down;
+ m_keymap[VK_RIGHT] = key_right;
+ m_keymap[VK_LEFT] = key_left;
+ m_keymap[VK_INSERT] = key_insert;
+ m_keymap[VK_DELETE] = key_delete;
+ m_keymap[VK_HOME] = key_home;
+ m_keymap[VK_END] = key_end;
+ m_keymap[VK_PRIOR] = key_page_up;
+ m_keymap[VK_NEXT] = key_page_down;
+
+ m_keymap[VK_F1] = key_f1;
+ m_keymap[VK_F2] = key_f2;
+ m_keymap[VK_F3] = key_f3;
+ m_keymap[VK_F4] = key_f4;
+ m_keymap[VK_F5] = key_f5;
+ m_keymap[VK_F6] = key_f6;
+ m_keymap[VK_F7] = key_f7;
+ m_keymap[VK_F8] = key_f8;
+ m_keymap[VK_F9] = key_f9;
+ m_keymap[VK_F10] = key_f10;
+ m_keymap[VK_F11] = key_f11;
+ m_keymap[VK_F12] = key_f12;
+ m_keymap[VK_F13] = key_f13;
+ m_keymap[VK_F14] = key_f14;
+ m_keymap[VK_F15] = key_f15;
+
+ m_keymap[VK_NUMLOCK] = key_numlock;
+ m_keymap[VK_CAPITAL] = key_capslock;
+ m_keymap[VK_SCROLL] = key_scrollock;
+
+
+ switch(m_format)
+ {
+ case pix_format_bw:
+ m_sys_format = pix_format_bw;
+ m_bpp = 1;
+ m_sys_bpp = 1;
+ break;
+
+ case pix_format_gray8:
+ m_sys_format = pix_format_gray8;
+ m_bpp = 8;
+ m_sys_bpp = 8;
+ break;
+
+ case pix_format_gray16:
+ m_sys_format = pix_format_gray8;
+ m_bpp = 16;
+ m_sys_bpp = 8;
+ break;
+
+ case pix_format_rgb565:
+ case pix_format_rgb555:
+ m_sys_format = pix_format_rgb555;
+ m_bpp = 16;
+ m_sys_bpp = 16;
+ break;
+
+ case pix_format_rgbAAA:
+ case pix_format_bgrAAA:
+ case pix_format_rgbBBA:
+ case pix_format_bgrABB:
+ m_sys_format = pix_format_bgr24;
+ m_bpp = 32;
+ m_sys_bpp = 24;
+ break;
+
+ case pix_format_rgb24:
+ case pix_format_bgr24:
+ m_sys_format = pix_format_bgr24;
+ m_bpp = 24;
+ m_sys_bpp = 24;
+ break;
+
+ case pix_format_rgb48:
+ case pix_format_bgr48:
+ m_sys_format = pix_format_bgr24;
+ m_bpp = 48;
+ m_sys_bpp = 24;
+ break;
+
+ case pix_format_bgra32:
+ case pix_format_abgr32:
+ case pix_format_argb32:
+ case pix_format_rgba32:
+ m_sys_format = pix_format_bgra32;
+ m_bpp = 32;
+ m_sys_bpp = 32;
+ break;
+
+ case pix_format_bgra64:
+ case pix_format_abgr64:
+ case pix_format_argb64:
+ case pix_format_rgba64:
+ m_sys_format = pix_format_bgra32;
+ m_bpp = 64;
+ m_sys_bpp = 32;
+ break;
+ }
+ ::QueryPerformanceFrequency(&m_sw_freq);
+ ::QueryPerformanceCounter(&m_sw_start);
+ }
+
+
+ //------------------------------------------------------------------------
+ void platform_specific::create_pmap(unsigned width,
+ unsigned height,
+ rendering_buffer* wnd)
+ {
+ m_pmap_window.create(width, height, org_e(m_bpp));
+ wnd->attach(m_pmap_window.buf(),
+ m_pmap_window.width(),
+ m_pmap_window.height(),
+ m_flip_y ?
+ m_pmap_window.stride() :
+ -m_pmap_window.stride());
+ }
+
+
+ //------------------------------------------------------------------------
+ static void convert_pmap(rendering_buffer* dst,
+ const rendering_buffer* src,
+ pix_format_e format)
+ {
+ switch(format)
+ {
+ case pix_format_gray8:
+ break;
+
+ case pix_format_gray16:
+ color_conv(dst, src, color_conv_gray16_to_gray8());
+ break;
+
+ case pix_format_rgb565:
+ color_conv(dst, src, color_conv_rgb565_to_rgb555());
+ break;
+
+ case pix_format_rgbAAA:
+ color_conv(dst, src, color_conv_rgbAAA_to_bgr24());
+ break;
+
+ case pix_format_bgrAAA:
+ color_conv(dst, src, color_conv_bgrAAA_to_bgr24());
+ break;
+
+ case pix_format_rgbBBA:
+ color_conv(dst, src, color_conv_rgbBBA_to_bgr24());
+ break;
+
+ case pix_format_bgrABB:
+ color_conv(dst, src, color_conv_bgrABB_to_bgr24());
+ break;
+
+ case pix_format_rgb24:
+ color_conv(dst, src, color_conv_rgb24_to_bgr24());
+ break;
+
+ case pix_format_rgb48:
+ color_conv(dst, src, color_conv_rgb48_to_bgr24());
+ break;
+
+ case pix_format_bgr48:
+ color_conv(dst, src, color_conv_bgr48_to_bgr24());
+ break;
+
+ case pix_format_abgr32:
+ color_conv(dst, src, color_conv_abgr32_to_bgra32());
+ break;
+
+ case pix_format_argb32:
+ color_conv(dst, src, color_conv_argb32_to_bgra32());
+ break;
+
+ case pix_format_rgba32:
+ color_conv(dst, src, color_conv_rgba32_to_bgra32());
+ break;
+
+ case pix_format_bgra64:
+ color_conv(dst, src, color_conv_bgra64_to_bgra32());
+ break;
+
+ case pix_format_abgr64:
+ color_conv(dst, src, color_conv_abgr64_to_bgra32());
+ break;
+
+ case pix_format_argb64:
+ color_conv(dst, src, color_conv_argb64_to_bgra32());
+ break;
+
+ case pix_format_rgba64:
+ color_conv(dst, src, color_conv_rgba64_to_bgra32());
+ break;
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void platform_specific::display_pmap(HDC dc, const rendering_buffer* src)
+ {
+ if(m_sys_format == m_format)
+ {
+ m_pmap_window.draw(dc);
+ }
+ else
+ {
+ pixel_map pmap_tmp;
+ pmap_tmp.create(m_pmap_window.width(),
+ m_pmap_window.height(),
+ org_e(m_sys_bpp));
+
+ rendering_buffer rbuf_tmp;
+ rbuf_tmp.attach(pmap_tmp.buf(),
+ pmap_tmp.width(),
+ pmap_tmp.height(),
+ m_flip_y ?
+ pmap_tmp.stride() :
+ -pmap_tmp.stride());
+
+ convert_pmap(&rbuf_tmp, src, m_format);
+ pmap_tmp.draw(dc);
+ }
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool platform_specific::save_pmap(const char* fn, unsigned idx,
+ const rendering_buffer* src)
+ {
+ if(m_sys_format == m_format)
+ {
+ return m_pmap_img[idx].save_as_bmp(fn);
+ }
+
+ pixel_map pmap_tmp;
+ pmap_tmp.create(m_pmap_img[idx].width(),
+ m_pmap_img[idx].height(),
+ org_e(m_sys_bpp));
+
+ rendering_buffer rbuf_tmp;
+ rbuf_tmp.attach(pmap_tmp.buf(),
+ pmap_tmp.width(),
+ pmap_tmp.height(),
+ m_flip_y ?
+ pmap_tmp.stride() :
+ -pmap_tmp.stride());
+
+ convert_pmap(&rbuf_tmp, src, m_format);
+ return pmap_tmp.save_as_bmp(fn);
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool platform_specific::load_pmap(const char* fn, unsigned idx,
+ rendering_buffer* dst)
+ {
+ pixel_map pmap_tmp;
+ if(!pmap_tmp.load_from_bmp(fn)) return false;
+
+ rendering_buffer rbuf_tmp;
+ rbuf_tmp.attach(pmap_tmp.buf(),
+ pmap_tmp.width(),
+ pmap_tmp.height(),
+ m_flip_y ?
+ pmap_tmp.stride() :
+ -pmap_tmp.stride());
+
+ m_pmap_img[idx].create(pmap_tmp.width(),
+ pmap_tmp.height(),
+ org_e(m_bpp),
+ 0);
+
+ dst->attach(m_pmap_img[idx].buf(),
+ m_pmap_img[idx].width(),
+ m_pmap_img[idx].height(),
+ m_flip_y ?
+ m_pmap_img[idx].stride() :
+ -m_pmap_img[idx].stride());
+
+ switch(m_format)
+ {
+ case pix_format_gray8:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray8()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_gray8()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break;
+ }
+ break;
+
+ case pix_format_gray16:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray16()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_gray16()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray16()); break;
+ }
+ break;
+
+ case pix_format_rgb555:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb555()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb555()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb555()); break;
+ }
+ break;
+
+ case pix_format_rgb565:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb565()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb565()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb565()); break;
+ }
+ break;
+
+ case pix_format_rgb24:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb24()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb24()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb24()); break;
+ }
+ break;
+
+ case pix_format_bgr24:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr24()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgr24()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr24()); break;
+ }
+ break;
+
+ case pix_format_rgb48:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb48()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb48()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb48()); break;
+ }
+ break;
+
+ case pix_format_bgr48:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr48()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgr48()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr48()); break;
+ }
+ break;
+
+ case pix_format_abgr32:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr32()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_abgr32()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr32()); break;
+ }
+ break;
+
+ case pix_format_argb32:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb32()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_argb32()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb32()); break;
+ }
+ break;
+
+ case pix_format_bgra32:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra32()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgra32()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra32()); break;
+ }
+ break;
+
+ case pix_format_rgba32:
+ switch(pmap_tmp.bpp())
+ {
+ case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba32()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgba32()); break;
+ case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break;
+ }
+ break;
+
+ case pix_format_abgr64:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr64()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_abgr64()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr64()); break;
+ }
+ break;
+
+ case pix_format_argb64:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb64()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_argb64()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb64()); break;
+ }
+ break;
+
+ case pix_format_bgra64:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra64()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgra64()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra64()); break;
+ }
+ break;
+
+ case pix_format_rgba64:
+ switch(pmap_tmp.bpp())
+ {
+ //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba64()); break;
+ case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgba64()); break;
+ //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba64()); break;
+ }
+ break;
+
+ }
+
+ return true;
+ }
+
+
+
+
+
+
+
+
+ //------------------------------------------------------------------------
+ unsigned platform_specific::translate(unsigned keycode)
+ {
+ return m_last_translated_key = (keycode > 255) ? 0 : m_keymap[keycode];
+ }
+
+
+
+ //------------------------------------------------------------------------
+ platform_support::platform_support(pix_format_e format, bool flip_y) :
+ m_specific(new platform_specific(format, flip_y)),
+ m_format(format),
+ m_bpp(m_specific->m_bpp),
+ m_window_flags(0),
+ m_wait_mode(true),
+ m_flip_y(flip_y),
+ m_initial_width(10),
+ m_initial_height(10)
+ {
+ strcpy(m_caption, "Anti-Grain Geometry Application");
+ }
+
+
+ //------------------------------------------------------------------------
+ platform_support::~platform_support()
+ {
+ delete m_specific;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void platform_support::caption(const char* cap)
+ {
+ strcpy(m_caption, cap);
+ if(m_specific->m_hwnd)
+ {
+ SetWindowTextA(m_specific->m_hwnd, m_caption);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ void platform_support::start_timer()
+ {
+ ::QueryPerformanceCounter(&(m_specific->m_sw_start));
+ }
+
+ //------------------------------------------------------------------------
+ double platform_support::elapsed_time() const
+ {
+ LARGE_INTEGER stop;
+ ::QueryPerformanceCounter(&stop);
+ return double(stop.QuadPart -
+ m_specific->m_sw_start.QuadPart) * 1000.0 /
+ double(m_specific->m_sw_freq.QuadPart);
+ }
+
+
+
+ //------------------------------------------------------------------------
+ static unsigned get_key_flags(int wflags)
+ {
+ unsigned flags = 0;
+ if(wflags & MK_LBUTTON) flags |= mouse_left;
+ if(wflags & MK_RBUTTON) flags |= mouse_right;
+ if(wflags & MK_SHIFT) flags |= kbd_shift;
+ if(wflags & MK_CONTROL) flags |= kbd_ctrl;
+ return flags;
+ }
+
+
+ void* platform_support::raw_display_handler()
+ {
+ return m_specific->m_current_dc;
+ }
+
+
+ //------------------------------------------------------------------------
+ LRESULT CALLBACK window_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ PAINTSTRUCT ps;
+ HDC paintDC;
+
+
+ void* user_data = reinterpret_cast<void*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ platform_support* app = 0;
+
+ if(user_data)
+ {
+ app = reinterpret_cast<platform_support*>(user_data);
+ }
+
+ if(app == 0)
+ {
+ if(msg == WM_DESTROY)
+ {
+ ::PostQuitMessage(0);
+ return 0;
+ }
+ return ::DefWindowProc(hWnd, msg, wParam, lParam);
+ }
+
+ HDC dc = ::GetDC(app->m_specific->m_hwnd);
+ app->m_specific->m_current_dc = dc;
+ LRESULT ret = 0;
+
+ switch(msg)
+ {
+ //--------------------------------------------------------------------
+ case WM_CREATE:
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_SIZE:
+ app->m_specific->create_pmap(LOWORD(lParam),
+ HIWORD(lParam),
+ &app->rbuf_window());
+
+ app->trans_affine_resizing(LOWORD(lParam), HIWORD(lParam));
+ app->on_resize(LOWORD(lParam), HIWORD(lParam));
+ app->force_redraw();
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_ERASEBKGND:
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_LBUTTONDOWN:
+ ::SetCapture(app->m_specific->m_hwnd);
+ app->m_specific->m_cur_x = int16(LOWORD(lParam));
+ if(app->flip_y())
+ {
+ app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam));
+ }
+ else
+ {
+ app->m_specific->m_cur_y = int16(HIWORD(lParam));
+ }
+ app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam);
+
+ app->m_ctrls.set_cur(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y);
+ if(app->m_ctrls.on_mouse_button_down(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y))
+ {
+ app->on_ctrl_change();
+ app->force_redraw();
+ }
+ else
+ {
+ if(app->m_ctrls.in_rect(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y))
+ {
+ if(app->m_ctrls.set_cur(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y))
+ {
+ app->on_ctrl_change();
+ app->force_redraw();
+ }
+ }
+ else
+ {
+ app->on_mouse_button_down(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ app->m_specific->m_input_flags);
+ }
+ }
+/*
+ if(!app->wait_mode())
+ {
+ app->on_idle();
+ }
+*/
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_LBUTTONUP:
+ ::ReleaseCapture();
+ app->m_specific->m_cur_x = int16(LOWORD(lParam));
+ if(app->flip_y())
+ {
+ app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam));
+ }
+ else
+ {
+ app->m_specific->m_cur_y = int16(HIWORD(lParam));
+ }
+ app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam);
+
+ if(app->m_ctrls.on_mouse_button_up(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y))
+ {
+ app->on_ctrl_change();
+ app->force_redraw();
+ }
+ app->on_mouse_button_up(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ app->m_specific->m_input_flags);
+/*
+ if(!app->wait_mode())
+ {
+ app->on_idle();
+ }
+*/
+ break;
+
+
+ //--------------------------------------------------------------------
+ case WM_RBUTTONDOWN:
+ ::SetCapture(app->m_specific->m_hwnd);
+ app->m_specific->m_cur_x = int16(LOWORD(lParam));
+ if(app->flip_y())
+ {
+ app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam));
+ }
+ else
+ {
+ app->m_specific->m_cur_y = int16(HIWORD(lParam));
+ }
+ app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam);
+ app->on_mouse_button_down(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ app->m_specific->m_input_flags);
+/*
+ if(!app->wait_mode())
+ {
+ app->on_idle();
+ }
+*/
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_RBUTTONUP:
+ ::ReleaseCapture();
+ app->m_specific->m_cur_x = int16(LOWORD(lParam));
+ if(app->flip_y())
+ {
+ app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam));
+ }
+ else
+ {
+ app->m_specific->m_cur_y = int16(HIWORD(lParam));
+ }
+ app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam);
+ app->on_mouse_button_up(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ app->m_specific->m_input_flags);
+/*
+ if(!app->wait_mode())
+ {
+ app->on_idle();
+ }
+*/
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_MOUSEMOVE:
+ app->m_specific->m_cur_x = int16(LOWORD(lParam));
+ if(app->flip_y())
+ {
+ app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam));
+ }
+ else
+ {
+ app->m_specific->m_cur_y = int16(HIWORD(lParam));
+ }
+ app->m_specific->m_input_flags = get_key_flags(wParam);
+
+
+ if(app->m_ctrls.on_mouse_move(
+ app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ (app->m_specific->m_input_flags & mouse_left) != 0))
+ {
+ app->on_ctrl_change();
+ app->force_redraw();
+ }
+ else
+ {
+ if(!app->m_ctrls.in_rect(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y))
+ {
+ app->on_mouse_move(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ app->m_specific->m_input_flags);
+ }
+ }
+/*
+ if(!app->wait_mode())
+ {
+ app->on_idle();
+ }
+*/
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ app->m_specific->m_last_translated_key = 0;
+ switch(wParam)
+ {
+ case VK_CONTROL:
+ app->m_specific->m_input_flags |= kbd_ctrl;
+ break;
+
+ case VK_SHIFT:
+ app->m_specific->m_input_flags |= kbd_shift;
+ break;
+
+ default:
+ app->m_specific->translate(wParam);
+ break;
+ }
+
+ if(app->m_specific->m_last_translated_key)
+ {
+ bool left = false;
+ bool up = false;
+ bool right = false;
+ bool down = false;
+
+ switch(app->m_specific->m_last_translated_key)
+ {
+ case key_left:
+ left = true;
+ break;
+
+ case key_up:
+ up = true;
+ break;
+
+ case key_right:
+ right = true;
+ break;
+
+ case key_down:
+ down = true;
+ break;
+
+ case key_f2:
+ app->copy_window_to_img(agg::platform_support::max_images - 1);
+ app->save_img(agg::platform_support::max_images - 1, "screenshot");
+ break;
+ }
+
+ if(app->window_flags() & window_process_all_keys)
+ {
+ app->on_key(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ app->m_specific->m_last_translated_key,
+ app->m_specific->m_input_flags);
+ }
+ else
+ {
+ if(app->m_ctrls.on_arrow_keys(left, right, down, up))
+ {
+ app->on_ctrl_change();
+ app->force_redraw();
+ }
+ else
+ {
+ app->on_key(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ app->m_specific->m_last_translated_key,
+ app->m_specific->m_input_flags);
+ }
+ }
+ }
+/*
+ if(!app->wait_mode())
+ {
+ app->on_idle();
+ }
+*/
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ app->m_specific->m_last_translated_key = 0;
+ switch(wParam)
+ {
+ case VK_CONTROL:
+ app->m_specific->m_input_flags &= ~kbd_ctrl;
+ break;
+
+ case VK_SHIFT:
+ app->m_specific->m_input_flags &= ~kbd_shift;
+ break;
+ }
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ if(app->m_specific->m_last_translated_key == 0)
+ {
+ app->on_key(app->m_specific->m_cur_x,
+ app->m_specific->m_cur_y,
+ wParam,
+ app->m_specific->m_input_flags);
+ }
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_PAINT:
+ paintDC = ::BeginPaint(hWnd, &ps);
+ app->m_specific->m_current_dc = paintDC;
+ if(app->m_specific->m_redraw_flag)
+ {
+ app->on_draw();
+ app->m_specific->m_redraw_flag = false;
+ }
+ app->m_specific->display_pmap(paintDC, &app->rbuf_window());
+ app->on_post_draw(paintDC);
+ app->m_specific->m_current_dc = 0;
+ ::EndPaint(hWnd, &ps);
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_COMMAND:
+ break;
+
+ //--------------------------------------------------------------------
+ case WM_DESTROY:
+ ::PostQuitMessage(0);
+ break;
+
+ //--------------------------------------------------------------------
+ default:
+ ret = ::DefWindowProc(hWnd, msg, wParam, lParam);
+ break;
+ }
+ app->m_specific->m_current_dc = 0;
+ ::ReleaseDC(app->m_specific->m_hwnd, dc);
+ return ret;
+ }
+
+
+ //------------------------------------------------------------------------
+ void platform_support::message(const char* msg)
+ {
+ ::MessageBoxA(m_specific->m_hwnd, msg, "AGG Message", MB_OK);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool platform_support::init(unsigned width, unsigned height, unsigned flags)
+ {
+ if(m_specific->m_sys_format == pix_format_undefined)
+ {
+ return false;
+ }
+
+ m_window_flags = flags;
+
+ int wflags = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
+
+ WNDCLASSA wc;
+ wc.lpszClassName = "AGGAppClass";
+ wc.lpfnWndProc = window_proc;
+ wc.style = wflags;
+ wc.hInstance = g_windows_instance;
+ wc.hIcon = LoadIcon(0, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(0, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wc.lpszMenuName = "AGGAppMenu";
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ ::RegisterClassA(&wc);
+
+ wflags = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+
+ if(m_window_flags & window_resize)
+ {
+ wflags |= WS_THICKFRAME | WS_MAXIMIZEBOX;
+ }
+
+ m_specific->m_hwnd = ::CreateWindowA("AGGAppClass",
+ m_caption,
+ wflags,
+ 100,
+ 100,
+ width,
+ height,
+ 0,
+ 0,
+ g_windows_instance,
+ 0);
+
+ if(m_specific->m_hwnd == 0)
+ {
+ return false;
+ }
+
+
+ RECT rct;
+ ::GetClientRect(m_specific->m_hwnd, &rct);
+
+ ::MoveWindow(m_specific->m_hwnd, // handle to window
+ 100, // horizontal position
+ 100, // vertical position
+ width + (width - (rct.right - rct.left)),
+ height + (height - (rct.bottom - rct.top)),
+ FALSE);
+
+ ::SetWindowLongPtr(m_specific->m_hwnd, GWLP_USERDATA, (LONG)this);
+ m_specific->create_pmap(width, height, &m_rbuf_window);
+ m_initial_width = width;
+ m_initial_height = height;
+ on_init();
+ m_specific->m_redraw_flag = true;
+ ::ShowWindow(m_specific->m_hwnd, g_windows_cmd_show);
+ return true;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ int platform_support::run()
+ {
+ MSG msg;
+
+ for(;;)
+ {
+ if(m_wait_mode)
+ {
+ if(!::GetMessage(&msg, 0, 0, 0))
+ {
+ break;
+ }
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+ else
+ {
+ if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ ::TranslateMessage(&msg);
+ if(msg.message == WM_QUIT)
+ {
+ break;
+ }
+ ::DispatchMessage(&msg);
+ }
+ else
+ {
+ on_idle();
+ }
+ }
+ }
+ return (int)msg.wParam;
+ }
+
+
+ //------------------------------------------------------------------------
+ const char* platform_support::img_ext() const { return ".bmp"; }
+
+
+ //------------------------------------------------------------------------
+ const char* platform_support::full_file_name(const char* file_name)
+ {
+ return file_name;
+ }
+
+ //------------------------------------------------------------------------
+ bool platform_support::load_img(unsigned idx, const char* file)
+ {
+ if(idx < max_images)
+ {
+ char fn[1024];
+ strcpy(fn, file);
+ int len = strlen(fn);
+ if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0)
+ {
+ strcat(fn, ".bmp");
+ }
+ return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]);
+ }
+ return true;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool platform_support::save_img(unsigned idx, const char* file)
+ {
+ if(idx < max_images)
+ {
+ char fn[1024];
+ strcpy(fn, file);
+ int len = strlen(fn);
+ if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0)
+ {
+ strcat(fn, ".bmp");
+ }
+ return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]);
+ }
+ return true;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool platform_support::create_img(unsigned idx, unsigned width, unsigned height)
+ {
+ if(idx < max_images)
+ {
+ if(width == 0) width = m_specific->m_pmap_window.width();
+ if(height == 0) height = m_specific->m_pmap_window.height();
+ m_specific->m_pmap_img[idx].create(width, height, org_e(m_specific->m_bpp));
+ m_rbuf_img[idx].attach(m_specific->m_pmap_img[idx].buf(),
+ m_specific->m_pmap_img[idx].width(),
+ m_specific->m_pmap_img[idx].height(),
+ m_flip_y ?
+ m_specific->m_pmap_img[idx].stride() :
+ -m_specific->m_pmap_img[idx].stride());
+ return true;
+ }
+ return false;
+ }
+
+
+ //------------------------------------------------------------------------
+ void platform_support::force_redraw()
+ {
+ m_specific->m_redraw_flag = true;
+ ::InvalidateRect(m_specific->m_hwnd, 0, FALSE);
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void platform_support::update_window()
+ {
+ HDC dc = ::GetDC(m_specific->m_hwnd);
+ m_specific->display_pmap(dc, &m_rbuf_window);
+ ::ReleaseDC(m_specific->m_hwnd, dc);
+ }
+
+
+ //------------------------------------------------------------------------
+ void platform_support::on_init() {}
+ void platform_support::on_resize(int sx, int sy) {}
+ void platform_support::on_idle() {}
+ void platform_support::on_mouse_move(int x, int y, unsigned flags) {}
+ void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {}
+ void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {}
+ void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {}
+ void platform_support::on_ctrl_change() {}
+ void platform_support::on_draw() {}
+ void platform_support::on_post_draw(void* raw_handler) {}
+}
+
+
+
+
+namespace agg
+{
+ // That's ridiculous. I have to parse the command line by myself
+ // because Windows doesn't provide a method of getting the command
+ // line arguments in a form of argc, argv. Of course, there's
+ // CommandLineToArgv() but first, it returns Unicode that I don't
+ // need to deal with, but most of all, it's not compatible with Win98.
+ //-----------------------------------------------------------------------
+ class tokenizer
+ {
+ public:
+ enum sep_flag
+ {
+ single,
+ multiple,
+ whole_str
+ };
+
+ struct token
+ {
+ const char* ptr;
+ unsigned len;
+ };
+
+ public:
+ tokenizer(const char* sep,
+ const char* trim=0,
+ const char* quote="\"",
+ char mask_chr='\\',
+ sep_flag sf=multiple);
+
+ void set_str(const char* str);
+ token next_token();
+
+ private:
+ int check_chr(const char *str, char chr);
+
+ private:
+ const char* m_src_string;
+ int m_start;
+ const char* m_sep;
+ const char* m_trim;
+ const char* m_quote;
+ char m_mask_chr;
+ unsigned m_sep_len;
+ sep_flag m_sep_flag;
+ };
+
+
+
+ //-----------------------------------------------------------------------
+ inline void tokenizer::set_str(const char* str)
+ {
+ m_src_string = str;
+ m_start = 0;
+ }
+
+
+ //-----------------------------------------------------------------------
+ inline int tokenizer::check_chr(const char *str, char chr)
+ {
+ return int(strchr(str, chr));
+ }
+
+
+ //-----------------------------------------------------------------------
+ tokenizer::tokenizer(const char* sep,
+ const char* trim,
+ const char* quote,
+ char mask_chr,
+ sep_flag sf) :
+ m_src_string(0),
+ m_start(0),
+ m_sep(sep),
+ m_trim(trim),
+ m_quote(quote),
+ m_mask_chr(mask_chr),
+ m_sep_len(sep ? strlen(sep) : 0),
+ m_sep_flag(sep ? sf : single)
+ {
+ }
+
+
+ //-----------------------------------------------------------------------
+ tokenizer::token tokenizer::next_token()
+ {
+ unsigned count = 0;
+ char quote_chr = 0;
+ token tok;
+
+ tok.ptr = 0;
+ tok.len = 0;
+ if(m_src_string == 0 || m_start == -1) return tok;
+
+ register const char *pstr = m_src_string + m_start;
+
+ if(*pstr == 0)
+ {
+ m_start = -1;
+ return tok;
+ }
+
+ int sep_len = 1;
+ if(m_sep_flag == whole_str) sep_len = m_sep_len;
+
+ if(m_sep_flag == multiple)
+ {
+ //Pass all the separator symbols at the begin of the string
+ while(*pstr && check_chr(m_sep, *pstr))
+ {
+ ++pstr;
+ ++m_start;
+ }
+ }
+
+ if(*pstr == 0)
+ {
+ m_start = -1;
+ return tok;
+ }
+
+ for(count = 0;; ++count)
+ {
+ char c = *pstr;
+ int found = 0;
+
+ //We are outside of qotation: find one of separator symbols
+ if(quote_chr == 0)
+ {
+ if(sep_len == 1)
+ {
+ found = check_chr(m_sep, c);
+ }
+ else
+ {
+ found = strncmp(m_sep, pstr, m_sep_len) == 0;
+ }
+ }
+
+ ++pstr;
+
+ if(c == 0 || found)
+ {
+ if(m_trim)
+ {
+ while(count &&
+ check_chr(m_trim, m_src_string[m_start]))
+ {
+ ++m_start;
+ --count;
+ }
+
+ while(count &&
+ check_chr(m_trim, m_src_string[m_start + count - 1]))
+ {
+ --count;
+ }
+ }
+
+ tok.ptr = m_src_string + m_start;
+ tok.len = count;
+
+ //Next time it will be the next separator character
+ //But we must check, whether it is NOT the end of the string.
+ m_start += count;
+ if(c)
+ {
+ m_start += sep_len;
+ if(m_sep_flag == multiple)
+ {
+ //Pass all the separator symbols
+ //after the end of the string
+ while(check_chr(m_sep, m_src_string[m_start]))
+ {
+ ++m_start;
+ }
+ }
+ }
+ break;
+ }
+
+ //Switch quote. If it is not a quote yet, try to check any of
+ //quote symbols. Otherwise quote must be finished with quote_symb
+ if(quote_chr == 0)
+ {
+ if(check_chr(m_quote, c))
+ {
+ quote_chr = c;
+ continue;
+ }
+ }
+ else
+ {
+ //We are inside quote: pass all the mask symbols
+ if(m_mask_chr && c == m_mask_chr)
+ {
+ if(*pstr)
+ {
+ ++count;
+ ++pstr;
+ }
+ continue;
+ }
+ if(c == quote_chr)
+ {
+ quote_chr = 0;
+ continue;
+ }
+ }
+ }
+ return tok;
+ }
+
+
+}
+
+
+
+//----------------------------------------------------------------------------
+int agg_main(int argc, char* argv[]);
+
+
+
+//----------------------------------------------------------------------------
+int PASCAL WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine,
+ int nCmdShow)
+{
+ agg::g_windows_instance = hInstance;
+ agg::g_windows_cmd_show = nCmdShow;
+
+ char* argv_str = new char [strlen(lpszCmdLine) + 3];
+ char* argv_ptr = argv_str;
+
+ char* argv[64];
+ memset(argv, 0, sizeof(argv));
+
+ agg::tokenizer cmd_line(" ", "\"' ", "\"'", '\\', agg::tokenizer::multiple);
+ cmd_line.set_str(lpszCmdLine);
+
+ int argc = 0;
+ argv[argc++] = argv_ptr;
+ *argv_ptr++ = 0;
+
+ while(argc < 64)
+ {
+ agg::tokenizer::token tok = cmd_line.next_token();
+ if(tok.ptr == 0) break;
+ if(tok.len)
+ {
+ memcpy(argv_ptr, tok.ptr, tok.len);
+ argv[argc++] = argv_ptr;
+ argv_ptr += tok.len;
+ *argv_ptr++ = 0;
+ }
+ }
+
+ int ret = agg_main(argc, argv);
+ delete [] argv_str;
+
+ return ret;
+}
+
+
+
+
diff --git a/plugins/Clist_ng/AGG/src/platform/win32/agg_win32_bmp.cpp b/plugins/Clist_ng/AGG/src/platform/win32/agg_win32_bmp.cpp new file mode 100644 index 0000000000..249eac9470 --- /dev/null +++ b/plugins/Clist_ng/AGG/src/platform/win32/agg_win32_bmp.cpp @@ -0,0 +1,625 @@ +//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+// Contact: mcseemagg@yahoo.com
+//----------------------------------------------------------------------------
+//
+// class pixel_map
+//
+//----------------------------------------------------------------------------
+
+#include "platform/win32/agg_win32_bmp.h"
+#include "agg_basics.h"
+
+namespace agg
+{
+
+ //------------------------------------------------------------------------
+ pixel_map::~pixel_map()
+ {
+ destroy();
+ }
+
+
+ //------------------------------------------------------------------------
+ pixel_map::pixel_map() :
+ m_bmp(0),
+ m_buf(0),
+ m_bpp(0),
+ m_is_internal(false),
+ m_img_size(0),
+ m_full_size(0)
+
+ {
+ }
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::destroy()
+ {
+ if(m_bmp && m_is_internal) delete [] (unsigned char*)m_bmp;
+ m_bmp = 0;
+ m_is_internal = false;
+ m_buf = 0;
+ }
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::create(unsigned width,
+ unsigned height,
+ org_e org,
+ unsigned clear_val)
+ {
+ destroy();
+ if(width == 0) width = 1;
+ if(height == 0) height = 1;
+ m_bpp = org;
+ create_from_bmp(create_bitmap_info(width, height, m_bpp));
+ create_gray_scale_palette(m_bmp);
+ m_is_internal = true;
+ if(clear_val <= 255)
+ {
+ memset(m_buf, clear_val, m_img_size);
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ HBITMAP pixel_map::create_dib_section(HDC h_dc,
+ unsigned width,
+ unsigned height,
+ org_e org,
+ unsigned clear_val)
+ {
+ destroy();
+ if(width == 0) width = 1;
+ if(height == 0) height = 1;
+ m_bpp = org;
+ HBITMAP h_bitmap = create_dib_section_from_args(h_dc, width, height, m_bpp);
+ create_gray_scale_palette(m_bmp);
+ m_is_internal = true;
+ if(clear_val <= 255)
+ {
+ memset(m_buf, clear_val, m_img_size);
+ }
+ return h_bitmap;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::clear(unsigned clear_val)
+ {
+ if(m_buf) memset(m_buf, clear_val, m_img_size);
+ }
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::attach_to_bmp(BITMAPINFO *bmp)
+ {
+ if(bmp)
+ {
+ destroy();
+ create_from_bmp(bmp);
+ m_is_internal = false;
+ }
+ }
+
+
+
+ //static
+ //------------------------------------------------------------------------
+ unsigned pixel_map::calc_full_size(BITMAPINFO *bmp)
+ {
+ if(bmp == 0) return 0;
+
+ return sizeof(BITMAPINFOHEADER) +
+ sizeof(RGBQUAD) * calc_palette_size(bmp) +
+ bmp->bmiHeader.biSizeImage;
+ }
+
+ //static
+ //------------------------------------------------------------------------
+ unsigned pixel_map::calc_header_size(BITMAPINFO *bmp)
+ {
+ if(bmp == 0) return 0;
+ return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * calc_palette_size(bmp);
+ }
+
+
+ //static
+ //------------------------------------------------------------------------
+ unsigned pixel_map::calc_palette_size(unsigned clr_used, unsigned bits_per_pixel)
+ {
+ int palette_size = 0;
+
+ if(bits_per_pixel <= 8)
+ {
+ palette_size = clr_used;
+ if(palette_size == 0)
+ {
+ palette_size = 1 << bits_per_pixel;
+ }
+ }
+ return palette_size;
+ }
+
+ //static
+ //------------------------------------------------------------------------
+ unsigned pixel_map::calc_palette_size(BITMAPINFO *bmp)
+ {
+ if(bmp == 0) return 0;
+ return calc_palette_size(bmp->bmiHeader.biClrUsed, bmp->bmiHeader.biBitCount);
+ }
+
+
+ //static
+ //------------------------------------------------------------------------
+ unsigned char * pixel_map::calc_img_ptr(BITMAPINFO *bmp)
+ {
+ if(bmp == 0) return 0;
+ return ((unsigned char*)bmp) + calc_header_size(bmp);
+ }
+
+ //static
+ //------------------------------------------------------------------------
+ BITMAPINFO* pixel_map::create_bitmap_info(unsigned width,
+ unsigned height,
+ unsigned bits_per_pixel)
+ {
+ unsigned line_len = calc_row_len(width, bits_per_pixel);
+ unsigned img_size = line_len * height;
+ unsigned rgb_size = calc_palette_size(0, bits_per_pixel) * sizeof(RGBQUAD);
+ unsigned full_size = sizeof(BITMAPINFOHEADER) + rgb_size + img_size;
+
+ BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size];
+
+ bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmp->bmiHeader.biWidth = width;
+ bmp->bmiHeader.biHeight = height;
+ bmp->bmiHeader.biPlanes = 1;
+ bmp->bmiHeader.biBitCount = (unsigned short)bits_per_pixel;
+ bmp->bmiHeader.biCompression = 0;
+ bmp->bmiHeader.biSizeImage = img_size;
+ bmp->bmiHeader.biXPelsPerMeter = 0;
+ bmp->bmiHeader.biYPelsPerMeter = 0;
+ bmp->bmiHeader.biClrUsed = 0;
+ bmp->bmiHeader.biClrImportant = 0;
+
+ return bmp;
+ }
+
+
+ //static
+ //------------------------------------------------------------------------
+ void pixel_map::create_gray_scale_palette(BITMAPINFO *bmp)
+ {
+ if(bmp == 0) return;
+
+ unsigned rgb_size = calc_palette_size(bmp);
+ RGBQUAD *rgb = (RGBQUAD*)(((unsigned char*)bmp) + sizeof(BITMAPINFOHEADER));
+ unsigned brightness;
+ unsigned i;
+
+ for(i = 0; i < rgb_size; i++)
+ {
+ brightness = (255 * i) / (rgb_size - 1);
+ rgb->rgbBlue =
+ rgb->rgbGreen =
+ rgb->rgbRed = (unsigned char)brightness;
+ rgb->rgbReserved = 0;
+ rgb++;
+ }
+ }
+
+
+
+ //static
+ //------------------------------------------------------------------------
+ unsigned pixel_map::calc_row_len(unsigned width, unsigned bits_per_pixel)
+ {
+ unsigned n = width;
+ unsigned k;
+
+ switch(bits_per_pixel)
+ {
+ case 1: k = n;
+ n = n >> 3;
+ if(k & 7) n++;
+ break;
+
+ case 4: k = n;
+ n = n >> 1;
+ if(k & 3) n++;
+ break;
+
+ case 8:
+ break;
+
+ case 16: n *= 2;
+ break;
+
+ case 24: n *= 3;
+ break;
+
+ case 32: n *= 4;
+ break;
+
+ case 48: n *= 6;
+ break;
+
+ case 64: n *= 8;
+ break;
+
+ default: n = 0;
+ break;
+ }
+ return ((n + 3) >> 2) << 2;
+ }
+
+
+
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::draw(HDC h_dc, const RECT *device_rect, const RECT *bmp_rect) const
+ {
+ if(m_bmp == 0 || m_buf == 0) return;
+
+ unsigned bmp_x = 0;
+ unsigned bmp_y = 0;
+ unsigned bmp_width = m_bmp->bmiHeader.biWidth;
+ unsigned bmp_height = m_bmp->bmiHeader.biHeight;
+ unsigned dvc_x = 0;
+ unsigned dvc_y = 0;
+ unsigned dvc_width = m_bmp->bmiHeader.biWidth;
+ unsigned dvc_height = m_bmp->bmiHeader.biHeight;
+
+ if(bmp_rect)
+ {
+ bmp_x = bmp_rect->left;
+ bmp_y = bmp_rect->top;
+ bmp_width = bmp_rect->right - bmp_rect->left;
+ bmp_height = bmp_rect->bottom - bmp_rect->top;
+ }
+
+ dvc_x = bmp_x;
+ dvc_y = bmp_y;
+ dvc_width = bmp_width;
+ dvc_height = bmp_height;
+
+ if(device_rect)
+ {
+ dvc_x = device_rect->left;
+ dvc_y = device_rect->top;
+ dvc_width = device_rect->right - device_rect->left;
+ dvc_height = device_rect->bottom - device_rect->top;
+ }
+
+ if(dvc_width != bmp_width || dvc_height != bmp_height)
+ {
+ ::SetStretchBltMode(h_dc, COLORONCOLOR);
+ ::StretchDIBits(
+ h_dc, // handle of device context
+ dvc_x, // x-coordinate of upper-left corner of source rect.
+ dvc_y, // y-coordinate of upper-left corner of source rect.
+ dvc_width, // width of source rectangle
+ dvc_height, // height of source rectangle
+ bmp_x,
+ bmp_y, // x, y -coordinates of upper-left corner of dest. rect.
+ bmp_width, // width of destination rectangle
+ bmp_height, // height of destination rectangle
+ m_buf, // address of bitmap bits
+ m_bmp, // address of bitmap data
+ DIB_RGB_COLORS, // usage
+ SRCCOPY // raster operation code
+ );
+ }
+ else
+ {
+ ::SetDIBitsToDevice(
+ h_dc, // handle to device context
+ dvc_x, // x-coordinate of upper-left corner of
+ dvc_y, // y-coordinate of upper-left corner of
+ dvc_width, // source rectangle width
+ dvc_height, // source rectangle height
+ bmp_x, // x-coordinate of lower-left corner of
+ bmp_y, // y-coordinate of lower-left corner of
+ 0, // first scan line in array
+ bmp_height, // number of scan lines
+ m_buf, // address of array with DIB bits
+ m_bmp, // address of structure with bitmap info.
+ DIB_RGB_COLORS // RGB or palette indexes
+ );
+ }
+ }
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::draw(HDC h_dc, int x, int y, double scale) const
+ {
+ if(m_bmp == 0 || m_buf == 0) return;
+
+ unsigned width = unsigned(m_bmp->bmiHeader.biWidth * scale);
+ unsigned height = unsigned(m_bmp->bmiHeader.biHeight * scale);
+ RECT rect;
+ rect.left = x;
+ rect.top = y;
+ rect.right = x + width;
+ rect.bottom = y + height;
+ draw(h_dc, &rect);
+ }
+
+
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::blend(HDC h_dc, const RECT *device_rect, const RECT *bmp_rect) const
+ {
+#if !defined(AGG_BMP_ALPHA_BLEND)
+ draw(h_dc, device_rect, bmp_rect);
+ return;
+#else
+ if(m_bpp != 32)
+ {
+ draw(h_dc, device_rect, bmp_rect);
+ return;
+ }
+
+ if(m_bmp == 0 || m_buf == 0) return;
+
+ unsigned bmp_x = 0;
+ unsigned bmp_y = 0;
+ unsigned bmp_width = m_bmp->bmiHeader.biWidth;
+ unsigned bmp_height = m_bmp->bmiHeader.biHeight;
+ unsigned dvc_x = 0;
+ unsigned dvc_y = 0;
+ unsigned dvc_width = m_bmp->bmiHeader.biWidth;
+ unsigned dvc_height = m_bmp->bmiHeader.biHeight;
+
+ if(bmp_rect)
+ {
+ bmp_x = bmp_rect->left;
+ bmp_y = bmp_rect->top;
+ bmp_width = bmp_rect->right - bmp_rect->left;
+ bmp_height = bmp_rect->bottom - bmp_rect->top;
+ }
+
+ dvc_x = bmp_x;
+ dvc_y = bmp_y;
+ dvc_width = bmp_width;
+ dvc_height = bmp_height;
+
+ if(device_rect)
+ {
+ dvc_x = device_rect->left;
+ dvc_y = device_rect->top;
+ dvc_width = device_rect->right - device_rect->left;
+ dvc_height = device_rect->bottom - device_rect->top;
+ }
+
+ HDC mem_dc = ::CreateCompatibleDC(h_dc);
+ void* buf = 0;
+ HBITMAP bmp = ::CreateDIBSection(
+ mem_dc,
+ m_bmp,
+ DIB_RGB_COLORS,
+ &buf,
+ 0,
+ 0
+ );
+ memcpy(buf, m_buf, m_bmp->bmiHeader.biSizeImage);
+
+ HBITMAP temp = (HBITMAP)::SelectObject(mem_dc, bmp);
+
+ BLENDFUNCTION blend;
+ blend.BlendOp = AC_SRC_OVER;
+ blend.BlendFlags = 0;
+
+#if defined(AC_SRC_ALPHA)
+ blend.AlphaFormat = AC_SRC_ALPHA;
+//#elif defined(AC_SRC_NO_PREMULT_ALPHA)
+// blend.AlphaFormat = AC_SRC_NO_PREMULT_ALPHA;
+#else
+#error "No appropriate constant for alpha format. Check version of wingdi.h, There must be AC_SRC_ALPHA or AC_SRC_NO_PREMULT_ALPHA"
+#endif
+
+ blend.SourceConstantAlpha = 255;
+ ::AlphaBlend(
+ h_dc,
+ dvc_x,
+ dvc_y,
+ dvc_width,
+ dvc_height,
+ mem_dc,
+ bmp_x,
+ bmp_y,
+ bmp_width,
+ bmp_height,
+ blend
+ );
+
+ ::SelectObject(mem_dc, temp);
+ ::DeleteObject(bmp);
+ ::DeleteObject(mem_dc);
+#endif //defined(AGG_BMP_ALPHA_BLEND)
+ }
+
+
+ //------------------------------------------------------------------------
+ void pixel_map::blend(HDC h_dc, int x, int y, double scale) const
+ {
+ if(m_bmp == 0 || m_buf == 0) return;
+ unsigned width = unsigned(m_bmp->bmiHeader.biWidth * scale);
+ unsigned height = unsigned(m_bmp->bmiHeader.biHeight * scale);
+ RECT rect;
+ rect.left = x;
+ rect.top = y;
+ rect.right = x + width;
+ rect.bottom = y + height;
+ blend(h_dc, &rect);
+ }
+
+
+ //------------------------------------------------------------------------
+ bool pixel_map::load_from_bmp(FILE *fd)
+ {
+ BITMAPFILEHEADER bmf;
+ BITMAPINFO *bmi = 0;
+ unsigned bmp_size;
+
+ fread(&bmf, sizeof(bmf), 1, fd);
+ if(bmf.bfType != 0x4D42) goto bmperr;
+
+ bmp_size = bmf.bfSize - sizeof(BITMAPFILEHEADER);
+
+ bmi = (BITMAPINFO*) new unsigned char [bmp_size];
+ if(fread(bmi, 1, bmp_size, fd) != bmp_size) goto bmperr;
+ destroy();
+ m_bpp = bmi->bmiHeader.biBitCount;
+ create_from_bmp(bmi);
+ m_is_internal = 1;
+ return true;
+
+ bmperr:
+ if(bmi) delete [] (unsigned char*) bmi;
+ return false;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool pixel_map::load_from_bmp(const char *filename)
+ {
+ FILE *fd = fopen(filename, "rb");
+ bool ret = false;
+ if(fd)
+ {
+ ret = load_from_bmp(fd);
+ fclose(fd);
+ }
+ return ret;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool pixel_map::save_as_bmp(FILE *fd) const
+ {
+ if(m_bmp == 0) return 0;
+
+ BITMAPFILEHEADER bmf;
+
+ bmf.bfType = 0x4D42;
+ bmf.bfOffBits = calc_header_size(m_bmp) + sizeof(bmf);
+ bmf.bfSize = bmf.bfOffBits + m_img_size;
+ bmf.bfReserved1 = 0;
+ bmf.bfReserved2 = 0;
+
+ fwrite(&bmf, sizeof(bmf), 1, fd);
+ fwrite(m_bmp, m_full_size, 1, fd);
+ return true;
+ }
+
+
+
+ //------------------------------------------------------------------------
+ bool pixel_map::save_as_bmp(const char *filename) const
+ {
+ FILE *fd = fopen(filename, "wb");
+ bool ret = false;
+ if(fd)
+ {
+ ret = save_as_bmp(fd);
+ fclose(fd);
+ }
+ return ret;
+ }
+
+
+ //------------------------------------------------------------------------
+ unsigned char* pixel_map::buf()
+ {
+ return m_buf;
+ }
+
+ //------------------------------------------------------------------------
+ unsigned pixel_map::width() const
+ {
+ return m_bmp->bmiHeader.biWidth;
+ }
+
+ //------------------------------------------------------------------------
+ unsigned pixel_map::height() const
+ {
+ return m_bmp->bmiHeader.biHeight;
+ }
+
+ //------------------------------------------------------------------------
+ int pixel_map::stride() const
+ {
+ return calc_row_len(m_bmp->bmiHeader.biWidth,
+ m_bmp->bmiHeader.biBitCount);
+ }
+
+
+ //private
+ //------------------------------------------------------------------------
+ void pixel_map::create_from_bmp(BITMAPINFO *bmp)
+ {
+ if(bmp)
+ {
+ m_img_size = calc_row_len(bmp->bmiHeader.biWidth,
+ bmp->bmiHeader.biBitCount) *
+ bmp->bmiHeader.biHeight;
+
+ m_full_size = calc_full_size(bmp);
+ m_bmp = bmp;
+ m_buf = calc_img_ptr(bmp);
+ }
+ }
+
+
+ //private
+ //------------------------------------------------------------------------
+ HBITMAP pixel_map::create_dib_section_from_args(HDC h_dc,
+ unsigned width,
+ unsigned height,
+ unsigned bits_per_pixel)
+ {
+ unsigned line_len = calc_row_len(width, bits_per_pixel);
+ unsigned img_size = line_len * height;
+ unsigned rgb_size = calc_palette_size(0, bits_per_pixel) * sizeof(RGBQUAD);
+ unsigned full_size = sizeof(BITMAPINFOHEADER) + rgb_size;
+
+ BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size];
+
+ bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmp->bmiHeader.biWidth = width;
+ bmp->bmiHeader.biHeight = height;
+ bmp->bmiHeader.biPlanes = 1;
+ bmp->bmiHeader.biBitCount = (unsigned short)bits_per_pixel;
+ bmp->bmiHeader.biCompression = 0;
+ bmp->bmiHeader.biSizeImage = img_size;
+ bmp->bmiHeader.biXPelsPerMeter = 0;
+ bmp->bmiHeader.biYPelsPerMeter = 0;
+ bmp->bmiHeader.biClrUsed = 0;
+ bmp->bmiHeader.biClrImportant = 0;
+
+ void* img_ptr = 0;
+ HBITMAP h_bitmap = ::CreateDIBSection(h_dc, bmp, DIB_RGB_COLORS, &img_ptr, NULL, 0);
+
+ if(img_ptr)
+ {
+ m_img_size = calc_row_len(width, bits_per_pixel) * height;
+ m_full_size = 0;
+ m_bmp = bmp;
+ m_buf = (unsigned char *) img_ptr;
+ }
+
+ return h_bitmap;
+ }
+}
+
+
+
diff --git a/plugins/Clist_ng/AGG/src/readme b/plugins/Clist_ng/AGG/src/readme new file mode 100644 index 0000000000..d565c28a6b --- /dev/null +++ b/plugins/Clist_ng/AGG/src/readme @@ -0,0 +1,5 @@ +Use automake to build the library.
+
+If automake is not available you still can use the old make.
+There is a very simple Makefile that can be used. Note that
+if you use automake it will overwrite Makefile.
diff --git a/plugins/Clist_ng/BASESKIN/AeroBack.png b/plugins/Clist_ng/BASESKIN/AeroBack.png Binary files differnew file mode 100644 index 0000000000..b52912971d --- /dev/null +++ b/plugins/Clist_ng/BASESKIN/AeroBack.png diff --git a/plugins/Clist_ng/BASESKIN/Back.png b/plugins/Clist_ng/BASESKIN/Back.png Binary files differnew file mode 100644 index 0000000000..4b3627d462 --- /dev/null +++ b/plugins/Clist_ng/BASESKIN/Back.png diff --git a/plugins/Clist_ng/BASESKIN/base.cng b/plugins/Clist_ng/BASESKIN/base.cng new file mode 100644 index 0000000000..4ff34cc440 --- /dev/null +++ b/plugins/Clist_ng/BASESKIN/base.cng @@ -0,0 +1,1443 @@ +[SkinInfo]
+Version=5
+Name=Base Skin for Clist NG
+
+; Frameless metrics describe the window metrics for the fully skinned mode where
+; no default window border or title bar is visible.
+; These values are left, right, top and bottom paddings.
+
+[FramelessMetrics]
+CLeft=0
+CRight=0
+CTop=0
+CBottom=2
+StatusBarHeight=22
+CaptionHeight=26
+LeftBorderWidth=5
+RightBorderWidth=5
+BottomBorderWidth=3
+
+; normal metrics, when a normal window border and title bar is present.
+
+[Metrics]
+CLeft=2
+CRight=2
+CTop=0
+CBottom=0
+
+[Settings]
+DefaultWindowStyle=3
+ButtonHeight=22
+
+[Buttonset]
+Top=24
+Left=0
+Right=0
+Bottom=0
+
+; Skinning the contact list items with IMAGES
+
+; 2. Image items
+; --------------
+;
+; image items are separated from the normal item definitions. This allows to
+; use a single image for multiple items. Images are optional, because the skinning
+; engine can work without them and draw skin items in a traditional way, using gradients
+; and such.
+;
+; images have to be 32bit PNG images - other formats are not supported. They can be
+; partially transparent using per-pixel alpha values.
+
+; Image item definitions MUST start with a $ character. The name is free - you can use
+; any name you want. The image filenames are RELATIVE to the location of the .cln file,
+; so the best solution would be to place them in the same directory as this skin definition
+; and then
+;
+; To define the contents of an image item, you can use either:
+;
+; Image=foo.png (use a separate image for this item)
+;
+; OR
+;
+; Glyph=left,top,right,bottom (extract the contents of the image from the $glyphs
+; item at the specified coordinates)
+;
+; sizing margins:
+;
+; sizing margins have to be specified as Left, Right, Top and Bottom. These margins
+; divide the image into 9 parts. The corner parts are rendered without stretching
+; or shrinking, other parts of the image are stretched to make it fit the target
+; area. Sizing margins are only valid and used when ALL 4 margin values are specified.
+;
+; ALPHA is a constant alpha value which is applied AFTER per pixel alpha values- this
+; can be used to make a non-transparent image translucent. Alpha values are in percent,
+; so the valid range is from 0 (completely transparent) to 100 (completely opaque).
+;
+; assign images to actual skin item(s).
+;
+; This is done with the ItemX=Itemname value. X is a 0-based index number, so the first
+; assignment has to be Item0=foo, the 2nd Item1=bar and so on. Itemname refers to one of
+; the skin item names listed at the beginning of this document, WITHOUT the % character.
+;
+; FillColor
+; This is a color value, which, if present, will be used to fill the inner part of the
+; target area. This can speed up rendering significantly and should be used when an image
+; item is covered by other parts and only the margins of the image are important.
+
+; $Window is a SPECIAL item - it is used to skin the contact list background and nothing
+; else. You can name it whatever you want, but you MUST assign it to the CLUI item.
+; Since clist_nicer+ is NOT a layered skinning engine, this picture should not use
+; partially transparent pixels. It can still use fully transparent pixels for implementing
+; rounded window corners.
+; Also, set the colorkey to a "rare" color (magenta #ff00ff is always a good choice) and
+; activate the full transparency option.
+; FillColor can be used to fill the inner part of the divided image with a solid color
+; this can speed up painting significantly.
+
+[$Window]
+Image=back.png
+Left=5
+Right=5
+Top=25
+Bottom=5
+Item0=CLUIAero
+Item1=CLUI
+Alpha=100
+Colorkey=ff00ff
+
+[$CluiClient]
+Glyph=1,108,33,126
+Right=3
+Top=3
+Bottom=3
+Left=3
+Alpha=80
+Item0=CLUIClient
+
+[$Frametitle]
+Glyph=0,0,37,24
+Item0=Frame titlebars
+Left=5
+Top=5
+Right=5
+Bottom=5
+Alpha=100
+
+[$Button]
+Glyph=1,62,35,82
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=100
+Item0=UI button normal
+
+[$Buttonhover]
+Glyph=0,85,36,105
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=100
+Item0=UI button hover
+
+[$Buttonpressed]
+Glyph=0,107,34,127
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=100
+Item0=UI button pressed
+
+[$FrameSkin]
+Glyph=0,129,38,140
+Right=3
+Top=3
+Bottom=3
+Left=3
+Alpha=100
+Item0=Frame border no titlebar
+FillColor=ffffff
+
+[$FrameSkinTB]
+Glyph=0,26,37,34
+Right=3
+Top=1
+Bottom=4
+Left=3
+Alpha=100
+Item0=Frame border with titlebar
+FillColor=ffffff
+
+[$Avatar]
+Glyph=88,24,107,39
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=80
+;Item0=Avatarframe
+
+[$Avataroffline]
+Glyph=88,0,107,20
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=50
+;Item0=Avatarframe offline
+
+; This is an independent image item. It is not connected to any skin item and can be used for
+; the buttons. Useful for things like defining a graphical window caption in skinned mode or
+; just give one single button a different look.
+
+[@BtnNormal]
+Glyph=64,0,83,20
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=50
+
+[@BtnHover]
+Glyph=64,22,83,42
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=100
+
+[@BtnPushed]
+Glyph=64,44,83,64
+Right=4
+Top=4
+Bottom=4
+Left=4
+Alpha=100
+
+[$Thumb]
+Glyph=0,142,17,158
+Right=6
+Top=5
+Bottom=5
+Left=5
+Alpha=100
+Item0=Scrollbar thumb
+
+[$Thumbpressed]
+Glyph=0,159,17,175
+Right=6
+Top=5
+Bottom=5
+Left=5
+Alpha=100
+Item0=Scrollbar thumb pressed
+Item1=Scrollbar thumb hovered
+
+[$Scrollback]
+Glyph=18,142,35,155
+Right=2
+Top=2
+Bottom=2
+Left=2
+Alpha=100
+Item0=Scrollbar backgroundupper
+Item1=Scrollbar backgroundlower
+Item2=Scrollbar button
+Item3=Scrollbar button pressed
+Item4=Scrollbar button hovered
+
+[$ScrollArrowUp]
+Glyph=18,167,28,175
+Right=2
+Top=2
+Bottom=2
+Left=2
+Alpha=100
+Item0=Scrollbar arrow up
+
+[$ScrollArrowDown]
+Glyph=18,157,28,165
+Right=2
+Top=2
+Bottom=2
+Left=2
+Alpha=100
+Item0=Scrollbar arrow down
+
+[$Groups]
+Glyph=0,215,31,233
+Left=5
+Right=5
+Top=5
+Bottom=5
+Item0=Expanded Group
+
+[$Selection]
+Glyph=63,65,84,87
+Alpha=50
+Left=3
+Top=3
+Right=3
+Bottom=3
+Item0=Selection
+
+[$Hottrack]
+Glyph=63,87,84,109
+Alpha=50
+Left=3
+Top=3
+Right=3
+Bottom=3
+Item0=Hottracked
+
+; all contacts share the same background image (could be different though) - even/odd rows
+; can be implemented on the background+ page by using the appropriate item(s).
+
+[$Contacts]
+Glyph=0,36,36,59
+Alpha=85
+left=1
+top=1
+right=1
+bottom=1
+Item0=Online
+Item1=Offline
+Item2=Away
+Item3=DND
+Item4=NA
+Item5=Occupied
+Item6=Invisible
+Item7=Free for chat
+Item8=Out to lunch
+Item9=On the phone
+;Fillcolor=DCDACE
+
+; Glyphs
+; ------
+; this is a special image item. It contains glyphs which can be used as image items.
+; This item is optional unless you are using button glyphs.
+
+; using a single image for all glpyhs may look strange at the first glance, but has a lot
+; of advantages performance-wise (people who have been working on mods for games may know
+; these technique for creating textures and collecting them in a single image file).
+
+[$glyphs]
+Image=glyphs.png
+Alpha=100
+
+; button definitions
+; * there can be as many buttons as you want
+; * name MUST start with a !
+; * to make room for the buttons, set the client margins on the Options->Contact List->Window
+; page (left, top, bottom, right) and MAKE SURE TO EXPORT the skin definition from the
+; Background+ page after you have set them. Doing so will export quite a few important
+; settings to the skin file.
+
+; The Pressed, Normal and Hover properties represent image items for the different button states
+; You can re-use image items of course, but if needed, every button can have its own
+;
+; xOff/yOff -> offset values from the left/top edge of the clist window. Use negative
+; values to specify offsets from the right or bottom
+;
+; Width/Height -> dimensions of the button
+
+; Action: can be one of:
+;
+; cln_* constants to replicate the clist_nicer+ internal toolbar buttons. See below for
+; valid cln_ constants.
+
+; Service: execute a normal service
+; ProtoService: execute a protocol service. Requires a contact selection on the list.
+; Database: Set a database value (see below for more info)
+
+; Service = Service to execute on push (depends on the Action property whether it will
+; be considered a normal or protocol service);
+
+; PassContact - must bei either w or l (if set, handle of currently selected contact
+; will be passed in either wParam or lParam)
+; if this is set for a button definion and you press the button without
+; a valid contact list selection, you will receive an error.
+;
+; Tip: - set the tooltip for the button
+; Toggle - - 0/1 value. if 1, button is a toggle button which will stay pressed until you
+; click it again
+
+; Here are the constants for the predefined buttons (you have to put them in the Action=
+; property).
+
+; CLN_topmenu -> the miranda menu
+; CLN_online -> toggle hide offline
+; CLN_groups -> toggle group mode
+; CLN_findadd -> find and add contacts
+; CLN_options -> open options
+; CLN_sound -> toggle sounds
+; CLN_minimize -> minimize the clist
+; CLN_topstatus -> open status menu
+; CLN_slist -> tabsrmm session list
+; CLN_menu -> tabsrmm traycontext menu
+; CLN_CLVM_select -> select a view mode (dropdown menu)
+; CLN_CLVM_options -> configure view modes
+; CLN_CLVM_reset -> clear currently selected view mode
+
+; the button definitions start here
+; ---------------------------------
+
+[!CloseButton]
+Width=12
+Height=12
+xoff=-18
+yoff=6
+NormalGlyph=51,0,62,11
+HoverGlyph=51,12,62,23
+PressedGlyph=51,24,62,35
+Action=cln_minimize
+FramelessOnly=1
+FakeTitleButton=1
+
+[!ButtonOnlineOffline]
+Width=20
+Height=20
+xoff=4
+yoff=2
+Normal=BtnNormal
+Pressed=BtnPushed
+Hover=BtnHover
+NormalGlyph=40,81,53,96
+PressedGlyph=40,65,53,80
+HoverGlyph=40,97,53,112
+Action=cln_online
+Toggle=1
+
+[!ButtonGroups]
+Width=20
+Height=20
+xoff=26
+yoff=2
+Normal=BtnNormal
+Pressed=BtnPushed
+Hover=BtnHover
+NormalGlyph=40,130,53,145
+PressedGlyph=40,114,53,129
+HoverGlyph=40,130,53,145
+Action=cln_groups
+Toggle=1
+
+[!ButtonOptions]
+Width=20
+Height=20
+xoff=48
+yoff=2
+Normal=BtnNormal
+Pressed=BtnPushed
+Hover=BtnHover
+NormalGlyph=40,147,53,162
+PressedGlyph=40,147,53,162
+HoverGlyph=40,147,53,162
+Action=cln_options
+
+[!ButtonFind]
+Width=20
+Height=20
+xoff=-48
+yoff=2
+Normal=BtnNormal
+Pressed=BtnPushed
+Hover=BtnHover
+NormalGlyph=39,48,54,63
+PressedGlyph=39,48,54,63
+HoverGlyph=39,48,54,63
+Action=cln_findadd
+Tip=Find contacts
+
+[!ButtonMenu]
+Width=18
+Height=14
+xoff=5
+yoff=4
+NormalGlyph=39,36,54,45
+PressedGlyph=39,36,54,45
+HoverGlyph=39,36,54,45
+Action=cln_topmenu
+Tip=Open main menu
+FramelessOnly=1
+FakeTitleButton=1
+
+[!ButtonMinimize]
+Width=12
+Height=12
+xoff=-36
+yoff=6
+NormalGlyph=39,0,50,11
+PressedGlyph=39,24,50,35
+HoverGlyph=39,12,50,23
+Action=cln_minimize
+Tip=Minimize
+FramelessOnly=1
+FakeTitleButton=1
+
+[!ButtonStatus]
+Width=20
+Height=20
+xoff=-26
+yoff=2
+Pressed=BtnPushed
+Normal=BtnNormal
+Hover=BtnHover
+NormalGlyph=38,48,48,58
+PressedGlyph=38,48,48,58
+HoverGlyph=38,48,48,58
+Action=cln_topstatus
+Tip=Status menu
+
+[!ButtonSound]
+Width=20
+Height=20
+xoff=70
+yoff=2
+Pressed=BtnPushed
+Normal=BtnNormal
+Hover=BtnHover
+NormalGlyph=66,130,81,144
+PressedGlyph=66,114,81,128
+HoverGlyph=66,130,81,144
+Action=cln_sound
+Tip=Toggle sounds
+Toggle=1
+
+; A button which modifies a database value on push/release
+;
+; special entries for such a button:
+;
+; Action: must be "database"
+; Module: The module name. It can be $c in which case it will be replaced by the
+; protocol of the currently selected contact.
+; in this case, a contact must be selected when you use the button, otherwise.
+; using the button will result in an error message.
+;
+; Setting: the db setting to change
+;
+; dbonpush: The db value. You MUST prefix it with b, w, d or s to specify the type
+; of setting (byte, word, dword, string)
+;
+; dbonrelease: same as above, only valid if button is set to a toggle button
+; if button is set to be a toggle button (Toggle=1) and no dbonrelease
+; is present, releasing the button to unpressed state will DELETE the
+; specified database value. Be careful :)
+;
+; Contact: if set to any numeric value != 0, then it will modify the value under
+; the record of the currently selected contact, otherwise it will modify
+; the global db value if no contact is selected in the clist.
+
+[Offline]
+ColorHigh=14079702
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=80
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[Online]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[Away]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[DND]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[NA]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[Occupied]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[Free for chat]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[Invisible]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[On the phone]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[Out to lunch]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=9
+[Idle]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Expanded Group]
+ColorHigh=33023
+ColorLow=33023
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=100
+Alpha2=100
+Corner=0
+Gradient=9
+Flags=68
+[Collapsed Group]
+ColorHigh=12632256
+ColorLow=12632256
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=100
+Alpha2=100
+Corner=0
+Gradient=9
+Flags=68
+[Empty Group]
+ColorHigh=12046066
+ColorLow=7783902
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=80
+Alpha2=80
+Corner=0
+Gradient=9
+Flags=68
+[First contact of a group]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Single item in group]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Last contact of a group]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[First contact of NON-group]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Single item in NON-group]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Last contact of NON-group]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Even Contact Positions]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Odd Contact Positions]
+ColorHigh=15658734
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=80
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Selection]
+ColorHigh=16744576
+ColorLow=16744576
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=100
+Alpha2=100
+Corner=0
+Gradient=9
+Flags=68
+[Hottracked]
+ColorHigh=8454143
+ColorLow=8454143
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=100
+Alpha2=100
+Corner=0
+Gradient=9
+Flags=68
+[Frame titlebars]
+ColorHigh=0
+ColorLow=0
+Textcolor=16777215
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Event area]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Status Bar]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[UI Button - pressed]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[UI Button - not pressed]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[UI Button - mouseover]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Status floater]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Frame border no titlebar]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=1
+Top=1
+Right=1
+Bottom=1
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=32
+[Frame border with titlebar]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=1
+Top=1
+Right=1
+Bottom=1
+Alpha=100
+Alpha2=100
+Corner=0
+Gradient=0
+Flags=32
+[Avatarframe]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=32
+[Avatarframe offline]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=32
+[AIM_1]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[ICQ]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[IRC]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[JABBER]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[JABBER_1]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[JABBER_2]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[MetaContacts]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[mPhantomUser]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[mRadio]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[MSN]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[MSN_SC]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[TV]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Twitter_1]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Weather]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[YAHOO]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=1
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+
+[Font0]
+Name=Segoe UI Semibold
+Size=9
+Style=0
+Set=0
+Color=0
+Flags=297
+[Font1]
+Name=Segoe UI Semibold
+Size=9
+Style=2
+Set=0
+Color=0
+Flags=297
+[Font2]
+Name=Segoe UI
+Size=9
+Style=0
+Set=0
+Color=0
+Flags=297
+[Font3]
+Name=Segoe UI
+Size=9
+Style=0
+Set=0
+Color=0
+Flags=297
+[Font4]
+Name=Segoe UI
+Size=9
+Style=1
+Set=0
+Color=0
+Flags=297
+[Font5]
+Name=Segoe UI
+Size=9
+Style=0
+Set=0
+Color=0
+Flags=297
+[Font6]
+Name=Ubuntu
+Size=8
+Style=0
+Set=0
+Color=0
+Flags=297
+[Font7]
+Name=Ubuntu
+Size=8
+Style=0
+Set=0
+Color=0
+Flags=297
+[Font8]
+Name=Ubuntu
+Size=8
+Style=0
+Set=0
+Color=16580
+Flags=297
+[Font9]
+Name=Segoe UI Semibold
+Size=10
+Style=0
+Set=0
+Color=16777215
+Flags=297
+[Font10]
+Name=Segoe UI Semibold
+Size=9
+Style=0
+Set=0
+Color=0
+Flags=297
+[Font11]
+Name=Ubuntu
+Size=8
+Style=0
+Set=0
+Color=255
+Flags=297
+[Even rows]
+ColorHigh=16777215
+ColorLow=16777215
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=100
+Alpha2=100
+Corner=0
+Gradient=9
+Flags=68
+[Odd rows]
+ColorHigh=16771304
+ColorLow=16771304
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=90
+Alpha2=90
+Corner=0
+Gradient=9
+Flags=68
+[Hottracked]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[UI Button pressed]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[UI Button normal]
+ColorHigh=12632256
+ColorLow=12632256
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=100
+Alpha2=100
+Corner=0
+Gradient=0
+Flags=65
+[UI Button hover]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
+[Frame border no titlebar]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=1
+Top=1
+Right=1
+Bottom=1
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=32
+[Frame border with titlebar]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=32
+[MSN_1]
+ColorHigh=0
+ColorLow=0
+Textcolor=0
+Ignored=0
+Left=0
+Top=0
+Right=0
+Bottom=0
+Alpha=1
+Alpha2=1
+Corner=0
+Gradient=0
+Flags=1
diff --git a/plugins/Clist_ng/BASESKIN/glyphs.png b/plugins/Clist_ng/BASESKIN/glyphs.png Binary files differnew file mode 100644 index 0000000000..a7049f4a16 --- /dev/null +++ b/plugins/Clist_ng/BASESKIN/glyphs.png diff --git a/plugins/Clist_ng/CLUIFrames/cluiframes.cpp b/plugins/Clist_ng/CLUIFrames/cluiframes.cpp new file mode 100644 index 0000000000..222bbbf176 --- /dev/null +++ b/plugins/Clist_ng/CLUIFrames/cluiframes.cpp @@ -0,0 +1,3496 @@ +/* + * 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 + * ----------------------------------------------------------------------- + * The CLUI frames module was first written many years ago for Miranda 0.2 + * as part of the multiwindow patch. Later it was converted to a contact + * list plugin (clist_mw) on which all modern contact list plugins for + * miranda are still somewhat based. + * + * original author of the CLUI frames module is a guy with the nick name + * Bethoven + * + * $Id: cluiframes.cpp 135 2010-10-06 13:13:51Z silvercircle $ + * + */ + +#include <commonheaders.h> +void RefreshButtons(); + +extern HWND g_hwndViewModeFrame, g_hwndEventArea; +extern int mf_updatethread_running; + +extern void MF_UpdateThread(LPVOID p); +extern HANDLE hThreadMFUpdate;; + +HANDLE hExtraImageListRebuilding, hExtraImageApplying; +HANDLE hStatusBarShowToolTipEvent, hStatusBarHideToolTipEvent; +HANDLE g_hEventThread = 0; + +LOGFONT TitleBarLogFont = {0}; + +//we use dynamic frame list, +//but who wants so huge number of frames ?? +#define MAX_FRAMES 40 + +#define UNCOLLAPSED_FRAME_SIZE 0 + +//legacy menu support +#define frame_menu_lock 1 +#define frame_menu_visible 2 +#define frame_menu_showtitlebar 3 +#define frame_menu_floating 4 +#define frame_menu_skinned 5 + +static int UpdateTBToolTip(int framepos); +INT_PTR CLUIFrameSetFloat(WPARAM wParam, LPARAM lParam); +int CLUIFrameResizeFloatingFrame(int framepos); +extern int ProcessCommandProxy(WPARAM wParam, LPARAM lParam); +extern int InitFramesMenus(void); +static int CLUIFramesReSort(); + +boolean FramesSysNotStarted = TRUE; + +static SortData g_sd[MAX_FRAMES]; + +static HHOOK g_hFrameHook = 0; + +static FrameMenuHandles cont; + +static int sortfunc(const void *a, const void *b) +{ + SortData *sd1, *sd2; + sd1 = (SortData *)a; + sd2 = (SortData *)b; + if (sd1->order > sd2->order) + return(1); + if (sd1->order < sd2->order) + return(-1); + return(0); +} + +#define CLUIFRAMESSETALIGN "CLUIFramesSetAlign" +#define CLUIFRAMESSETALIGNALTOP "CLUIFramesSetAlignalTop" +#define CLUIFRAMESSETALIGNALCLIENT "CLUIFramesSetAlignalClient" +#define CLUIFRAMESSETALIGNALBOTTOM "CLUIFramesSetAlignalBottom" +#define CLUIFRAMESMOVEUP "CLUIFramesMoveUp" +#define CLUIFRAMESMOVEDOWN "CLUIFramesMoveDown" + +static FRAMEWND *Frames = NULL; + +FRAMEWND *wndFrameCLC = NULL, *wndFrameEventArea = NULL, *wndFrameViewMode = NULL; + +static int nFramescount = 0; +static int alclientFrame = -1;//for fast access to frame with alclient properties +static int NextFrameId = 100; + +static int TitleBarH = DEFAULT_TITLEBAR_HEIGHT; +static boolean resizing = FALSE; + +// menus +static HANDLE contMIVisible, contMITitle, contMITBVisible, contMILock, contMIColl, contMIFloating; +static HANDLE contMIAlignRoot; +static HANDLE contMIAlignTop, contMIAlignClient, contMIAlignBottom; +static HANDLE contMIBorder, contMISkinned; +static HANDLE MainMIRoot = (HANDLE) - 1; + +// others +static int ContactListHeight; +static int LastStoreTick = 0; + +static int lbypos = -1; +static int oldframeheight = -1; +static int curdragbar = -1; +static CRITICAL_SECTION csFrameHook; + +static BOOLEAN CLUIFramesFitInSize(void); +HWND hWndExplorerToolBar; +static int GapBetweenFrames = 1; + +static int RemoveItemFromList(int pos, FRAMEWND **lpFrames, int *FrameItemCount) +{ + memcpy(&((*lpFrames)[pos]), &((*lpFrames)[pos+1]), sizeof(FRAMEWND)*(*FrameItemCount - pos - 1)); + (*FrameItemCount)--; + return 0; +} + +static int id2pos(int id) +{ + int i; + + if (FramesSysNotStarted) + return -1; + + for (i = 0;i < nFramescount;i++) { + if (Frames[i].id == id) + return(i); + } + return(-1); +} + +int __forceinline btoint(BOOLEAN b) +{ + return(b ? 1 : 0); +} + +void __forceinline lockfrm() +{ + if (FramesSysNotStarted == FALSE) + EnterCriticalSection(&csFrameHook); +} + +void __forceinline ulockfrm() +{ + LeaveCriticalSection(&csFrameHook); +} + +static FRAMEWND* FindFrameByWnd(HWND hwnd) +{ + int i; + + if (hwnd == NULL) + return(NULL); + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].floating) && (Frames[i].ContainerWnd == hwnd)) + return(&Frames[i]); + } + return(NULL); +} + + +static void DockThumbs(FRAMEWND *pThumbLeft, FRAMEWND *pThumbRight) +{ + if ((pThumbRight->dockOpt.hwndLeft == NULL) && (pThumbLeft->dockOpt.hwndRight == NULL)) { + pThumbRight->dockOpt.hwndLeft = pThumbLeft->ContainerWnd; + pThumbLeft->dockOpt.hwndRight = pThumbRight->ContainerWnd; + } +} + + +static void UndockThumbs(FRAMEWND *pThumb1, FRAMEWND *pThumb2) +{ + if ((pThumb1 == NULL) || (pThumb2 == NULL)) + return; + + if (pThumb1->dockOpt.hwndRight == pThumb2->ContainerWnd) + pThumb1->dockOpt.hwndRight = NULL; + + if (pThumb1->dockOpt.hwndLeft == pThumb2->ContainerWnd) + pThumb1->dockOpt.hwndLeft = NULL; + + if (pThumb2->dockOpt.hwndRight == pThumb1->ContainerWnd) + pThumb2->dockOpt.hwndRight = NULL; + + if (pThumb2->dockOpt.hwndLeft == pThumb1->ContainerWnd) + pThumb2->dockOpt.hwndLeft = NULL; +} + +BOOLEAN bMoveTogether; + +static void PositionThumb(FRAMEWND *pThumb, short nX, short nY) +{ + FRAMEWND *pCurThumb = &Frames[0]; + FRAMEWND *pDockThumb = pThumb; + FRAMEWND fakeMainWindow; + FRAMEWND fakeTaskBarWindow; + RECT rc; + RECT rcThumb; + RECT rcOld; + SIZE sizeScreen; + int nNewX; + int nNewY; + int nOffs = 10; + int nWidth; + int nHeight; + POINT pt; + RECT rcLeft; + RECT rcTop; + RECT rcRight; + RECT rcBottom; + BOOL bDocked; + BOOL bDockedLeft; + BOOL bDockedRight; + BOOL bLeading; + int frmidx = 0; + + if (pThumb == NULL) + return; + + sizeScreen.cx = GetSystemMetrics(SM_CXSCREEN); + sizeScreen.cy = GetSystemMetrics(SM_CYSCREEN); + + // Get thumb dimnsions + GetWindowRect(pThumb->ContainerWnd, &rcThumb); + nWidth = rcThumb.right - rcThumb.left; + nHeight = rcThumb.bottom - rcThumb.top; + + // Docking to the edges of the screen + nNewX = nX < nOffs ? 0 : nX; + nNewX = nNewX > (sizeScreen.cx - nWidth - nOffs) ? (sizeScreen.cx - nWidth) : nNewX; + nNewY = nY < nOffs ? 0 : nY; + nNewY = nNewY > (sizeScreen.cy - nHeight - nOffs) ? (sizeScreen.cy - nHeight) : nNewY; + + bLeading = pThumb->dockOpt.hwndRight != NULL; + + if (bMoveTogether) { + UndockThumbs(pThumb, FindFrameByWnd(pThumb->dockOpt.hwndLeft)); + GetWindowRect(pThumb->ContainerWnd, &rcOld); + } + + memset(&fakeMainWindow, 0, sizeof(fakeMainWindow)); + fakeMainWindow.ContainerWnd = pcli->hwndContactList; + fakeMainWindow.floating = TRUE; + + memset(&fakeTaskBarWindow, 0, sizeof(fakeTaskBarWindow)); + fakeTaskBarWindow.ContainerWnd = hWndExplorerToolBar; + fakeTaskBarWindow.floating = TRUE; + + + while (pCurThumb != NULL) { + if (pCurThumb->floating) { + + if (pCurThumb != pThumb) { + GetWindowRect(pThumb->ContainerWnd, &rcThumb); + OffsetRect(&rcThumb, nX - rcThumb.left, nY - rcThumb.top); + + GetWindowRect(pCurThumb->ContainerWnd, &rc); + + rcLeft.left = rc.left - nOffs; + rcLeft.top = rc.top - nOffs; + rcLeft.right = rc.left + nOffs; + rcLeft.bottom = rc.bottom + nOffs; + + rcTop.left = rc.left - nOffs; + rcTop.top = rc.top - nOffs; + rcTop.right = rc.right + nOffs; + rcTop.bottom = rc.top + nOffs; + + rcRight.left = rc.right - nOffs; + rcRight.top = rc.top - nOffs; + rcRight.right = rc.right + nOffs; + rcRight.bottom = rc.bottom + nOffs; + + rcBottom.left = rc.left - nOffs; + rcBottom.top = rc.bottom - nOffs; + rcBottom.right = rc.right + nOffs; + rcBottom.bottom = rc.bottom + nOffs; + + + bDockedLeft = FALSE; + bDockedRight = FALSE; + + // Upper-left + pt.x = rcThumb.left; + pt.y = rcThumb.top; + bDocked = FALSE; + + if (PtInRect(&rcRight, pt)) { + nNewX = rc.right; + bDocked = TRUE; + } + + if (PtInRect(&rcBottom, pt)) { + nNewY = rc.bottom; + + if (PtInRect(&rcLeft, pt)) + nNewX = rc.left; + } + + if (PtInRect(&rcTop, pt)) { + nNewY = rc.top; + bDockedLeft = bDocked; + } + + // Upper-right + pt.x = rcThumb.right; + pt.y = rcThumb.top; + bDocked = FALSE; + + if (!bLeading && PtInRect(&rcLeft, pt)) { + if (!bDockedLeft) { + nNewX = rc.left - nWidth; + bDocked = TRUE; + } else if (rc.right == rcThumb.left) + bDocked = TRUE; + } + + + if (PtInRect(&rcBottom, pt)) { + nNewY = rc.bottom; + + if (PtInRect(&rcRight, pt)) + nNewX = rc.right - nWidth; + } + + if (!bLeading && PtInRect(&rcTop, pt)) { + nNewY = rc.top; + bDockedRight = bDocked; + } + + if (bMoveTogether) { + if (bDockedRight) { + DockThumbs(pThumb, pCurThumb); + } + + if (bDockedLeft) { + DockThumbs(pCurThumb, pThumb); + } + } + + // Lower-left + pt.x = rcThumb.left; + pt.y = rcThumb.bottom; + + if (PtInRect(&rcRight, pt)) { + nNewX = rc.right; + } + + if (PtInRect(&rcTop, pt)) { + nNewY = rc.top - nHeight; + + if (PtInRect(&rcLeft, pt)) { + nNewX = rc.left; + } + } + + + // Lower-right + pt.x = rcThumb.right; + pt.y = rcThumb.bottom; + + if (!bLeading && PtInRect(&rcLeft, pt)) { + nNewX = rc.left - nWidth; + } + + if (!bLeading && PtInRect(&rcTop, pt)) { + nNewY = rc.top - nHeight; + + if (PtInRect(&rcRight, pt)) { + nNewX = rc.right - nWidth; + } + } + } + + }; + frmidx++; + if (pCurThumb->ContainerWnd == fakeTaskBarWindow.ContainerWnd) + break; + if (pCurThumb->ContainerWnd == fakeMainWindow.ContainerWnd) { + pCurThumb = &fakeTaskBarWindow; + continue; + } + if (frmidx == nFramescount) { + pCurThumb = &fakeMainWindow; + continue; + } + pCurThumb = &Frames[frmidx]; + } + + // Adjust coords once again + nNewX = nNewX < nOffs ? 0 : nNewX; + nNewX = nNewX > (sizeScreen.cx - nWidth - nOffs) ? (sizeScreen.cx - nWidth) : nNewX; + nNewY = nNewY < nOffs ? 0 : nNewY; + nNewY = nNewY > (sizeScreen.cy - nHeight - nOffs) ? (sizeScreen.cy - nHeight) : nNewY; + + SetWindowPos(pThumb->ContainerWnd, + 0, + nNewX, + nNewY, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + + + // OK, move all docked thumbs + if (bMoveTogether) { + pDockThumb = FindFrameByWnd(pDockThumb->dockOpt.hwndRight); + + PositionThumb(pDockThumb, (short)(nNewX + nWidth), (short)nNewY); + } +} + +void GetBorderSize(HWND hwnd, RECT *rect) +{ + RECT wr, cr; + POINT pt1, pt2; + + GetWindowRect(hwnd, &wr); + GetClientRect(hwnd, &cr); + pt1.y = cr.top; + pt1.x = cr.left; + pt2.y = cr.bottom; + pt2.x = cr.right; + + ClientToScreen(hwnd, &pt1); + ClientToScreen(hwnd, &pt2); + + cr.top = pt1.y; + cr.left = pt1.x; + cr.bottom = pt2.y; + cr.right = pt2.x; + + rect->top = cr.top - wr.top; + rect->left = cr.left - wr.left; + rect->right = wr.right - cr.right; + rect->bottom = wr.bottom - cr.bottom; +} + +//append string +char __forceinline *AS(char *str, const char *setting, char *addstr) +{ + if (str != NULL) { + strcpy(str, setting); + strcat(str, addstr); + } + return str; +} + +int DBLoadFrameSettingsAtPos(int pos, int Frameid) +{ + char sadd[15]; + char buf[255]; + + _itoa(pos, sadd, 10); + + Frames[Frameid].collapsed = 0 != cfg::getByte(CLUIFrameModule, AS(buf, "Collapse", sadd), Frames[Frameid].collapsed); + + Frames[Frameid].Locked = 0 != cfg::getByte(CLUIFrameModule, AS(buf, "Locked", sadd), Frames[Frameid].Locked); + Frames[Frameid].visible = 0 != cfg::getByte(CLUIFrameModule, AS(buf, "Visible", sadd), Frames[Frameid].visible); + Frames[Frameid].TitleBar.ShowTitleBar = 0 != cfg::getByte(CLUIFrameModule, AS(buf, "TBVisile", sadd), Frames[Frameid].TitleBar.ShowTitleBar); + + Frames[Frameid].height = cfg::getWord(CLUIFrameModule, AS(buf, "Height", sadd), Frames[Frameid].height); + Frames[Frameid].HeightWhenCollapsed = cfg::getWord(CLUIFrameModule, AS(buf, "HeightCollapsed", sadd), 0); + Frames[Frameid].align = cfg::getWord(CLUIFrameModule, AS(buf, "Align", sadd), Frames[Frameid].align); + + Frames[Frameid].FloatingPos.x = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatX", sadd), 100, 0, 1024); + Frames[Frameid].FloatingPos.y = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatY", sadd), 100, 0, 1024); + Frames[Frameid].FloatingSize.x = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatW", sadd), 100, 0, 1024); + Frames[Frameid].FloatingSize.y = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatH", sadd), 100, 0, 1024); + + Frames[Frameid].floating = 0 != cfg::getByte(CLUIFrameModule, AS(buf, "Floating", sadd), 0); + Frames[Frameid].order = cfg::getWord(CLUIFrameModule, AS(buf, "Order", sadd), 0); + + Frames[Frameid].UseBorder = 0 != cfg::getByte(CLUIFrameModule, AS(buf, "UseBorder", sadd), Frames[Frameid].UseBorder); + Frames[Frameid].Skinned = 0 != cfg::getByte(CLUIFrameModule, AS(buf, "Skinned", sadd), Frames[Frameid].Skinned); + return 0; +} + +int DBStoreFrameSettingsAtPos(int pos, int Frameid) +{ + char sadd[16]; + char buf[255]; + + _itoa(pos, sadd, 10); + + cfg::writeTString(0, CLUIFrameModule, AS(buf, "Name", sadd), Frames[Frameid].name); + //boolean + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Collapse", sadd), (BYTE)btoint(Frames[Frameid].collapsed)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Locked", sadd), (BYTE)btoint(Frames[Frameid].Locked)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Visible", sadd), (BYTE)btoint(Frames[Frameid].visible)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "TBVisile", sadd), (BYTE)btoint(Frames[Frameid].TitleBar.ShowTitleBar)); + + cfg::writeWord(CLUIFrameModule, AS(buf, "Height", sadd), (WORD)Frames[Frameid].height); + cfg::writeWord(CLUIFrameModule, AS(buf, "HeightCollapsed", sadd), (WORD)Frames[Frameid].HeightWhenCollapsed); + cfg::writeWord(CLUIFrameModule, AS(buf, "Align", sadd), (WORD)Frames[Frameid].align); + //FloatingPos + cfg::writeWord(CLUIFrameModule, AS(buf, "FloatX", sadd), (WORD)Frames[Frameid].FloatingPos.x); + cfg::writeWord(CLUIFrameModule, AS(buf, "FloatY", sadd), (WORD)Frames[Frameid].FloatingPos.y); + cfg::writeWord(CLUIFrameModule, AS(buf, "FloatW", sadd), (WORD)Frames[Frameid].FloatingSize.x); + cfg::writeWord(0, CLUIFrameModule, AS(buf, "FloatH", sadd), (WORD)Frames[Frameid].FloatingSize.y); + + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Floating", sadd), (BYTE)btoint(Frames[Frameid].floating)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "UseBorder", sadd), (BYTE)btoint(Frames[Frameid].UseBorder)); + cfg::writeWord(0, CLUIFrameModule, AS(buf, "Order", sadd), (WORD)Frames[Frameid].order); + + cfg::writeByte(CLUIFrameModule, AS(buf, "Skinned", sadd), Frames[Frameid].Skinned); + return 0; +} + +int LocateStorePosition(int Frameid, int maxstored) +{ + int i; + LPTSTR frmname; + char settingname[255]; + if (Frames[Frameid].name == NULL) return -1; + + for (i = 0;i < maxstored;i++) { + mir_snprintf(settingname, sizeof(settingname), "Name%d", i); + frmname = db_get_tsa(0, CLUIFrameModule, settingname); + if (frmname == NULL) continue; + if (lstrcmpi(frmname, Frames[Frameid].name) == 0) { + mir_free(frmname); + return i; + } + mir_free(frmname); + } + return -1; +} + +int CLUIFramesLoadFrameSettings(int Frameid) +{ + int storpos, maxstored; + + if (FramesSysNotStarted) return -1; + + if (Frameid < 0 || Frameid >= nFramescount) + return -1; + + maxstored = cfg::getWord(CLUIFrameModule, "StoredFrames", -1); + if (maxstored == -1) + return 0; + + storpos = LocateStorePosition(Frameid, maxstored); + if (storpos == -1) + return 0; + + DBLoadFrameSettingsAtPos(storpos, Frameid); + return 0; +} + +int CLUIFramesStoreFrameSettings(int Frameid) +{ + int maxstored, storpos; + + if (FramesSysNotStarted) + return -1; + + if (Frameid < 0 || Frameid >= nFramescount) + return -1; + + maxstored = cfg::getWord(CLUIFrameModule, "StoredFrames", -1); + if (maxstored == -1) + maxstored = 0; + + storpos = LocateStorePosition(Frameid, maxstored); + if (storpos == -1) { + storpos = maxstored; + maxstored++; + } + + DBStoreFrameSettingsAtPos(storpos, Frameid); + cfg::writeWord(CLUIFrameModule, "StoredFrames", (WORD)maxstored); + return 0; +} + +int CLUIFramesStoreAllFrames() +{ + int i; + + if (FramesSysNotStarted) + return -1; + + if (cfg::shutDown) + return -1; + + lockfrm(); + for (i = 0;i < nFramescount;i++) + CLUIFramesStoreFrameSettings(i); + ulockfrm(); + return 0; +} + +// Get client frame +int CLUIFramesGetalClientFrame(void) +{ + int i; + if (FramesSysNotStarted) + return -1; + + if (alclientFrame != -1) + return alclientFrame; + + if (alclientFrame != -1) { + /* this value could become invalid if RemoveItemFromList was called, + * so we double-check */ + if (alclientFrame < nFramescount) { + if (Frames[alclientFrame].align == alClient) { + return alclientFrame; + } + } + } + + for (i = 0;i < nFramescount;i++) + if (Frames[i].align == alClient) { + alclientFrame = i; + return i; + } + //pluginLink + return -1; +} + +static HGENMENU addFrameMenuItem(TMO_MenuItem *pmi, int frameid, bool bMain) +{ + HGENMENU res = (bMain) ? Menu_AddMainMenuItem(pmi) : Menu_AddContextFrameMenuItem(pmi); + if (pmi->pszService != NULL) + Menu_ConfigureItem(res, MCI_OPT_EXECPARAM, frameid); + return res; +} + +HMENU CLUIFramesCreateMenuForFrame(int frameid, HGENMENU root, int popuppos, bool bMain) +{ + if (FramesSysNotStarted) + return NULL; + + int framepos = id2pos(frameid); + FrameMenuHandles &fmh = (frameid == -1) ? cont : Frames[framepos].MenuHandles; + + CMenuItem mi; + mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_MIRANDA); + mi.root = root; + mi.position = popuppos++; + mi.name.a = LPGEN("&FrameTitle"); + mi.flags = CMIF_SYSTEM | CMIF_GRAYED; + fmh.MITitle = addFrameMenuItem(&mi, frameid, bMain); + + popuppos += 100000; + + mi.hIcolibItem = NULL; + mi.position = popuppos++; + mi.name.a = LPGEN("&Visible"); + mi.flags = CMIF_SYSTEM | CMIF_CHECKED; + mi.pszService = MS_CLIST_FRAMES_SHFRAME; + fmh.MIVisible = addFrameMenuItem(&mi, frameid, bMain); + + mi.position = popuppos++; + mi.name.a = LPGEN("&Show title bar"); + mi.pszService = MS_CLIST_FRAMES_SHFRAMETITLEBAR; + fmh.MITBVisible = addFrameMenuItem(&mi, frameid, bMain); + + popuppos += 100000; + + mi.position = popuppos++; + mi.name.a = LPGEN("&Locked"); + mi.pszService = MS_CLIST_FRAMES_ULFRAME; + fmh.MILock = addFrameMenuItem(&mi, frameid, bMain); + + mi.position = popuppos++; + mi.name.a = LPGEN("&Collapsed"); + mi.pszService = MS_CLIST_FRAMES_UCOLLFRAME; + fmh.MIColl = addFrameMenuItem(&mi, frameid, bMain); + + // floating + mi.position = popuppos++; + mi.name.a = LPGEN("&Floating mode"); + mi.flags = CMIF_SYSTEM; + mi.pszService = "Set_Floating"; + fmh.MIFloating = addFrameMenuItem(&mi, frameid, bMain); + + popuppos += 100000; + + mi.position = popuppos++; + mi.name.a = LPGEN("&Border"); + mi.flags = CMIF_SYSTEM | CMIF_CHECKED; + mi.pszService = MS_CLIST_FRAMES_SETUNBORDER; + fmh.MIBorder = addFrameMenuItem(&mi, frameid, bMain); + + popuppos += 100000; + + mi.position = popuppos++; + mi.name.a = LPGEN("&Skinned frame"); + mi.pszService = MS_CLIST_FRAMES_SETSKINNED; + fmh.MISkinned = addFrameMenuItem(&mi, frameid, bMain); + + popuppos += 100000; + + // alignment root + mi.root = root; + mi.position = popuppos++; + mi.name.a = LPGEN("&Align"); + mi.flags = CMIF_SYSTEM; + mi.pszService = NULL; + fmh.MIAlignRoot = addFrameMenuItem(&mi, frameid, bMain); + + // align top + mi.root = fmh.MIAlignRoot; + mi.position = popuppos++; + mi.name.a = LPGEN("&Top"); + mi.pszService = CLUIFRAMESSETALIGNALTOP; + fmh.MIAlignTop = addFrameMenuItem(&mi, frameid, bMain); + + // align client + mi.position = popuppos++; + mi.name.a = LPGEN("&Client"); + mi.pszService = CLUIFRAMESSETALIGNALCLIENT; + fmh.MIAlignClient = addFrameMenuItem(&mi, frameid, bMain); + + // align bottom + mi.position = popuppos++; + mi.name.a = LPGEN("&Bottom"); + mi.pszService = CLUIFRAMESSETALIGNALBOTTOM; + fmh.MIAlignBottom = addFrameMenuItem(&mi, frameid, bMain); + + // position root + mi.root = root; + mi.position = popuppos++; + mi.name.a = LPGEN("&Position"); + mi.pszService = NULL; + mi.root = addFrameMenuItem(&mi, frameid, bMain); + + mi.position = popuppos++; + mi.name.a = LPGEN("&Up"); + mi.pszService = CLUIFRAMESMOVEUP; + addFrameMenuItem(&mi, frameid, bMain); + + mi.position = popuppos++; + mi.name.a = LPGEN("&Down"); + mi.pszService = CLUIFRAMESMOVEDOWN; + addFrameMenuItem(&mi, frameid, bMain); + return 0; +} + +/* +int ModifyMItem(WPARAM wParam, LPARAM lParam) +{ + //return ModifyMenuItemProxy(wParam, lParam); + return 0; +}; +*/ + +static int CLUIFramesModifyContextMenuForFrame(WPARAM wParam, LPARAM) +{ + if (FramesSysNotStarted) + return -1; + + mir_cslock lck(csFrameHook); + int pos = id2pos(wParam); + if (pos >= 0 && pos < nFramescount) { + FRAMEWND &p = Frames[pos]; + Menu_ModifyItem(cont.MITitle, p.TitleBar.tbname ? p.TitleBar.tbname : p.name); + Menu_SetChecked(cont.MIVisible, p.visible); + Menu_SetChecked(cont.MILock, p.Locked); + Menu_SetChecked(cont.MITBVisible, p.TitleBar.ShowTitleBar); + Menu_SetChecked(cont.MIFloating, p.floating); + Menu_SetChecked(cont.MIBorder, p.UseBorder); + Menu_SetChecked(cont.MISkinned, p.Skinned); + Menu_SetChecked(cont.MIAlignTop, (p.align & alTop) != 0); + Menu_SetChecked(cont.MIAlignClient, (p.align & alClient) != 0); + Menu_SetChecked(cont.MIAlignBottom, (p.align & alBottom) != 0); + + Menu_SetChecked(cont.MIColl, !p.collapsed); + Menu_EnableItem(cont.MIColl, p.visible && !p.Locked && pos != CLUIFramesGetalClientFrame()); + } + return 0; +} + +INT_PTR CLUIFramesModifyMainMenuItems(WPARAM frameId, LPARAM) +{ + if (FramesSysNotStarted) + return -1; + + mir_cslock lck(csFrameHook); + int pos = id2pos(frameId); + + if (pos >= 0 && pos < nFramescount) { + FRAMEWND &p = Frames[pos]; + Menu_ModifyItem(p.MenuHandles.MITitle, p.TitleBar.tbname ? p.TitleBar.tbname : p.name); + + Menu_SetChecked(p.MenuHandles.MIVisible, p.visible); + Menu_SetChecked(p.MenuHandles.MILock, p.Locked); + Menu_SetChecked(p.MenuHandles.MITBVisible, p.TitleBar.ShowTitleBar); + Menu_SetChecked(p.MenuHandles.MIFloating, p.floating); + Menu_SetChecked(p.MenuHandles.MIBorder, p.UseBorder); + Menu_SetChecked(p.MenuHandles.MISkinned, p.Skinned); + + Menu_EnableItem(p.MenuHandles.MIAlignTop, (p.align & alClient) == 0); + Menu_SetChecked(p.MenuHandles.MIAlignTop, (p.align & alTop) != 0); + + Menu_SetChecked(p.MenuHandles.MIAlignClient, (p.align & alClient) != 0); + + Menu_EnableItem(p.MenuHandles.MIAlignTop, (p.align & alClient) == 0); + Menu_SetChecked(p.MenuHandles.MIAlignTop, (p.align & alBottom) != 0); + + Menu_SetChecked(p.MenuHandles.MIColl, !p.collapsed); + Menu_EnableItem(p.MenuHandles.MIColl, p.visible && !p.Locked && pos != CLUIFramesGetalClientFrame()); + } + return 0; +} + +INT_PTR CLUIFramesGetFrameOptions(WPARAM wParam, LPARAM lParam) +{ + int pos; + INT_PTR retval; + lParam = 0; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos(HIWORD(wParam)); + if (pos < 0 || pos >= nFramescount) { + ulockfrm(); + return -1; + } + + switch (LOWORD(wParam)) { + case FO_FLAGS: + retval = 0; + if (Frames[pos].visible) retval |= F_VISIBLE; + if (!Frames[pos].collapsed) retval |= F_UNCOLLAPSED; + if (Frames[pos].Locked) retval |= F_LOCKED; + if (Frames[pos].TitleBar.ShowTitleBar) retval |= F_SHOWTB; + if (Frames[pos].TitleBar.ShowTitleBarTip) retval |= F_SHOWTBTIP; + if (Frames[pos].Skinned) retval |= F_SKINNED; + retval |= F_NOBORDER; + break; + + case FO_NAME: + retval = (INT_PTR)Frames[pos].name; + break; + + case FO_TBNAME: + retval = (INT_PTR)Frames[pos].TitleBar.tbname; + break; + + case FO_TBTIPNAME: + retval = (INT_PTR)Frames[pos].TitleBar.tooltip; + break; + + case FO_TBSTYLE: + retval = GetWindowLong(Frames[pos].TitleBar.hwnd, GWL_STYLE); + break; + + case FO_TBEXSTYLE: + retval = GetWindowLong(Frames[pos].TitleBar.hwnd, GWL_EXSTYLE); + break; + + case FO_ICON: + retval = (INT_PTR)Frames[pos].TitleBar.hicon; + break; + + case FO_HEIGHT: + retval = (INT_PTR)Frames[pos].height; + break; + + case FO_ALIGN: + retval = (INT_PTR)Frames[pos].align; + break; + case FO_FLOATING: + retval = (int)Frames[pos].floating; + break; + default: + retval = -1; + break; + } + ulockfrm(); + return retval; +} + +INT_PTR CLUIFramesSetFrameOptions(WPARAM wParam, LPARAM lParam) +{ + int pos; + int retval; // value to be returned + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos(HIWORD(wParam)); + if (pos < 0 || pos >= nFramescount) { + ulockfrm(); + return -1; + } + switch (LOWORD(wParam) & ~FO_UNICODETEXT) { + case FO_FLAGS: { + int flag = lParam; + int style; + + Frames[pos].dwFlags = flag; + Frames[pos].visible = FALSE; + if (flag&F_VISIBLE) Frames[pos].visible = TRUE; + + Frames[pos].collapsed = TRUE; + if (flag&F_UNCOLLAPSED) Frames[pos].collapsed = FALSE; + + Frames[pos].Locked = FALSE; + if (flag&F_LOCKED) Frames[pos].Locked = TRUE; + + Frames[pos].TitleBar.ShowTitleBar = FALSE; + if (flag&F_SHOWTB) Frames[pos].TitleBar.ShowTitleBar = TRUE; + + Frames[pos].TitleBar.ShowTitleBarTip = FALSE; + if (flag&F_SHOWTBTIP) Frames[pos].TitleBar.ShowTitleBarTip = TRUE; + + SendMessage(Frames[pos].TitleBar.hwndTip, TTM_ACTIVATE, (WPARAM)Frames[pos].TitleBar.ShowTitleBarTip, 0); + + style = (int)GetWindowLong(Frames[pos].hWnd, GWL_STYLE); + style |= CLS_SKINNEDFRAME; + + Frames[pos].Skinned = FALSE; + if (flag & F_SKINNED) + Frames[pos].Skinned = TRUE; + + if (!(flag & F_SKINNED)) + style &= ~CLS_SKINNEDFRAME; + + SetWindowLong(Frames[pos].hWnd, GWL_STYLE, (LONG)style); + SetWindowLong(Frames[pos].TitleBar.hwnd, GWL_STYLE, (LONG)style & ~(WS_VSCROLL | WS_HSCROLL)); + + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + SetWindowPos(Frames[pos].TitleBar.hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + return 0; + } + + case FO_NAME: + if (lParam == (LPARAM)NULL) { + ulockfrm(); + return -1; + } + mir_free(Frames[pos].name); + Frames[pos].name = (wParam & FO_UNICODETEXT) ? mir_u2t((LPWSTR)lParam) : mir_a2t((LPSTR)lParam); + ulockfrm(); + return 0; + + case FO_TBNAME: + if (lParam == (LPARAM)NULL) { + ulockfrm(); + return(-1); + } + mir_free(Frames[pos].TitleBar.tbname); + Frames[pos].TitleBar.tbname = (wParam & FO_UNICODETEXT) ? mir_u2t((LPWSTR)lParam) : mir_a2t((LPSTR)lParam); + ulockfrm(); + if (Frames[pos].floating && (Frames[pos].TitleBar.tbname != NULL)) + SetWindowText(Frames[pos].ContainerWnd, Frames[pos].TitleBar.tbname); + return 0; + + case FO_TBTIPNAME: + if (lParam == (LPARAM)NULL) { + ulockfrm(); + return(-1); + } + mir_free(Frames[pos].TitleBar.tooltip); + Frames[pos].TitleBar.tooltip = (wParam & FO_UNICODETEXT) ? mir_u2t((LPWSTR)lParam) : mir_a2t((LPSTR)lParam); + UpdateTBToolTip(pos); + ulockfrm(); + return 0; + + case FO_TBSTYLE: + SetWindowLong(Frames[pos].TitleBar.hwnd, GWL_STYLE, lParam); + ulockfrm(); + return 0; + + case FO_TBEXSTYLE: + SetWindowLong(Frames[pos].TitleBar.hwnd, GWL_EXSTYLE, lParam); + ulockfrm(); + return 0; + + case FO_ICON: + Frames[pos].TitleBar.hicon = (HICON)lParam; + ulockfrm(); + return 0; + + case FO_HEIGHT: + { + if (lParam < 0) { + ulockfrm(); + return -1; + } + if(Frames[pos].Skinned) { + int uID = Frames[pos].TitleBar.ShowTitleBar ? ID_EXTBKOWNEDFRAMEBORDERTB : ID_EXTBKOWNEDFRAMEBORDER; + lParam += (Skin::statusItems[uID].MARGIN_BOTTOM + Skin::statusItems[uID].MARGIN_TOP); + } + if (Frames[pos].collapsed) { + int oldHeight = Frames[pos].height; + retval = Frames[pos].height; + Frames[pos].height = lParam; + if(!CLUIFramesFitInSize()) + Frames[pos].height = retval; + retval = Frames[pos].height; + + if (Frames[pos].height != oldHeight) { + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0); + if(Frames[pos].Skinned) + RedrawWindow(Frames[pos].hWnd, 0, 0, RDW_FRAME|RDW_UPDATENOW|RDW_INVALIDATE); + } + } + else { + retval = Frames[pos].HeightWhenCollapsed; + Frames[pos].HeightWhenCollapsed = lParam; + if(!CLUIFramesFitInSize()) + Frames[pos].HeightWhenCollapsed = retval; + retval = Frames[pos].HeightWhenCollapsed; + } + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + CLUI::Redraw(); + ulockfrm(); + return(retval); + } + + case FO_FLOATING: + if (lParam < 0) { + ulockfrm(); + return -1; + } + { + int id = Frames[pos].id; + Frames[pos].floating = !(lParam); + ulockfrm(); + + CLUIFrameSetFloat(id, 1);//lparam=1 use stored width and height + return(wParam); + } + case FO_ALIGN: + if (!(lParam&alTop || lParam&alBottom || lParam&alClient)) { + ulockfrm(); + return(-1); + } + if ((lParam&alClient) && (CLUIFramesGetalClientFrame() >= 0)) { //only one alClient frame possible + alclientFrame = -1;//recalc it + ulockfrm(); + return -1; + } + Frames[pos].align = lParam; + ulockfrm(); + return(0); + } + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + return -1; +} + +static INT_PTR CLUIFramesShowAll(WPARAM wParam, LPARAM lParam) +{ + int i; + lParam = 0; + + if (FramesSysNotStarted) + return -1; + + for (i = 0;i < nFramescount;i++) + Frames[i].visible = TRUE; + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + return 0; +} + +INT_PTR CLUIFramesShowAllTitleBars(WPARAM wParam, LPARAM lParam) +{ + int i; + lParam = 0; + + if (FramesSysNotStarted) + return -1; + + for (i = 0;i < nFramescount;i++) { + Frames[i].TitleBar.ShowTitleBar = TRUE; + SetWindowPos(Frames[i].hWnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + } + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + CLUI::Redraw(); + return 0; +} + +//wparam=lparam=0 +INT_PTR CLUIFramesHideAllTitleBars(WPARAM wParam, LPARAM lParam) +{ + int i; + lParam = 0; + + if (FramesSysNotStarted) + return -1; + + for (i = 0;i < nFramescount;i++) { + Frames[i].TitleBar.ShowTitleBar = FALSE; + SetWindowPos(Frames[i].hWnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + } + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + CLUI::Redraw(); + return 0; +} + +//wparam=frameid +INT_PTR CLUIFramesShowHideFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + lParam = 0; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && !lstrcmp(Frames[pos].name, _T("My Contacts"))) + Frames[pos].visible = 1; + else { + if (pos >= 0 && (int)pos < nFramescount) + Frames[pos].visible = !Frames[pos].visible; + if (Frames[pos].floating) + CLUIFrameResizeFloatingFrame(pos); + } + ulockfrm(); + if (!Frames[pos].floating) + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + CLUI::Redraw(); + return 0; +} + +//wparam=frameid +INT_PTR CLUIFramesShowHideFrameTitleBar(WPARAM wParam, LPARAM lParam) +{ + int pos; + lParam = 0; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && (int)pos < nFramescount) { + Frames[pos].TitleBar.ShowTitleBar = !Frames[pos].TitleBar.ShowTitleBar; + SetWindowPos(Frames[pos].hWnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + } + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + CLUI::Redraw(); + return 0; +} + + +//wparam=frameid +//lparam=-1 up ,1 down +INT_PTR CLUIFramesMoveUpDown(WPARAM wParam, LPARAM lParam) +{ + int pos, i, curpos, curalign, v, tmpval; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && (int)pos < nFramescount) { + curpos = Frames[pos].order; + curalign = Frames[pos].align; + v = 0; + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + for (i = 0;i < nFramescount;i++) { + if (Frames[i].floating || (!Frames[i].visible) || (Frames[i].align != curalign)) + continue; + g_sd[v].order = Frames[i].order; + g_sd[v].realpos = i; + v++; + } + if (v == 0) { + ulockfrm(); + return(0); + } + qsort(g_sd, v, sizeof(SortData), sortfunc); + for (i = 0;i < v;i++) { + if (g_sd[i].realpos == pos) { + if (lParam == -1) { + if (i < 1) break; + tmpval = Frames[g_sd[i-1].realpos].order; + Frames[g_sd[i-1].realpos].order = Frames[pos].order; + Frames[pos].order = tmpval; + break; + } + if (lParam == 1) { + if (i > v - 1) break; + tmpval = Frames[g_sd[i+1].realpos].order; + Frames[g_sd[i+1].realpos].order = Frames[pos].order; + Frames[pos].order = tmpval; + break; + } + } + } + ulockfrm(); + CLUIFramesReSort(); + //CLUIFramesStoreAllFrames(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + } + return(0); +} + +static INT_PTR CLUIFramesMoveUp(WPARAM wParam, LPARAM lParam) +{ + lParam = -1; + return(CLUIFramesMoveUpDown(wParam, lParam)); +} + +static INT_PTR CLUIFramesMoveDown(WPARAM wParam, LPARAM lParam) +{ + lParam = 1; + return(CLUIFramesMoveUpDown(wParam, lParam)); +} + + +//wparam=frameid +//lparam=alignment +INT_PTR CLUIFramesSetAlign(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) return -1; + + CLUIFramesSetFrameOptions(MAKEWPARAM(FO_ALIGN, wParam), lParam); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + CLUI::Redraw(); + return(0); +} +INT_PTR CLUIFramesSetAlignalTop(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) + return -1; + + lParam = 0; + return CLUIFramesSetAlign(wParam, alTop); +} +INT_PTR CLUIFramesSetAlignalBottom(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) + return -1; + + lParam = 0; + return CLUIFramesSetAlign(wParam, alBottom); +} +INT_PTR CLUIFramesSetAlignalClient(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) + return -1; + + lParam = 0; + return CLUIFramesSetAlign(wParam, alClient); +} + + +//wparam=frameid +INT_PTR CLUIFramesLockUnlockFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && (int)pos < nFramescount) { + Frames[pos].Locked = !Frames[pos].Locked; + CLUIFramesStoreFrameSettings(pos); + } + ulockfrm(); + return 0; +} + +//wparam=frameid +INT_PTR CLUIFramesSetUnSetBorder(WPARAM wParam, LPARAM lParam) +{ + return(0); +} + +//wparam=frameid +INT_PTR CLUIFramesSetUnSetSkinned(WPARAM wParam, LPARAM lParam) +{ + RECT rc; + int FrameId, oldflags; + HWND hw; + boolean flt; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + FrameId = id2pos((INT_PTR)wParam); + if (FrameId == -1) { + ulockfrm(); + return(-1); + } + flt = oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, wParam), 0); + + if (oldflags & F_SKINNED) + oldflags &= ~F_SKINNED; + else + oldflags |= F_SKINNED; + + hw = Frames[FrameId].hWnd; + GetWindowRect(hw, &rc); + ulockfrm(); + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, wParam), oldflags); + SetWindowPos(hw, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_NOZORDER); + return(0); +} + +//wparam=frameid +INT_PTR CLUIFramesCollapseUnCollapseFrame(WPARAM wParam, LPARAM lParam) +{ + int FrameId; + + if (FramesSysNotStarted) + return -1; + + TitleBarH = cfg::dat.titleBarHeight; + lockfrm(); + FrameId = id2pos((INT_PTR)wParam); + if (FrameId >= 0 && FrameId < nFramescount) { + int oldHeight; + + // do not collapse/uncollapse client/locked/invisible frames + if (Frames[FrameId].align == alClient && !(Frames[FrameId].Locked || (!Frames[FrameId].visible) || Frames[FrameId].floating)) { + RECT rc; + if (CallService(MS_CLIST_DOCKINGISDOCKED, 0, 0)) { + ulockfrm(); + return 0; + } + if (cfg::getByte("CLUI", "AutoSize", 0)) { + ulockfrm(); + return 0; + } + GetWindowRect(pcli->hwndContactList, &rc); + + if (Frames[FrameId].collapsed == TRUE) { + rc.bottom -= rc.top; + rc.bottom -= Frames[FrameId].height; + Frames[FrameId].HeightWhenCollapsed = Frames[FrameId].height; + Frames[FrameId].collapsed = FALSE; + } else { + rc.bottom -= rc.top; + rc.bottom += Frames[FrameId].HeightWhenCollapsed; + Frames[FrameId].collapsed = TRUE; + } + + SetWindowPos(pcli->hwndContactList, NULL, 0, 0, rc.right - rc.left, rc.bottom, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); + + CLUIFramesStoreAllFrames(); + ulockfrm(); + CLUI::Redraw(); + return 0; + + } + if (Frames[FrameId].Locked || (!Frames[FrameId].visible)) { + ulockfrm(); + return 0; + } + + oldHeight = Frames[FrameId].height; + + // if collapsed, uncollapse + if (Frames[FrameId].collapsed == TRUE) { + Frames[FrameId].HeightWhenCollapsed = Frames[FrameId].height; + Frames[FrameId].height = UNCOLLAPSED_FRAME_SIZE; + Frames[FrameId].collapsed = FALSE; + } + // if uncollapsed, collapse + else { + Frames[FrameId].height = Frames[FrameId].HeightWhenCollapsed; + Frames[FrameId].collapsed = TRUE; + } + + if (!Frames[FrameId].floating) { + + if (!CLUIFramesFitInSize()) { + //cant collapse,we can resize only for height<alclient frame height + int alfrm = CLUIFramesGetalClientFrame(); + + if (alfrm != -1) { + Frames[FrameId].collapsed = FALSE; + if (Frames[alfrm].height > 2*UNCOLLAPSED_FRAME_SIZE) { + oldHeight = Frames[alfrm].height - UNCOLLAPSED_FRAME_SIZE; + Frames[FrameId].collapsed = TRUE; + } + } else { + int i, sumheight = 0; + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].align != alClient) && (!Frames[i].floating) && (Frames[i].visible) && (!Frames[i].needhide)) { + sumheight += (Frames[i].height) + (TitleBarH * btoint(Frames[i].TitleBar.ShowTitleBar)) + 2; + ulockfrm(); + return FALSE; + } + if (sumheight > ContactListHeight - 0 - 2) + Frames[FrameId].height = (ContactListHeight - 0 - 2) - sumheight; + } + } + Frames[FrameId].height = oldHeight; + if (Frames[FrameId].collapsed == FALSE) { + if (Frames[FrameId].floating) + SetWindowPos(Frames[FrameId].ContainerWnd, HWND_TOP, 0, 0, Frames[FrameId].wndSize.right - Frames[FrameId].wndSize.left + 6, Frames[FrameId].height + DEFAULT_TITLEBAR_HEIGHT + 4, SWP_SHOWWINDOW | SWP_NOMOVE); + ulockfrm(); + return -1; + } + } + } + ulockfrm(); + if (!Frames[FrameId].floating) + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + else { + RECT contwnd; + GetWindowRect(Frames[FrameId].ContainerWnd, &contwnd); + contwnd.top = contwnd.bottom - contwnd.top;//height + contwnd.left = contwnd.right - contwnd.left;//width + + contwnd.top -= (oldHeight - Frames[FrameId].height);//newheight + SetWindowPos(Frames[FrameId].ContainerWnd, HWND_TOP, 0, 0, contwnd.left, contwnd.top, SWP_SHOWWINDOW | SWP_NOMOVE); + } + CLUI::Redraw(); + CLUIFramesStoreAllFrames(); + return(0); + } else { + ulockfrm(); + return -1; + } +} + +static int CLUIFramesLoadMainMenu() +{ + if (FramesSysNotStarted) + return -1; + + if (cont.MainMenuItem != NULL) { + Menu_RemoveItem(cont.MainMenuItem); + cont.MainMenuItem = NULL; + } + + // create root menu + CMenuItem mi; + mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_FRAME); + mi.position = 3000090000; + mi.name.a = LPGEN("Frames"); + mi.pszService = 0; + cont.MainMenuItem = Menu_AddMainMenuItem(&mi); + + // create frames menu + mi.root = cont.MainMenuItem; + int separator = (int)3000200000; + for (int i = 0; i < nFramescount; i++) { + mi.hIcolibItem = Frames[i].TitleBar.hicon; + mi.flags = CMIF_TCHAR; + mi.position = separator; + mi.name.t = Frames[i].TitleBar.tbname ? Frames[i].TitleBar.tbname : Frames[i].name; + mi.pszService = 0; + Frames[i].MenuHandles.MainMenuItem = Menu_AddMainMenuItem(&mi); + CLUIFramesCreateMenuForFrame(Frames[i].id, Frames[i].MenuHandles.MainMenuItem, separator, true); + CLUIFramesModifyMainMenuItems(Frames[i].id, 0); + CallService(MS_CLIST_FRAMEMENUNOTIFY, (WPARAM)Frames[i].id, (LPARAM)Frames[i].MenuHandles.MainMenuItem); + separator++; + } + + separator += 100000; + + // create "show all frames" menu + mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_MIRANDA); + mi.flags = 0; + mi.position = separator++; + mi.name.a = LPGEN("Show all frames"); + mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMES; + Menu_AddMainMenuItem(&mi); + + // create "show all titlebars" menu + mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_HELP); + mi.position = separator++; + mi.name.a = LPGEN("Show all title bars"); + mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMESTB; + Menu_AddMainMenuItem(&mi); + + // create "hide all titlebars" menu + mi.position = separator++; + mi.name.a = LPGEN("Hide all title bars"); + mi.pszService = MS_CLIST_FRAMES_HIDEALLFRAMESTB; + Menu_AddMainMenuItem(&mi); + return 0; +} + +static HFONT CLUILoadTitleBarFont() +{ + char facename[] = "MS Shell Dlg"; + HFONT hfont; + LOGFONT logfont; + memset(&logfont, 0, sizeof(logfont)); + memcpy(logfont.lfFaceName, facename, sizeof(facename)); + logfont.lfWeight = FW_NORMAL; + logfont.lfHeight = -10; + hfont = CreateFontIndirect(&logfont); + return hfont; +} + +static int UpdateTBToolTip(int framepos) +{ + { + TOOLINFO ti; + + ZeroMemory(&ti, sizeof(ti)); + ti.cbSize = sizeof(ti); + ti.lpszText = Frames[framepos].TitleBar.tooltip; + ti.hinst = g_hInst; + ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS ; + ti.uId = (UINT_PTR)Frames[framepos].TitleBar.hwnd; + + return(SendMessage(Frames[framepos].TitleBar.hwndTip, TTM_UPDATETIPTEXT, (WPARAM)0, (LPARAM)&ti)); + } + +}; + +int FrameNCPaint(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar) +{ + HDC hdc; + RECT rcWindow, rc; + HWND hwndParent = GetParent(hwnd); + LRESULT result; + + if (hwndParent != pcli->hwndContactList || !cfg::dat.bSkinnedScrollbar) + result = CallWindowProc(oldWndProc, hwnd, WM_NCPAINT, wParam, lParam); + else + result = 0; + + if (pcli && pcli->hwndContactList && GetParent(hwnd) == pcli->hwndContactList) { + if (GetWindowLong(hwnd, GWL_STYLE) & CLS_SKINNEDFRAME) { + TStatusItem *item = Skin::statusItems ? (hasTitleBar ? &Skin::statusItems[ID_EXTBKOWNEDFRAMEBORDERTB] : &Skin::statusItems[ID_EXTBKOWNEDFRAMEBORDER]) : 0; + HDC realDC; + HBITMAP hbmDraw = 0, hbmOld = 0; + + if (item == 0) + return 0; + + GetWindowRect(hwnd, &rcWindow); + rc.left = rc.top = 0; + rc.right = rcWindow.right - rcWindow.left; + rc.bottom = rcWindow.bottom - rcWindow.top; + + hdc = realDC = GetWindowDC(hwnd); + if (hwnd == pcli->hwndContactTree) { + realDC = CreateCompatibleDC(hdc); + hbmDraw = CreateCompatibleBitmap(hdc, rc.right, rc.bottom); + hbmOld = reinterpret_cast<HBITMAP>(SelectObject(realDC, hbmDraw)); + } + + ExcludeClipRect(realDC, item->MARGIN_LEFT, item->MARGIN_TOP, rc.right - item->MARGIN_RIGHT, rc.bottom - item->MARGIN_BOTTOM); + + BitBlt(realDC, 0, 0, rc.right - rc.left, rc.bottom - rc.top, cfg::dat.hdcBg, rcWindow.left - cfg::dat.ptW.x, rcWindow.top - cfg::dat.ptW.y, SRCCOPY); + + Gfx::renderSkinItem(realDC, &rc, item->imageItem); + if (hwnd == pcli->hwndContactTree) { + ExcludeClipRect(hdc, item->MARGIN_LEFT, item->MARGIN_TOP, rc.right - item->MARGIN_RIGHT, rc.bottom - item->MARGIN_BOTTOM); + BitBlt(hdc, 0, 0, rc.right, rc.bottom, realDC, 0, 0, SRCCOPY); + SelectObject(realDC, hbmOld); + DeleteObject(hbmDraw); + DeleteDC(realDC); + } + ReleaseDC(hwnd, hdc); + return 0; + } + } + return result; +} + +int FrameNCCalcSize(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar) +{ + TStatusItem *item = Skin::statusItems ? (hasTitleBar ? &Skin::statusItems[ID_EXTBKOWNEDFRAMEBORDERTB] : &Skin::statusItems[ID_EXTBKOWNEDFRAMEBORDER]) : 0; + LRESULT orig = oldWndProc ? CallWindowProc(oldWndProc, hwnd, WM_NCCALCSIZE, wParam, lParam) : 0; + NCCALCSIZE_PARAMS *nccp = (NCCALCSIZE_PARAMS *)lParam; + DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE); + + if (item == 0 || pcli == 0) + return orig; + + if (item->IGNORED || !(dwStyle & CLS_SKINNEDFRAME) || GetParent(hwnd) != pcli->hwndContactList) + return orig; + + nccp->rgrc[0].left += item->MARGIN_LEFT; + nccp->rgrc[0].right -= item->MARGIN_RIGHT; + nccp->rgrc[0].bottom -= item->MARGIN_BOTTOM; + nccp->rgrc[0].top += item->MARGIN_TOP; + return WVR_REDRAW; +} + +static LRESULT CALLBACK FramesSubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int i; + + WNDPROC oldWndProc = 0; + BOOL hasTitleBar = FALSE; + BOOL fFloating = FALSE; + + for (i = 0; i < nFramescount; i++) { + if (Frames[i].hWnd == hwnd) { + oldWndProc = Frames[i].wndProc; + hasTitleBar = Frames[i].TitleBar.ShowTitleBar; + fFloating = Frames[i].floating; + } + } + switch (msg) { + case WM_NCPAINT: { + if(!fFloating) + return FrameNCPaint(hwnd, oldWndProc ? oldWndProc : DefWindowProc, wParam, lParam, hasTitleBar); + break; + } + case WM_NCCALCSIZE: { + if(!fFloating) + return FrameNCCalcSize(hwnd, oldWndProc, wParam, lParam, hasTitleBar); + break; + } + + case WM_LBUTTONDOWN: { + POINT ptMouse, pt; + RECT rcClient; + + if(!fFloating) + break; + + GetCursorPos(&ptMouse); + pt = ptMouse; + ScreenToClient(hwnd, &ptMouse); + GetClientRect(hwnd, &rcClient); + if ((GetKeyState(VK_CONTROL) & 0x8000)) + return SendMessage(GetParent(hwnd), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + break; + } + + /* + * old method, does not work with all frames, because WM_PRINTCLIENT is + * required. + * + case WM_PAINT: { + PAINTSTRUCT ps; + HDC hdcMem; + RECT rc; + HDC hdc = BeginPaint(hwnd, &ps); + EndPaint(hwnd, &ps); + GetClientRect(hwnd, &rc); + HANDLE hbp = Gfx::InitiateBufferedPaint(hdc, rc, hdcMem); + Gfx::SkinDrawBg(hwnd, hdcMem); + CallWindowProc(oldWndProc, hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT | PRF_CHILDREN | PRF_OWNED); + Gfx::FinalizeBufferedPaint(hbp, &rc, 255); + return(0); + } + */ + + /* + * new method, let the frame paint itself normally and capture it in the buffered + * paint dc. Then set the alpha channel. + */ + case WM_PAINT: { + + if(fFloating) + return(CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam)); + + HDC hdc = GetDC(hwnd); + HDC hdcMem; + RECT rc; + RGBQUAD* rgbdata = 0; + int iWidth; + COLORREF rgbOld[3], rgbNew[3]; + HANDLE hbp = 0; + + GetClientRect(hwnd, &rc); + INIT_PAINT(hdc, rc, hdcMem); + //CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); // let the frame paint itself + Gfx::drawBGFromSurface(hwnd, rc, hdcMem); + /* + * TODO unattractive and lame (and far from failsafe) method to determine + * whether WM_PRINTCLIENT does anything to the target DC. This must be + * improved... + */ + rgbOld[0] = GetPixel(hdcMem, 0, 0); + rgbOld[1] = GetPixel(hdcMem, rc.right, rc.bottom); + rgbOld[2] = GetPixel(hdcMem, 10, 10); + SendMessage(hwnd, WM_PRINTCLIENT, (WPARAM)hdcMem, PRF_CLIENT|PRF_CLIENT|PRF_CHECKVISIBLE); + rgbNew[0] = GetPixel(hdcMem, 0, 0); + rgbNew[1] = GetPixel(hdcMem, rc.right, rc.bottom); + rgbNew[2] = GetPixel(hdcMem, 10, 10); + if(rgbNew[0] == rgbOld[0] && rgbNew[1] == rgbOld[1] && rgbNew[2] == rgbOld[2]) { + CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); // let the frame paint itself + BitBlt(hdcMem, 0, 0, rc.right, rc.bottom, hdc, 0, 0, SRCCOPY | CAPTUREBLT); + } + else { + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + EndPaint(hwnd, &ps); + } + + /* + * set pixel transparency for embedded frames + * NOTE: a buffered paint DC can (and in most cases always is) + * wider than the actual drawing rectangle. That's why we need to consider + * iWidth here. + * + * resulting data must be premultiplied! + */ + if(Skin::settings.fTransparentFrames) { + Api::pfnGetBufferedPaintBits(hbp, &rgbdata, &iWidth); + if(rgbdata && iWidth) { + COLORREF clr = Skin::settings.crFramesColorKey; + BYTE rValue = GetRValue(clr); + BYTE gValue = GetGValue(clr); + BYTE bValue = GetBValue(clr); + BYTE newAlpha = Skin::settings.bFramesAlpha; + + unsigned int uSize = (unsigned int)iWidth * rc.bottom; // BP = 32bit, so width * height gives number of RGBQUADs + for(unsigned int i = 0; i < uSize; i++) { + if(rgbdata[i].rgbBlue == bValue && rgbdata[i].rgbRed == rValue && rgbdata[i].rgbGreen == gValue) { + rgbdata[i].rgbReserved = newAlpha; + rgbdata[i].rgbBlue = rgbdata[i].rgbBlue * newAlpha/255; + rgbdata[i].rgbRed = rgbdata[i].rgbRed * newAlpha/255; + rgbdata[i].rgbGreen = rgbdata[i].rgbGreen * newAlpha/255; + } + else + rgbdata[i].rgbReserved = 255; + } + } + } + FINALIZE_PAINT(hbp, &rc, Skin::settings.fTransparentFrames ? 0 : 255); + ReleaseDC(hwnd, hdc); + return(0); + } + + default: + break; + } + if (oldWndProc) + return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +/* + * re-sort all frames and correct frame ordering + */ + +static int CLUIFramesReSort() +{ + int v = 0, i; + int order = 1; + + lockfrm(); + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + for (i = 0;i < nFramescount;i++) { + if (Frames[i].align != alTop) + continue; + g_sd[v].order = Frames[i].order; + g_sd[v].realpos = i; + v++; + } + if (v > 0) { + qsort(g_sd, v, sizeof(SortData), sortfunc); + for (i = 0; i < v; i++) + Frames[g_sd[i].realpos].order = order++; + } + + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + v = 0; + for (i = 0;i < nFramescount;i++) { + if (Frames[i].align != alBottom) + continue; + g_sd[v].order = Frames[i].order; + g_sd[v].realpos = i; + v++; + } + if (v > 0) { + qsort(g_sd, v, sizeof(SortData), sortfunc); + for (i = 0; i < v; i++) + Frames[g_sd[i].realpos].order = order++; + } + CLUIFramesStoreAllFrames(); + ulockfrm(); + return(0); +} + +//wparam=(CLISTFrame*)clfrm +INT_PTR CLUIFramesAddFrame(WPARAM wParam, LPARAM lParam) +{ + int style, retval; + CLISTFrame *clfrm = (CLISTFrame *)wParam; + + if (pcli->hwndContactList == 0) return -1; + if (FramesSysNotStarted) return -1; + if (clfrm->cbSize != sizeof(CLISTFrame)) return -1; + + lockfrm(); + if (nFramescount >= MAX_FRAMES) { + ulockfrm(); + return -1; + } + if (Frames == NULL) { + Frames = (FRAMEWND*)malloc(sizeof(FRAMEWND) * (MAX_FRAMES + 2)); + ZeroMemory(Frames, sizeof(FRAMEWND) * (MAX_FRAMES + 2)); + } + memset(&Frames[nFramescount], 0, sizeof(FRAMEWND)); + + Frames[nFramescount].id = NextFrameId++; + Frames[nFramescount].align = clfrm->align; + Frames[nFramescount].hWnd = clfrm->hWnd; + Frames[nFramescount].height = clfrm->height; + Frames[nFramescount].TitleBar.hicon = clfrm->hIcon; + //Frames[nFramescount].TitleBar.BackColour; + Frames[nFramescount].floating = FALSE; + + if (clfrm->Flags & F_NO_SUBCONTAINER) + Frames[nFramescount].OwnerWindow = (HWND) - 2; + else + Frames[nFramescount].OwnerWindow = pcli->hwndContactList; + + SetClassLong(clfrm->hWnd, GCL_STYLE, GetClassLong(clfrm->hWnd, GCL_STYLE) & ~(CS_VREDRAW | CS_HREDRAW)); + SetWindowLong(clfrm->hWnd, GWL_STYLE, GetWindowLong(clfrm->hWnd, GWL_STYLE) | WS_CLIPCHILDREN); + + if (GetCurrentThreadId() == GetWindowThreadProcessId(clfrm->hWnd, NULL)) { + if (clfrm->hWnd != pcli->hwndContactTree && clfrm->hWnd != g_hwndViewModeFrame && clfrm->hWnd != g_hwndEventArea) { + Frames[nFramescount].wndProc = (WNDPROC)GetWindowLongPtr(clfrm->hWnd, GWLP_WNDPROC); + SetWindowLongPtr(clfrm->hWnd, GWLP_WNDPROC, (LONG_PTR)FramesSubClassProc); + } + } + + if (clfrm->hWnd == g_hwndEventArea) + wndFrameEventArea = &Frames[nFramescount]; + else if (clfrm->hWnd == pcli->hwndContactTree) + wndFrameCLC = &Frames[nFramescount]; + else if (clfrm->hWnd == g_hwndViewModeFrame) + wndFrameViewMode = &Frames[nFramescount]; + + Frames[nFramescount].dwFlags = clfrm->Flags; + + if (clfrm->name == NULL || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->wname) : lstrlenA(clfrm->name)) == 0) { + wchar_t ptszClassName[ 256 ]; + GetClassName(Frames[nFramescount].hWnd, ptszClassName, _countof(ptszClassName)); + Frames[nFramescount].name = mir_tstrdup(ptszClassName); + } else + Frames[nFramescount].name = (clfrm->Flags & F_UNICODE) ? mir_u2t(clfrm->wname) : mir_a2t(clfrm->name); + + if (IsBadCodePtr((FARPROC)clfrm->TBname) || clfrm->TBname == NULL + || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->TBwname) : lstrlenA(clfrm->TBname)) == 0) + Frames[nFramescount].TitleBar.tbname = mir_tstrdup(Frames[nFramescount].name); + else + Frames[nFramescount].TitleBar.tbname = (clfrm->Flags & F_UNICODE) ? mir_u2t(clfrm->TBwname) : mir_a2t(clfrm->TBname); + + Frames[nFramescount].needhide = FALSE; + Frames[nFramescount].TitleBar.ShowTitleBar = (clfrm->Flags & F_SHOWTB ? TRUE : FALSE); + Frames[nFramescount].TitleBar.ShowTitleBarTip = (clfrm->Flags & F_SHOWTBTIP ? TRUE : FALSE); + + Frames[nFramescount].collapsed = clfrm->Flags & F_UNCOLLAPSED ? FALSE : TRUE; + Frames[nFramescount].Locked = clfrm->Flags & F_LOCKED ? TRUE : FALSE; + Frames[nFramescount].visible = clfrm->Flags & F_VISIBLE ? TRUE : FALSE; + + Frames[nFramescount].Skinned = TRUE; // (clfrm->Flags & F_SKINNED) ? TRUE : FALSE; + + // create frame + Frames[nFramescount].TitleBar.hwnd = + CreateWindow(CLUIFrameTitleBarClassName, Frames[nFramescount].name, WS_CHILD | (Frames[nFramescount].TitleBar.ShowTitleBar ? WS_VISIBLE : 0) | + WS_CLIPCHILDREN, 0, 0, 0, 0, pcli->hwndContactList, NULL, g_hInst, NULL); + + SetWindowLongPtr(Frames[nFramescount].TitleBar.hwnd, GWLP_USERDATA, Frames[nFramescount].id); + + Frames[nFramescount].TitleBar.hwndTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + pcli->hwndContactList, NULL, g_hInst, NULL); + + SetWindowPos(Frames[nFramescount].TitleBar.hwndTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + { + TOOLINFOA ti; + int res; + + ZeroMemory(&ti, sizeof(ti)); + ti.cbSize = sizeof(ti); + ti.lpszText = ""; + ti.hinst = g_hInst; + ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS ; + ti.uId = (UINT_PTR)Frames[nFramescount].TitleBar.hwnd; + res = SendMessageA(Frames[nFramescount].TitleBar.hwndTip, TTM_ADDTOOL, (WPARAM)0, (LPARAM) & ti); + } + + SendMessage(Frames[nFramescount].TitleBar.hwndTip, TTM_ACTIVATE, (WPARAM)Frames[nFramescount].TitleBar.ShowTitleBarTip, 0); + + Frames[nFramescount].oldstyles = GetWindowLong(Frames[nFramescount].hWnd, GWL_STYLE); + Frames[nFramescount].TitleBar.oldstyles = GetWindowLong(Frames[nFramescount].TitleBar.hwnd, GWL_STYLE); + //Frames[nFramescount].FloatingPos.x= + + retval = Frames[nFramescount].id; + Frames[nFramescount].order = nFramescount + 1; + nFramescount++; + + CLUIFramesLoadFrameSettings(id2pos(retval)); + style = GetWindowLong(Frames[nFramescount-1].hWnd, GWL_STYLE); + style &= ~(WS_BORDER); + + style |= Frames[nFramescount-1].Skinned ? CLS_SKINNEDFRAME : 0; + + SetWindowLong(Frames[nFramescount-1].hWnd, GWL_STYLE, style); + SetWindowLong(Frames[nFramescount-1].TitleBar.hwnd, GWL_STYLE, style & ~(WS_VSCROLL | WS_HSCROLL)); + + if (Frames[nFramescount-1].order == 0) { + Frames[nFramescount-1].order = nFramescount; + } + + ulockfrm(); + + alclientFrame = -1;//recalc it + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + + if (Frames[nFramescount-1].floating) { + Frames[nFramescount-1].floating = FALSE; + CLUIFrameSetFloat(retval, 1);//lparam=1 use stored width and height + } + CLUI::Redraw(); + return retval; +} + +static INT_PTR CLUIFramesRemoveFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + + if (pos < 0 || pos > nFramescount) { + ulockfrm(); + return(-1); + } + + { + FRAMEWND *F = &Frames[pos]; + if (F->hWnd == g_hwndEventArea) + wndFrameEventArea = NULL; + else if (F->hWnd == pcli->hwndContactTree) + wndFrameCLC = NULL; + else if (F->hWnd == g_hwndViewModeFrame) + wndFrameViewMode = NULL; + + mir_free(F->name); + mir_free(F->TitleBar.tbname); + mir_free(F->TitleBar.tooltip); + + DestroyWindow(F->hWnd); + F->hWnd = (HWND) - 1; + DestroyWindow(F->TitleBar.hwnd); + F->TitleBar.hwnd = (HWND) - 1; + DestroyWindow(F->ContainerWnd); + F->ContainerWnd = (HWND) - 1; + DestroyMenu(F->TitleBar.hmenu); + } + + RemoveItemFromList(pos, &Frames, &nFramescount); + + ulockfrm(); + if (!cfg::shutDown) { + InvalidateRect(pcli->hwndContactList, NULL, TRUE); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + CLUI::Redraw(); + } + return(0); +} + +INT_PTR CLUIFramesForceUpdateTB(const FRAMEWND *Frame) +{ + if (Frame->TitleBar.hwnd != 0) + RedrawWindow(Frame->TitleBar.hwnd, NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW | RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + return 0; +} + +INT_PTR CLUIFramesForceUpdateFrame(const FRAMEWND *Frame) +{ + if (Frame->hWnd != 0) + RedrawWindow(Frame->hWnd, NULL, NULL, RDW_UPDATENOW | RDW_FRAME | RDW_ERASE | RDW_INVALIDATE); + + if (Frame->floating) + if (Frame->ContainerWnd != 0) RedrawWindow(Frame->ContainerWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + return 0; +} + +int CLUIFrameMoveResize(const FRAMEWND *Frame) +{ + TitleBarH = cfg::dat.titleBarHeight; + // we need to show or hide the frame? + if (Frame->visible && (!Frame->needhide)) { + ShowWindow(Frame->hWnd, SW_SHOW); + ShowWindow(Frame->TitleBar.hwnd, Frame->TitleBar.ShowTitleBar == TRUE ? SW_SHOW : SW_HIDE); + } else { + ShowWindow(Frame->hWnd, SW_HIDE); + ShowWindow(Frame->TitleBar.hwnd, SW_HIDE); + return(0); + } + + SetWindowPos(Frame->hWnd, NULL, Frame->wndSize.left + Skin::metrics.cLeft, Frame->wndSize.top + Skin::metrics.dwTopOffset, + (Frame->wndSize.right - Frame->wndSize.left), + (Frame->wndSize.bottom - Frame->wndSize.top), SWP_NOZORDER | SWP_NOREDRAW); + if (Frame->TitleBar.ShowTitleBar) { + SetWindowPos(Frame->TitleBar.hwnd, NULL, Frame->wndSize.left + Skin::metrics.cLeft, Frame->wndSize.top + Skin::metrics.dwTopOffset - TitleBarH, + (Frame->wndSize.right - Frame->wndSize.left), + TitleBarH, SWP_NOZORDER); + } + return 0; +} + +BOOLEAN CLUIFramesFitInSize(void) +{ + int i; + int sumheight = 0; + int tbh = 0; // title bar height + int clientfrm; + + TitleBarH = cfg::dat.titleBarHeight; + + clientfrm = CLUIFramesGetalClientFrame(); + if (clientfrm != -1) + tbh = TitleBarH * btoint(Frames[clientfrm].TitleBar.ShowTitleBar); + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].align != alClient) && (!Frames[i].floating) && (Frames[i].visible) && (!Frames[i].needhide)) { + sumheight += (Frames[i].height) + (TitleBarH * btoint(Frames[i].TitleBar.ShowTitleBar)) + 2/*+btoint(Frames[i].UseBorder)*2*/; + if (sumheight > ContactListHeight - tbh - 2) + return FALSE; + } + } + return TRUE; +} + +int CLUIFramesGetMinHeight() +{ + int i, tbh, clientfrm, sumheight = 0; + RECT border; + int allbord = 0; + + if (pcli->hwndContactList == NULL) + return 0; + + lockfrm(); + + TitleBarH = cfg::dat.titleBarHeight; + // search for alClient frame and get the titlebar's height + tbh = 0; + clientfrm = CLUIFramesGetalClientFrame(); + if (clientfrm != -1) + tbh = TitleBarH * btoint(Frames[clientfrm].TitleBar.ShowTitleBar); + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].align != alClient) && (Frames[i].visible) && (!Frames[i].needhide) && (!Frames[i].floating)) { + RECT wsize; + + GetWindowRect(Frames[i].hWnd, &wsize); + sumheight += (wsize.bottom - wsize.top) + (TitleBarH * btoint(Frames[i].TitleBar.ShowTitleBar)) + 3; + } + } + ulockfrm(); + GetBorderSize(pcli->hwndContactList, &border); + return(sumheight + border.top + border.bottom + allbord + tbh + 3); +} + +int SizeMoveNewSizes() +{ + int i; + for (i = 0;i < nFramescount;i++) { + + if (Frames[i].floating) { + CLUIFrameResizeFloatingFrame(i); + } else { + CLUIFrameMoveResize(&Frames[i]); + }; + } + return 0; +} + +/* + * changed Nightwish + * gap calculation was broken. Now, it doesn't calculate and store the gaps in Frames[] anymore. + * instead, it remembers the smallest wndSize.top value (which has to be the top frame) and then passes + * the gap to all following frame(s) to the actual resizing function which just adds the gap to + * wndSize.top and corrects the frame height accordingly. + + * Title bar gap has been removed (can be simulated by using a clist_nicer skin item for frame title bars + * and setting the bottom margin of the skin item + */ + +int CLUIFramesResize(const RECT newsize) +{ + int sumheight = 9999999, newheight; + int prevframe, prevframebottomline; + int tbh, curfrmtbh; + int drawitems; + int clientfrm, clientframe = -1; + int i, j; + int sepw; + int topOff = 0, botOff = 0, last_bottomtop;; + + GapBetweenFrames = cfg::dat.gapBetweenFrames; + sepw = GapBetweenFrames; + + if (nFramescount < 1 || cfg::shutDown) + return 0; + + newheight = newsize.bottom - newsize.top; + TitleBarH = cfg::dat.titleBarHeight; + + // search for alClient frame and get the titlebar's height + tbh = 0; + clientfrm = CLUIFramesGetalClientFrame(); + if (clientfrm != -1) + tbh = (TitleBarH) * btoint(Frames[clientfrm].TitleBar.ShowTitleBar); + + for (i = 0;i < nFramescount;i++) { + if (!Frames[i].floating) { + Frames[i].needhide = FALSE; + Frames[i].wndSize.left = 0; + Frames[i].wndSize.right = newsize.right - newsize.left; + } + } + { + //sorting stuff + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + for (i = 0;i < nFramescount;i++) { + g_sd[i].order = Frames[i].order; + g_sd[i].realpos = i; + } + qsort(g_sd, nFramescount, sizeof(SortData), sortfunc); + + } + drawitems = nFramescount; + while (sumheight > (newheight - tbh) && drawitems > 0) { + sumheight = 0; + drawitems = 0; + for (i = 0;i < nFramescount;i++) { + if (((Frames[i].align != alClient)) && (!Frames[i].floating) && (Frames[i].visible) && (!Frames[i].needhide)) { + drawitems++; + curfrmtbh = (TitleBarH) * btoint(Frames[i].TitleBar.ShowTitleBar); + sumheight += (Frames[i].height) + curfrmtbh + (i > 0 ? sepw : 0); + if (sumheight > newheight - tbh) { + sumheight -= (Frames[i].height) + curfrmtbh + (i > 0 ? sepw : 0); + Frames[i].needhide = TRUE; + drawitems--; + break; + } + } + } + } + + prevframe = -1; + prevframebottomline = 0; + for (j = 0;j < nFramescount;j++) { + //move all alTop frames + i = g_sd[j].realpos; + if ((!Frames[i].needhide) && (!Frames[i].floating) && (Frames[i].visible) && (Frames[i].align == alTop)) { + curfrmtbh = (TitleBarH) * btoint(Frames[i].TitleBar.ShowTitleBar); + Frames[i].wndSize.top = prevframebottomline + (prevframebottomline > 0 ? sepw : 0) + (curfrmtbh); + Frames[i].wndSize.bottom = Frames[i].height + Frames[i].wndSize.top; + Frames[i].prevvisframe = prevframe; + prevframe = i; + prevframebottomline = Frames[i].wndSize.bottom; + topOff = prevframebottomline; + } + } + + if (sumheight < newheight) { + for (j = 0;j < nFramescount;j++) { + //move alClient frame + i = g_sd[j].realpos; + if ((!Frames[i].needhide) && (!Frames[i].floating) && (Frames[i].visible) && (Frames[i].align == alClient)) { + int oldh; + Frames[i].wndSize.top = prevframebottomline + (prevframebottomline > 0 ? sepw : 0) + (tbh); + Frames[i].wndSize.bottom = Frames[i].wndSize.top + newheight - sumheight - tbh - ((prevframebottomline > 0) ? sepw : 0); + clientframe = i; + oldh = Frames[i].height; + Frames[i].height = Frames[i].wndSize.bottom - Frames[i].wndSize.top; + Frames[i].prevvisframe = prevframe; + prevframe = i; + prevframebottomline = Frames[i].wndSize.bottom; + if (prevframebottomline > newheight) { + //prevframebottomline-=Frames[i].height+(tbh+1); + //Frames[i].needhide=TRUE; + } + break; + } + } + } + + //newheight + prevframebottomline = last_bottomtop = newheight; + //prevframe=-1; + for (j = nFramescount - 1;j >= 0;j--) { + //move all alBottom frames + i = g_sd[j].realpos; + if ((Frames[i].visible) && (!Frames[i].floating) && (!Frames[i].needhide) && (Frames[i].align == alBottom)) { + curfrmtbh = (TitleBarH) * btoint(Frames[i].TitleBar.ShowTitleBar); + Frames[i].wndSize.bottom = prevframebottomline - ((prevframebottomline < newheight) ? sepw : 0); + Frames[i].wndSize.top = Frames[i].wndSize.bottom - Frames[i].height; + Frames[i].prevvisframe = prevframe; + prevframe = i; + prevframebottomline = Frames[i].wndSize.top - curfrmtbh; + botOff = prevframebottomline; + last_bottomtop = Frames[i].wndSize.top - curfrmtbh; + } + } + + // correct client frame bottom gap if there is no other top frame. + + if (clientframe != -1) { + Frames[clientframe].wndSize.bottom = last_bottomtop - (last_bottomtop < newheight ? sepw : 0); + Frames[clientframe].height = Frames[clientframe].wndSize.bottom - Frames[clientframe].wndSize.top; + } + return 0; +} + +INT_PTR CLUIFramesUpdateFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + if (FramesSysNotStarted) + return -1; + if (wParam == -1) { + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + return 0; + } + if (lParam&FU_FMPOS) + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 1); + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + + if (pos < 0 || pos >= nFramescount) { + ulockfrm(); + return -1; + } + if (lParam&FU_TBREDRAW) + CLUIFramesForceUpdateTB(&Frames[pos]); + if (lParam&FU_FMREDRAW) + CLUIFramesForceUpdateFrame(&Frames[pos]); + ulockfrm(); + return 0; +} + +int dock_prevent_moving = 0; + +int CLUIFramesApplyNewSizes(int mode) +{ + int i; + dock_prevent_moving = 0; + for (i = 0;i < nFramescount;i++) { + if ((mode == 1 && Frames[i].OwnerWindow != (HWND) - 2 && Frames[i].OwnerWindow) || + (mode == 2 && Frames[i].OwnerWindow == (HWND) - 2) || + (mode == 3)) + if (Frames[i].floating) + CLUIFrameResizeFloatingFrame(i); + else + CLUIFrameMoveResize(&Frames[i]); + } + dock_prevent_moving = 1; + return 0; +} + +// RECT old_window_rect = {0}, new_window_rect = {0}; + +int SizeFramesByWindowRect(RECT *r) +{ + RECT nRect; + DWORD noSize = 0; + HDWP hdwp; + + if (FramesSysNotStarted) + return -1; + + TitleBarH = cfg::dat.titleBarHeight; + lockfrm(); + GapBetweenFrames = cfg::dat.gapBetweenFrames; + + nRect = *r; + + nRect.bottom -= (Skin::metrics.bSBarHeight + Skin::metrics.dwBottomOffset); + nRect.right -= Skin::metrics.cRight; + nRect.left = Skin::metrics.cLeft; + nRect.top = Skin::metrics.dwTopOffset; + ContactListHeight = nRect.bottom - nRect.top; + + CLUIFramesResize(nRect); + { + int i; + hdwp = BeginDeferWindowPos(20); + for (i = 0;i < nFramescount;i++) { + if (!Frames[i].floating) { + if (Frames[i].OwnerWindow && Frames[i].OwnerWindow != (HWND) - 2) { + hdwp = DeferWindowPos(hdwp, Frames[i].hWnd, NULL, Frames[i].wndSize.left + Skin::metrics.cLeft, Frames[i].wndSize.top + Skin::metrics.dwTopOffset, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + (Frames[i].wndSize.bottom - Frames[i].wndSize.top), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS | noSize); + + if (Frames[i].TitleBar.ShowTitleBar) { + hdwp = DeferWindowPos(hdwp, Frames[i].TitleBar.hwnd, NULL, Frames[i].wndSize.left + Skin::metrics.cLeft, Frames[i].wndSize.top + Skin::metrics.dwTopOffset - TitleBarH, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + TitleBarH, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS); + } + } else { + // set frame position + hdwp = DeferWindowPos(hdwp, Frames[i].hWnd, NULL, Frames[i].wndSize.left + Skin::metrics.cLeft, Frames[i].wndSize.top + Skin::metrics.dwTopOffset, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + (Frames[i].wndSize.bottom - Frames[i].wndSize.top), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOREDRAW); + + // set titlebar position + if (Frames[i].TitleBar.ShowTitleBar) { + hdwp = DeferWindowPos(hdwp, Frames[i].TitleBar.hwnd, NULL, Frames[i].wndSize.left + Skin::metrics.cLeft, Frames[i].wndSize.top + Skin::metrics.dwTopOffset - TitleBarH, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + TitleBarH, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOREDRAW); + } + //UpdateWindow(Frames[i].hWnd); + if (Frames[i].TitleBar.ShowTitleBar) + UpdateWindow(Frames[i].TitleBar.hwnd); + }; + } + + } + EndDeferWindowPos(hdwp); + if (GetTickCount() - LastStoreTick > 1000) { + CLUIFramesStoreAllFrames(); + LastStoreTick = GetTickCount(); + } + } + ulockfrm(); + return 0; +} + +int CLUIFramesOnClistResize(WPARAM wParam, LPARAM lParam) +{ + RECT nRect; + int tick; + GapBetweenFrames = cfg::dat.gapBetweenFrames; + + if (FramesSysNotStarted || cfg::shutDown) + return -1; + + lockfrm(); + + GetClientRect(pcli->hwndContactList, &nRect); + if (lParam && lParam != 1) { + RECT oldRect; + POINT pt; + RECT * newRect = (RECT *)lParam; + int dl, dt, dr, db; + GetWindowRect(pcli->hwndContactList, &oldRect); + pt.x = nRect.left; + pt.y = nRect.top; + ClientToScreen(pcli->hwndContactList, &pt); + dl = pt.x - oldRect.left; + dt = pt.y - oldRect.top; + dr = (oldRect.right - oldRect.left) - (nRect.right - nRect.left) - dl; + db = (oldRect.bottom - oldRect.top) - (nRect.bottom - nRect.top) - dt; + nRect.left = newRect->left + dl; + nRect.top = newRect->top + dt; + nRect.bottom = newRect->bottom - db; + nRect.right = newRect->right - dr; + } + + nRect.bottom -= (Skin::metrics.bSBarHeight + Skin::metrics.dwBottomOffset); + nRect.right -= Skin::metrics.cRight; + nRect.left = Skin::metrics.cLeft; + nRect.top = Skin::metrics.dwTopOffset; + ContactListHeight = nRect.bottom - nRect.top; + + tick = GetTickCount(); + + CLUIFramesResize(nRect); + CLUIFramesApplyNewSizes(3); + + ulockfrm(); + tick = GetTickCount() - tick; + + if (pcli->hwndContactList != 0) { + InvalidateRect(pcli->hwndContactList, NULL, TRUE); + //UpdateWindow(pcli->hwndContactList); + } + + Sleep(0); + + if (GetTickCount() - LastStoreTick > 2000) { + CLUIFramesStoreAllFrames(); + LastStoreTick = GetTickCount(); + } + return 0; +} + +boolean AlignCOLLIconToLeft; //will hide frame icon + +int OnFrameTitleBarBackgroundChange() +{ + CLUIFramesOnClistResize(0, 0); + return 0; +} + +static int DrawTitleBar(HDC dc, RECT& rect, int Frameid) +{ + HDC hdcMem; + HANDLE hbp = 0; + HBRUSH hBack; + int pos; + TStatusItem *item = &Skin::statusItems[ID_EXTBKFRAMETITLE]; + + /* + * no need to redraw anything while shutting down + */ + if (cfg::shutDown) + return 0; + + TitleBarH = cfg::dat.titleBarHeight; + + hBack = GetSysColorBrush(COLOR_3DFACE); + + lockfrm(); + pos = id2pos(Frameid); + + if (pos >= 0 && pos < nFramescount) { + HFONT oFont; + HWND hwnd = Frames[pos].TitleBar.hwnd; + RECT rc; + BOOL isFloat = Frames[pos].floating; + + INIT_PAINT(dc, rect, hdcMem); + SetBkMode(hdcMem, TRANSPARENT); + + GetClientRect(hwnd, &Frames[pos].TitleBar.wndSize); + rc = Frames[pos].TitleBar.wndSize; + + if (cfg::clcdat) + oFont = reinterpret_cast<HFONT>(SelectObject(hdcMem, cfg::clcdat->fontInfo[FONTID_FRAMETITLE].hFont)); + else + oFont = reinterpret_cast<HFONT>(SelectObject(hdcMem, GetStockObject(DEFAULT_GUI_FONT))); + + if(!isFloat) + Gfx::drawBGFromSurface(hwnd, rc, hdcMem); + else + FillRect(hdcMem, &rect, hBack); + + if (!item->IGNORED) { + RGBQUAD* rgb = 0; + int iWidth; + Api::pfnGetBufferedPaintBits(hbp, &rgb, &iWidth); + AGGPaintHelper* ph = new AGGPaintHelper(hdcMem); + ph->aggctx->attach(rgb, iWidth, rc.bottom); + ph->current_shape = 0; + rc.top += item->MARGIN_TOP; + rc.bottom -= item->MARGIN_BOTTOM; + rc.left += item->MARGIN_LEFT; + rc.right -= item->MARGIN_RIGHT; + Gfx::renderSkinItem(ph, item, &rc); + //Gfx::renderSkinItem(hdcMem, &rc, item->imageItem); + Gfx::setTextColor(item->TEXTCOLOR); + delete ph; + } else if (cfg::clcdat) { + FillRect(hdcMem, &rect, hBack); + Gfx::setTextColor(cfg::clcdat->fontInfo[FONTID_FRAMETITLE].colour); + } else { + FillRect(hdcMem, &rect, hBack); + Gfx::setTextColor(GetSysColor(COLOR_BTNTEXT)); + } + + HANDLE hTheme = Api::pfnOpenThemeData(hwnd, L"BUTTON"); + + if (!AlignCOLLIconToLeft) { + rc.right -= (CXSMICON + 3); + if (Frames[pos].TitleBar.hicon != NULL) { + rc.left += (CXSMICON + 8); + DrawIconEx(hdcMem, 6, ((TitleBarH >> 1) - 8), Frames[pos].TitleBar.hicon, 16, 16, 0, NULL, DI_NORMAL); + Gfx::renderText(hdcMem, hTheme, Frames[pos].TitleBar.tbname, &rc, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS, 0); + } else { + rc.left += 4; + Gfx::renderText(hdcMem, hTheme, Frames[pos].TitleBar.tbname, &rc, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS, 0); + } + } else { + rc.left += (CXSMICON + 6); + Gfx::renderText(hdcMem, hTheme, Frames[pos].TitleBar.tbname, &rc, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS, 0); + } + + Api::pfnCloseThemeData(hTheme); + + if (!AlignCOLLIconToLeft) + DrawIconEx(hdcMem, Frames[pos].TitleBar.wndSize.right - 22, ((TitleBarH >> 1) - 8), Frames[pos].collapsed ? Skin_LoadIcon(SKINICON_OTHER_GROUPOPEN) : Skin_LoadIcon(SKINICON_OTHER_GROUPSHUT), 16, 16, 0, NULL, DI_NORMAL); + else + DrawIconEx(hdcMem, 0, ((TitleBarH >> 1) - 8), Frames[pos].collapsed ? Skin_LoadIcon(SKINICON_OTHER_GROUPOPEN) : Skin_LoadIcon(SKINICON_OTHER_GROUPSHUT), 16, 16, 0, NULL, DI_NORMAL); + SelectObject(hdcMem, oFont); + + DeleteObject(hBack); + FINALIZE_PAINT(hbp, &rect, 0); + } + ulockfrm(); + return 0; +} + +#define MPCF_CONTEXTFRAMEMENU 3 +POINT ptOld; +short nLeft = 0; +short nTop = 0; + +LRESULT CALLBACK CLUIFrameTitleBarProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + RECT rect; + int Frameid, Framemod, direction; + int xpos, ypos; + + Frameid = GetWindowLongPtr(hwnd, GWLP_USERDATA); + memset(&rect, 0, sizeof(rect)); + + switch (msg) { + case WM_CREATE: + return FALSE; + + case WM_MEASUREITEM: + return Menu_MeasureItem((LPMEASUREITEMSTRUCT)lParam); + + case WM_DRAWITEM: + return Menu_DrawItem((LPDRAWITEMSTRUCT)lParam); + + case WM_ENABLE: + if (hwnd != 0) InvalidateRect(hwnd, NULL, FALSE); + return 0; + + case WM_SIZE: + return 0; + /* + case WM_PRINT: + case WM_PRINTCLIENT: + InvalidateRect(hwnd,NULL,FALSE); + { + RECT rect; + HDC dc; + GetClientRect(hwnd,&rect); + //DrawTitleBar(wParam,rect,Frameid); + SendMessage(hwnd,WM_PAINT,0,0); + SendMessage(hwnd,WM_NCPAINT,1,0); + dc=GetDC(hwnd); + SendMessage(hwnd,WM_ERASEBKGND,dc,0); + ReleaseDC(hwnd,dc); + SendMessage(hwnd,WM_PAINT,0,0); + // UpdateWindow(hwnd); + return(0); + } + */ + /* + case WM_NCPAINT: + { + + // if(wParam==1) break; + { POINT ptTopLeft={0,0}; + HRGN hClientRgn; + ClientToScreen(hwnd,&ptTopLeft); + hClientRgn=CreateRectRgn(0,0,1,1); + CombineRgn(hClientRgn,(HRGN)wParam,NULL,RGN_COPY); + OffsetRgn(hClientRgn,-ptTopLeft.x,-ptTopLeft.y); + InvalidateRgn(hwnd,hClientRgn,FALSE); + DeleteObject(hClientRgn); + UpdateWindow(hwnd); + } + //return(0); + }; + */ + + + case WM_COMMAND: + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), 0), Frameid)) + break; + + if (HIWORD(wParam) == 0) {//mouse events for self created menu + int framepos = id2pos(Frameid); + if (framepos == -1) + break; + + switch (LOWORD(wParam)) { + case frame_menu_lock: + Frames[framepos].Locked = !Frames[framepos].Locked; + break; + case frame_menu_visible: + Frames[framepos].visible = !Frames[framepos].visible; + break; + case frame_menu_showtitlebar: + Frames[framepos].TitleBar.ShowTitleBar = !Frames[framepos].TitleBar.ShowTitleBar; + break; + case frame_menu_floating: + CLUIFrameSetFloat(Frameid, 0); + break; + } + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + } + + break; + case WM_RBUTTONDOWN: { + HMENU hmenu; + POINT pt; + GetCursorPos(&pt); + + if (ServiceExists(MS_CLIST_MENUBUILDFRAMECONTEXT)) { + hmenu = (HMENU)CallService(MS_CLIST_MENUBUILDFRAMECONTEXT, Frameid, 0); + } else { + int framepos = id2pos(Frameid); + + lockfrm(); + if (framepos == -1) { + ulockfrm(); + break; + } + hmenu = CreatePopupMenu(); + AppendMenu(hmenu, MF_STRING | MF_DISABLED | MF_GRAYED, 15, Frames[framepos].name); + AppendMenu(hmenu, MF_SEPARATOR, 16, _T("")); + + if (Frames[framepos].Locked) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_lock, TranslateT("Lock Frame")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_lock, TranslateT("Lock Frame")); + + if (Frames[framepos].visible) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_visible, TranslateT("Visible")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_visible, TranslateT("Visible")); + + if (Frames[framepos].TitleBar.ShowTitleBar) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_showtitlebar, TranslateT("Show TitleBar")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_showtitlebar, TranslateT("Show TitleBar")); + + if (Frames[framepos].Skinned) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_skinned, TranslateT("Skinned frame")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_skinned, TranslateT("Skinned frame")); + + if (Frames[framepos].floating) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_floating, TranslateT("Floating")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_floating, TranslateT("Floating")); + + ulockfrm(); + } + TrackPopupMenu(hmenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, 0); + DestroyMenu(hmenu); + } + break; + case WM_LBUTTONDBLCLK: { + Framemod = -1; + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + CallService(MS_CLIST_FRAMES_UCOLLFRAME, Frameid, 0); + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + } + break; + + case WM_LBUTTONUP: { + if (GetCapture() != hwnd) { + break; + }; + curdragbar = -1; + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + CLUI::Redraw(); + break; + }; + case WM_LBUTTONDOWN: { + + int framepos = id2pos(Frameid); + lockfrm(); + if (framepos == -1) { + ulockfrm(); + break; + } + if (Frames[framepos].floating) { + + POINT pt; + GetCursorPos(&pt); + Frames[framepos].TitleBar.oldpos = pt; + } + + if ((!(wParam & MK_CONTROL)) && Frames[framepos].Locked && (!(Frames[framepos].floating))) { + if (cfg::getByte("CLUI", "ClientAreaDrag", 0)) { + POINT pt; + GetCursorPos(&pt); + ulockfrm(); + return SendMessage(GetParent(hwnd), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + } + } + if (Frames[framepos].floating) { + RECT rc; + GetCursorPos(&ptOld); + GetWindowRect(hwnd, &rc); + nLeft = (short)rc.left; + nTop = (short)rc.top; + } + ulockfrm(); + SetCapture(hwnd); + break; + } + case WM_MOUSEMOVE: { + POINT pt, pt2; + RECT wndr; + int pos; + { + char TBcapt[255]; + + lockfrm(); + pos = id2pos(Frameid); + + if (pos != -1) { + int oldflags; + wsprintfA(TBcapt, "%s - h:%d, vis:%d, fl:%d, fl:(%d,%d,%d,%d),or: %d", + Frames[pos].name, Frames[pos].height, Frames[pos].visible, Frames[pos].floating, + Frames[pos].FloatingPos.x, Frames[pos].FloatingPos.y, + Frames[pos].FloatingSize.x, Frames[pos].FloatingSize.y, + Frames[pos].order + ); + + oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, Frames[pos].id), (LPARAM)0); + if (!(oldflags&F_SHOWTBTIP)) + oldflags |= F_SHOWTBTIP; + } + ulockfrm(); + } + if ((wParam & MK_LBUTTON)) { + RECT rcMiranda; + RECT rcwnd, rcOverlap; + POINT newpt, ofspt, curpt, newpos; + + lockfrm(); + + pos = id2pos(Frameid); + if (Frames[pos].floating) { + GetCursorPos(&curpt); + rcwnd.bottom = curpt.y + 5; + rcwnd.top = curpt.y; + rcwnd.left = curpt.x; + rcwnd.right = curpt.x + 5; + + GetWindowRect(pcli->hwndContactList, &rcMiranda); + if (IsWindowVisible(pcli->hwndContactList) && IntersectRect(&rcOverlap, &rcwnd, &rcMiranda)) { + int id = Frames[pos].id; + + ulockfrm(); + ofspt.x = 0; + ofspt.y = 0; + ClientToScreen(Frames[pos].TitleBar.hwnd, &ofspt); + ofspt.x = curpt.x - ofspt.x; + ofspt.y = curpt.y - ofspt.y; + + CLUIFrameSetFloat(id, 0); + newpt.x = 0; + newpt.y = 0; + ClientToScreen(Frames[pos].TitleBar.hwnd, &newpt); + SetCursorPos(newpt.x + ofspt.x, newpt.y + ofspt.y); + GetCursorPos(&curpt); + lockfrm(); + Frames[pos].TitleBar.oldpos = curpt; + ulockfrm(); + return(0); + } + } else { + int id = Frames[pos].id; + + GetCursorPos(&curpt); + rcwnd.bottom = curpt.y + 5; + rcwnd.top = curpt.y; + rcwnd.left = curpt.x; + rcwnd.right = curpt.x + 5; + + GetWindowRect(pcli->hwndContactList, &rcMiranda); + + if (!IntersectRect(&rcOverlap, &rcwnd, &rcMiranda)) { + ulockfrm(); + GetCursorPos(&curpt); + GetWindowRect(Frames[pos].hWnd, &rcwnd); + rcwnd.left = rcwnd.right - rcwnd.left; + rcwnd.top = rcwnd.bottom - rcwnd.top; + newpos.x = curpt.x; + newpos.y = curpt.y; + if (curpt.x >= (rcMiranda.right - 1)) { + newpos.x = curpt.x + 5; + } + if (curpt.x <= (rcMiranda.left + 1)) { + newpos.x = curpt.x - (rcwnd.left) - 5; + } + if (curpt.y >= (rcMiranda.bottom - 1)) { + newpos.y = curpt.y + 5; + } + if (curpt.y <= (rcMiranda.top + 1)) { + newpos.y = curpt.y - (rcwnd.top) - 5; + }; + ofspt.x = 0; + ofspt.y = 0; + GetWindowRect(Frames[pos].TitleBar.hwnd, &rcwnd); + ofspt.x = curpt.x - ofspt.x; + ofspt.y = curpt.y - ofspt.y; + Frames[pos].FloatingPos.x = newpos.x; + Frames[pos].FloatingPos.y = newpos.y; + CLUIFrameSetFloat(id, 0); + lockfrm(); + newpt.x = 0; + newpt.y = 0; + ClientToScreen(Frames[pos].TitleBar.hwnd, &newpt); + GetWindowRect(Frames[pos].hWnd, &rcwnd); + SetCursorPos(newpt.x + (rcwnd.right - rcwnd.left) / 2, newpt.y + (rcwnd.bottom - rcwnd.top) / 2); + GetCursorPos(&curpt); + Frames[pos].TitleBar.oldpos = curpt; + ulockfrm(); + return(0); + } + } + ulockfrm(); + } + if (wParam & MK_LBUTTON) { + int newh = -1, prevold; + + if (GetCapture() != hwnd) + break; + + lockfrm(); + pos = id2pos(Frameid); + + if (Frames[pos].floating) { + GetCursorPos(&pt); + if ((Frames[pos].TitleBar.oldpos.x != pt.x) || (Frames[pos].TitleBar.oldpos.y != pt.y)) { + + pt2 = pt; + ScreenToClient(hwnd, &pt2); + GetWindowRect(Frames[pos].ContainerWnd, &wndr); + { + int dX, dY; + POINT ptNew; + + ptNew.x = pt.x; + ptNew.y = pt.y; + + dX = ptNew.x - ptOld.x; + dY = ptNew.y - ptOld.y; + + nLeft += (short)dX; + nTop += (short)dY; + + if (!(wParam&MK_CONTROL)) { + PositionThumb(&Frames[pos], nLeft, nTop); + } else { + + SetWindowPos(Frames[pos].ContainerWnd, + 0, + nLeft, + nTop, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + } + ptOld = ptNew; + } + pt.x = nLeft; + pt.y = nTop; + Frames[pos].TitleBar.oldpos = pt; + } + ulockfrm(); + return(0); + } + if (Frames[pos].prevvisframe != -1) { + GetCursorPos(&pt); + + if ((Frames[pos].TitleBar.oldpos.x == pt.x) && (Frames[pos].TitleBar.oldpos.y == pt.y)) { + ulockfrm(); + break; + } + + ypos = rect.top + pt.y; + xpos = rect.left + pt.x; + Framemod = -1; + + if (Frames[pos].align == alBottom) { + direction = -1; + Framemod = pos; + } else { + direction = 1; + Framemod = Frames[pos].prevvisframe; + } + if (Frames[Framemod].Locked) { + ulockfrm(); + break; + } + if (curdragbar != -1 && curdragbar != pos) { + ulockfrm(); + break; + } + if (lbypos == -1) { + curdragbar = pos; + lbypos = ypos; + oldframeheight = Frames[Framemod].height; + SetCapture(hwnd); + ulockfrm(); + break;; + } + newh = oldframeheight + direction * (ypos - lbypos); + if (newh > 0) { + prevold = Frames[Framemod].height; + Frames[Framemod].height = newh; + if (!CLUIFramesFitInSize()) { + Frames[Framemod].height = prevold; + ulockfrm(); + return TRUE; + } + Frames[Framemod].height = newh; + if (newh > 3) Frames[Framemod].collapsed = TRUE; + } + Frames[pos].TitleBar.oldpos = pt; + } + ulockfrm(); + if (newh > 0) + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + break; + } + curdragbar = -1; + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + } + break; + + case WM_PRINT: + case WM_PRINTCLIENT: { + GetClientRect(hwnd, &rect); + DrawTitleBar((HDC)wParam, rect, Frameid); + } + case WM_PAINT: { + HDC paintDC; + PAINTSTRUCT paintStruct; + + paintDC = BeginPaint(hwnd, &paintStruct); + rect = paintStruct.rcPaint; + DrawTitleBar(paintDC, rect, Frameid); + EndPaint(hwnd, &paintStruct); + return 0; + } + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return TRUE; +} +int CLUIFrameResizeFloatingFrame(int framepos) +{ + + int width, height, floatingHeight; + RECT rect; + + if (!Frames[framepos].floating) + return(0); + if (Frames[framepos].ContainerWnd == 0) + return(0); + GetClientRect(Frames[framepos].ContainerWnd, &rect); + + width = rect.right - rect.left; + height = rect.bottom - rect.top; + floatingHeight = cfg::dat.titleBarHeight; + + if(floatingHeight <= 0 || floatingHeight > 50) + floatingHeight = 18; + + Frames[framepos].visible ? ShowWindow(Frames[framepos].ContainerWnd, SW_SHOWNOACTIVATE) : ShowWindow(Frames[framepos].ContainerWnd, SW_HIDE); + + if (Frames[framepos].TitleBar.ShowTitleBar) { + ShowWindow(Frames[framepos].TitleBar.hwnd, SW_SHOWNOACTIVATE); + Frames[framepos].height = height - floatingHeight; + SetWindowPos(Frames[framepos].TitleBar.hwnd, HWND_TOP, 0, 0, width, floatingHeight, SWP_SHOWWINDOW | SWP_DRAWFRAME | SWP_NOACTIVATE); + InvalidateRect(Frames[framepos].TitleBar.hwnd, NULL, FALSE); + SetWindowPos(Frames[framepos].hWnd, HWND_TOP, 0, floatingHeight, width, height - floatingHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE); + + } else { + Frames[framepos].height = height; + ShowWindow(Frames[framepos].TitleBar.hwnd, SW_HIDE); + SetWindowPos(Frames[framepos].hWnd, HWND_TOP, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE); + } + + if (Frames[framepos].ContainerWnd != 0) + UpdateWindow(Frames[framepos].ContainerWnd); + GetWindowRect(Frames[framepos].hWnd, &Frames[framepos].wndSize); + + if (Frames[framepos].TitleBar.ShowTitleBar) + RedrawWindow(Frames[framepos].TitleBar.hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); + RedrawWindow(Frames[framepos].hWnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); + + return(0); +} + +static int CLUIFrameOnMainMenuBuild(WPARAM wParam, LPARAM lParam) +{ + CLUIFramesLoadMainMenu(); + return 0; +} + +LRESULT CALLBACK CLUIFrameContainerWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + INT_PTR Frameid = GetWindowLongPtr(hwnd, GWLP_USERDATA); + switch (msg) { + case WM_CREATE: { + int framepos; + lockfrm(); + framepos = id2pos(Frameid); + ulockfrm(); + return(0); + } + case WM_GETMINMAXINFO: { + int framepos; + MINMAXINFO minmax; + + TitleBarH = cfg::dat.titleBarHeight; + lockfrm(); + + framepos = id2pos(Frameid); + if (framepos < 0 || framepos >= nFramescount) { + ulockfrm(); + break; + } + if (!Frames[framepos].minmaxenabled) { + ulockfrm(); + break; + } + if (Frames[framepos].ContainerWnd == 0) { + ulockfrm(); + break; + } + if (Frames[framepos].Locked) { + RECT rct; + + GetWindowRect(hwnd, &rct); + ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = rct.right - rct.left; + ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rct.bottom - rct.top; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = rct.right - rct.left; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = rct.bottom - rct.top; + } + + memset(&minmax, 0, sizeof(minmax)); + if (SendMessage(Frames[framepos].hWnd, WM_GETMINMAXINFO, (WPARAM)0, (LPARAM)&minmax) == 0) { + RECT border; + int tbh = TitleBarH * btoint(Frames[framepos].TitleBar.ShowTitleBar); + GetBorderSize(hwnd, &border); + if (minmax.ptMaxTrackSize.x != 0 && minmax.ptMaxTrackSize.y != 0) { + + ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = minmax.ptMinTrackSize.x; + ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = minmax.ptMinTrackSize.y; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = minmax.ptMaxTrackSize.x + border.left + border.right; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = minmax.ptMaxTrackSize.y + tbh + border.top + border.bottom; + } + } else { + ulockfrm(); + return(DefWindowProc(hwnd, msg, wParam, lParam)); + } + ulockfrm(); + } + + case WM_NCHITTEST: { + LRESULT result; + RECT r; + POINT pt; + + GetWindowRect(hwnd, &r); + GetCursorPos(&pt); + if (pt.y <= r.bottom && pt.y >= r.bottom - 6) { + if (pt.x > r.left + 10 && pt.x < r.right - 10) + return HTBOTTOM; + if (pt.x < r.left + 10) + return HTBOTTOMLEFT; + if (pt.x > r.right - 10) + return HTBOTTOMRIGHT; + + } else if (pt.y >= r.top && pt.y <= r.top + 3) { + if (pt.x > r.left + 10 && pt.x < r.right - 10) + return HTTOP; + if (pt.x < r.left + 10) + return HTTOPLEFT; + if (pt.x > r.right - 10) + return HTTOPRIGHT; + } else if (pt.x >= r.left && pt.x <= r.left + 6) + return HTLEFT; + else if (pt.x >= r.right - 6 && pt.x <= r.right) + return HTRIGHT; + + result = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam); + if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT || result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT) + return HTCLIENT; + + return result; + } + + case WM_MOVE: { + int framepos; + RECT rect; + + lockfrm(); + framepos = id2pos(Frameid); + + if (framepos < 0 || framepos >= nFramescount) { + ulockfrm(); + break; + } + if (Frames[framepos].ContainerWnd == 0) { + ulockfrm(); + return(0); + } + GetWindowRect(Frames[framepos].ContainerWnd, &rect); + Frames[framepos].FloatingPos.x = rect.left; + Frames[framepos].FloatingPos.y = rect.top; + Frames[framepos].FloatingSize.x = rect.right - rect.left; + Frames[framepos].FloatingSize.y = rect.bottom - rect.top; + CLUIFramesStoreFrameSettings(framepos); + ulockfrm(); + return(0); + } + + case WM_SIZE: { + int framepos; + RECT rect; + lockfrm(); + + framepos = id2pos(Frameid); + + if (framepos < 0 || framepos >= nFramescount) { + ulockfrm(); + break; + } + if (Frames[framepos].ContainerWnd == 0) { + ulockfrm(); + return(0); + } + CLUIFrameResizeFloatingFrame(framepos); + + GetWindowRect(Frames[framepos].ContainerWnd, &rect); + Frames[framepos].FloatingPos.x = rect.left; + Frames[framepos].FloatingPos.y = rect.top; + Frames[framepos].FloatingSize.x = rect.right - rect.left; + Frames[framepos].FloatingSize.y = rect.bottom - rect.top; + CLUIFramesStoreFrameSettings(framepos); + ulockfrm(); + return(0); + } + case WM_CLOSE: { + DestroyWindow(hwnd); + break; + } + case WM_DESTROY: + return(0); + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static HWND CreateContainerWindow(HWND parent, int x, int y, int width, int height) +{ + return(CreateWindowExA(0, "FramesContainer", "", WS_POPUP | WS_BORDER, x, y, width, height, parent, 0, g_hInst, 0)); +} + + +INT_PTR CLUIFrameSetFloat(WPARAM wParam, LPARAM lParam) +{ + HWND hwndtmp, hwndtooltiptmp; + + lockfrm(); + wParam = id2pos((INT_PTR)wParam); + if (wParam >= 0 && (int)wParam < nFramescount) + if (Frames[wParam].floating) { + SetParent(Frames[wParam].hWnd, pcli->hwndContactList); + SetParent(Frames[wParam].TitleBar.hwnd, pcli->hwndContactList); + Frames[wParam].floating = FALSE; + DestroyWindow(Frames[wParam].ContainerWnd); + Frames[wParam].ContainerWnd = 0; + } else { + RECT recttb, rectw, border; + int temp; + int neww, newh; + bool locked; + + Frames[wParam].oldstyles = GetWindowLong(Frames[wParam].hWnd, GWL_STYLE); + Frames[wParam].TitleBar.oldstyles = GetWindowLong(Frames[wParam].TitleBar.hwnd, GWL_STYLE); + locked = Frames[wParam].Locked; + Frames[wParam].Locked = FALSE; + Frames[wParam].minmaxenabled = FALSE; + + GetWindowRect(Frames[wParam].hWnd, &rectw); + GetWindowRect(Frames[wParam].TitleBar.hwnd, &recttb); + if (!Frames[wParam].TitleBar.ShowTitleBar) { + recttb.top = recttb.bottom = recttb.left = recttb.right = 0; + } + Frames[wParam].ContainerWnd = CreateContainerWindow(pcli->hwndContactList, Frames[wParam].FloatingPos.x, Frames[wParam].FloatingPos.y, 10, 10); + + SetParent(Frames[wParam].hWnd, Frames[wParam].ContainerWnd); + SetParent(Frames[wParam].TitleBar.hwnd, Frames[wParam].ContainerWnd); + + GetBorderSize(Frames[wParam].ContainerWnd, &border); + + SetWindowLongPtr(Frames[wParam].ContainerWnd, GWLP_USERDATA, Frames[wParam].id); + if ((lParam == 1)) { + if ((Frames[wParam].FloatingPos.x != 0) && (Frames[wParam].FloatingPos.y != 0)) { + if (Frames[wParam].FloatingPos.x < 20) { + Frames[wParam].FloatingPos.x = 40; + } + if (Frames[wParam].FloatingPos.y < 20) { + Frames[wParam].FloatingPos.y = 40; + } + SetWindowPos(Frames[wParam].ContainerWnd, HWND_TOPMOST, Frames[wParam].FloatingPos.x, Frames[wParam].FloatingPos.y, Frames[wParam].FloatingSize.x, Frames[wParam].FloatingSize.y, SWP_HIDEWINDOW); + } else { + SetWindowPos(Frames[wParam].ContainerWnd, HWND_TOPMOST, 120, 120, 140, 140, SWP_HIDEWINDOW); + } + } else { + neww = rectw.right - rectw.left + border.left + border.right; + newh = (rectw.bottom - rectw.top) + (recttb.bottom - recttb.top) + border.top + border.bottom; + if (neww < 20) { + neww = 40; + } + if (newh < 20) { + newh = 40; + } + if (Frames[wParam].FloatingPos.x < 20) { + Frames[wParam].FloatingPos.x = 40; + } + if (Frames[wParam].FloatingPos.y < 20) { + Frames[wParam].FloatingPos.y = 40; + } + SetWindowPos(Frames[wParam].ContainerWnd, HWND_TOPMOST, Frames[wParam].FloatingPos.x, Frames[wParam].FloatingPos.y, neww, newh, SWP_HIDEWINDOW); + } + SetWindowText(Frames[wParam].ContainerWnd, Frames[wParam].TitleBar.tbname); + temp = GetWindowLong(Frames[wParam].ContainerWnd, GWL_EXSTYLE); + temp |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST ; + SetWindowLong(Frames[wParam].ContainerWnd, GWL_EXSTYLE, temp); + Frames[wParam].floating = TRUE; + Frames[wParam].Locked = locked; + + } + CLUIFramesStoreFrameSettings(wParam); + Frames[wParam].minmaxenabled = TRUE; + hwndtooltiptmp = Frames[wParam].TitleBar.hwndTip; + + hwndtmp = Frames[wParam].ContainerWnd; + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + SendMessage(hwndtmp, WM_SIZE, 0, 0); + SetWindowPos(hwndtooltiptmp, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + return 0; +} + +wchar_t g_ptszEventName[100]; + +static int CLUIFrameOnModulesLoad(WPARAM, LPARAM) +{ + mir_sntprintf(g_ptszEventName, _countof(g_ptszEventName), _T("mf_update_evt_%d"), GetCurrentThreadId()); + g_hEventThread = CreateEvent(NULL, TRUE, FALSE, g_ptszEventName); + hThreadMFUpdate = mir_forkthread(MF_UpdateThread, NULL); + SetThreadPriority(hThreadMFUpdate, THREAD_PRIORITY_IDLE); + CLUIFramesLoadMainMenu(); + CLUIFramesCreateMenuForFrame(-1, NULL, 000010000, false); + return 0; +} + +static int CLUIFrameOnModulesUnload(WPARAM, LPARAM) +{ + mf_updatethread_running = FALSE; + + SetThreadPriority(hThreadMFUpdate, THREAD_PRIORITY_NORMAL); + SetEvent(g_hEventThread); + WaitForSingleObject(hThreadMFUpdate, 2000); + CloseHandle(g_hEventThread); + + Menu_RemoveItem(cont.MIVisible); + Menu_RemoveItem(cont.MITitle); + Menu_RemoveItem(cont.MITBVisible); + Menu_RemoveItem(cont.MILock); + Menu_RemoveItem(cont.MIColl); + Menu_RemoveItem(cont.MIFloating); + Menu_RemoveItem(cont.MIAlignRoot); + Menu_RemoveItem(cont.MIAlignTop); + Menu_RemoveItem(cont.MIAlignClient); + Menu_RemoveItem(cont.MIAlignBottom); + Menu_RemoveItem(cont.MIBorder); + return 0; +} + +/* +static INT_PTR SetIconForExtraColumn(WPARAM wParam, LPARAM lParam) +{ + pIconExtraColumn piec; + + if (pcli->hwndContactTree == 0) + return -1; + + if (wParam == 0 || lParam == 0 || IsBadCodePtr((FARPROC)lParam)) + return -1; + + piec = (pIconExtraColumn)lParam; + + if (piec->cbSize != sizeof(IconExtraColumn)) + return -1; + + if (cfg::dat.bMetaAvail && cfg::dat.bMetaEnabled && cfg::getByte((HANDLE)wParam, cfg::dat.szMetaName, "IsSubcontact", 0)) + PostMessage(pcli->hwndContactTree, CLM_SETEXTRAIMAGEINTMETA, wParam, MAKELONG((WORD)piec->ColumnType, (WORD)piec->hImage)); + else + PostMessage(pcli->hwndContactTree, CLM_SETEXTRAIMAGEINT, wParam, MAKELONG((WORD)piec->ColumnType, (WORD)piec->hImage)); + return 0; +} +*/ + +/* + * wparam=hIcon + * return hImage on success,-1 on failure + */ +static INT_PTR AddIconToExtraImageList(WPARAM wParam, LPARAM lParam) +{ + if (CLUI::hExtraImages == 0 || wParam == 0) + return -1; + + return((int)ImageList_AddIcon(CLUI::hExtraImages, (HICON)wParam)); +} + +/* +static INT_PTR SkinDrawBgService(WPARAM wParam, LPARAM lParam) +{ + StatusItems_t item; + HWND hwnd; + RECT rc; + + SKINDRAWREQUEST *sdrq = (SKINDRAWREQUEST *)wParam; + + if(wParam == 0 || IsBadCodePtr((FARPROC)wParam) || pDrawAlpha == NULL) + return 0; + + hwnd = WindowFromDC(sdrq->hDC); + GetClientRect(hwnd, &rc); + if(strstr(sdrq->szObjectID, "/Background") && EqualRect(&sdrq->rcClipRect, &sdrq->rcDestRect)) { + SkinDrawBg(hwnd, sdrq->hDC); + GetItemByStatus(ID_EXTBKEVTAREA, &item); + if(item.IGNORED) + FillRect(sdrq->hDC, &(sdrq->rcClipRect), GetSysColorBrush(COLOR_3DFACE)); + else { + DrawAlpha(sdrq->hDC, &(sdrq->rcClipRect), item.COLOR, item.ALPHA, item.COLOR2, item.COLOR2_TRANSPARENT, + item.GRADIENT, item.CORNER, item.BORDERSTYLE, item.imageItem); + } + } + else { + GetItemByStatus(ID_EXTBKEVTAREA, &item); + if(item.IGNORED) + FillRect(sdrq->hDC, &(sdrq->rcClipRect), GetSysColorBrush(COLOR_3DFACE)); + else { + DrawAlpha(sdrq->hDC, &(sdrq->rcClipRect), item.COLOR, item.ALPHA, item.COLOR2, item.COLOR2_TRANSPARENT, + item.GRADIENT, item.CORNER, item.BORDERSTYLE, item.imageItem); + } + } +} +*/ + +void RegisterCLUIFrameClasses() +{ + WNDCLASS wndclass; + WNDCLASS cntclass; + + wndclass.style = CS_DBLCLKS;//|CS_HREDRAW|CS_VREDRAW ; + wndclass.lpfnWndProc = CLUIFrameTitleBarProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = g_hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = NULL; + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = CLUIFrameTitleBarClassName; + RegisterClass(&wndclass); + + cntclass.style = CS_DBLCLKS/*|CS_HREDRAW|CS_VREDRAW*/ | CS_DROPSHADOW; + cntclass.lpfnWndProc = CLUIFrameContainerWndProc; + cntclass.cbClsExtra = 0; + cntclass.cbWndExtra = 0; + cntclass.hInstance = g_hInst; + cntclass.hIcon = NULL; + cntclass.hCursor = LoadCursor(NULL, IDC_ARROW); + cntclass.hbrBackground = NULL; + cntclass.lpszMenuName = NULL; + cntclass.lpszClassName = _T("FramesContainer"); + RegisterClass(&cntclass); +} + +int LoadCLUIFramesModule(void) +{ + GapBetweenFrames = cfg::dat.gapBetweenFrames; + + nFramescount = 0; + InitializeCriticalSection(&csFrameHook); + //InitFramesMenus(); + + HookEvent(ME_SYSTEM_MODULESLOADED, CLUIFrameOnModulesLoad); + HookEvent(ME_CLIST_PREBUILDFRAMEMENU, CLUIFramesModifyContextMenuForFrame); + HookEvent(ME_CLIST_PREBUILDMAINMENU, CLUIFrameOnMainMenuBuild); + HookEvent(ME_SYSTEM_PRESHUTDOWN, CLUIFrameOnModulesUnload); + + CreateServiceFunction(MS_CLIST_FRAMES_ADDFRAME, CLUIFramesAddFrame); + CreateServiceFunction(MS_CLIST_FRAMES_REMOVEFRAME, CLUIFramesRemoveFrame); + + CreateServiceFunction(MS_CLIST_FRAMES_SETFRAMEOPTIONS, CLUIFramesSetFrameOptions); + CreateServiceFunction(MS_CLIST_FRAMES_GETFRAMEOPTIONS, CLUIFramesGetFrameOptions); + CreateServiceFunction(MS_CLIST_FRAMES_UPDATEFRAME, CLUIFramesUpdateFrame); + + CreateServiceFunction(MS_CLIST_FRAMES_SHFRAMETITLEBAR, CLUIFramesShowHideFrameTitleBar); + CreateServiceFunction(MS_CLIST_FRAMES_SHOWALLFRAMESTB, CLUIFramesShowAllTitleBars); + CreateServiceFunction(MS_CLIST_FRAMES_HIDEALLFRAMESTB, CLUIFramesHideAllTitleBars); + CreateServiceFunction(MS_CLIST_FRAMES_SHFRAME, CLUIFramesShowHideFrame); + CreateServiceFunction(MS_CLIST_FRAMES_SHOWALLFRAMES, CLUIFramesShowAll); + + CreateServiceFunction(MS_CLIST_FRAMES_ULFRAME, CLUIFramesLockUnlockFrame); + CreateServiceFunction(MS_CLIST_FRAMES_UCOLLFRAME, CLUIFramesCollapseUnCollapseFrame); + CreateServiceFunction(MS_CLIST_FRAMES_SETUNBORDER, CLUIFramesSetUnSetBorder); + CreateServiceFunction(MS_CLIST_FRAMES_SETSKINNED, CLUIFramesSetUnSetSkinned); + + CreateServiceFunction(CLUIFRAMESSETALIGN, CLUIFramesSetAlign); + CreateServiceFunction(CLUIFRAMESMOVEDOWN, CLUIFramesMoveDown); + CreateServiceFunction(CLUIFRAMESMOVEUP, CLUIFramesMoveUp); + + CreateServiceFunction(CLUIFRAMESSETALIGNALTOP, CLUIFramesSetAlignalTop); + CreateServiceFunction(CLUIFRAMESSETALIGNALCLIENT, CLUIFramesSetAlignalClient); + CreateServiceFunction(CLUIFRAMESSETALIGNALBOTTOM, CLUIFramesSetAlignalBottom); + + CreateServiceFunction("Set_Floating", CLUIFrameSetFloat); + hWndExplorerToolBar = FindWindowExA(0, 0, "Shell_TrayWnd", NULL); + OnFrameTitleBarBackgroundChange(); + + FramesSysNotStarted = FALSE; + CLUI::hPenFrames = CreatePen(PS_SOLID, 1, cfg::getDword("CLUI", "clr_frameborder", GetSysColor(COLOR_3DDKSHADOW))); + return 0; +} + +void CLUI::loadExtraIconModule() +{ + hExtraImageListRebuilding = CreateHookableEvent(ME_CLIST_EXTRA_LIST_REBUILD); + hExtraImageApplying = CreateHookableEvent(ME_CLIST_EXTRA_IMAGE_APPLY); + + hStatusBarShowToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_SHOW_TOOLTIP); + hStatusBarHideToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_HIDE_TOOLTIP); +} + +int UnLoadCLUIFramesModule(void) +{ + int i; + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + CLUIFramesStoreAllFrames(); + DeleteObject(CLUI::hPenFrames); + EnterCriticalSection(&csFrameHook); + FramesSysNotStarted = TRUE; + for (i = 0;i < nFramescount;i++) { + DestroyWindow(Frames[i].hWnd); + Frames[i].hWnd = (HWND) - 1; + DestroyWindow(Frames[i].TitleBar.hwnd); + Frames[i].TitleBar.hwnd = (HWND) - 1; + DestroyWindow(Frames[i].ContainerWnd); + Frames[i].ContainerWnd = (HWND) - 1; + DestroyMenu(Frames[i].TitleBar.hmenu); + + if (Frames[i].name != NULL) + mir_free(Frames[i].name); + if (Frames[i].TitleBar.tbname != NULL) + mir_free(Frames[i].TitleBar.tbname); + } + if (Frames) + free(Frames); + Frames = NULL; + nFramescount = 0; + UnregisterClass(CLUIFrameTitleBarClassName, g_hInst); + LeaveCriticalSection(&csFrameHook); + DeleteCriticalSection(&csFrameHook); + //UnitFramesMenu(); + return 0; +} + +void CLUI::reloadExtraIcons() +{ + NotifyEventHooks(hExtraImageListRebuilding, 0, 0); +} diff --git a/plugins/Clist_ng/CLUIFrames/cluiframes.h b/plugins/Clist_ng/CLUIFrames/cluiframes.h new file mode 100644 index 0000000000..c56b471ab3 --- /dev/null +++ b/plugins/Clist_ng/CLUIFrames/cluiframes.h @@ -0,0 +1,171 @@ +/*
+Miranda ICQ: the free icq client for MS Windows
+Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede
+
+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.
+*/
+
+#pragma once
+
+#ifndef _CLUIFRAMES_H_
+#define _CLUIFRAMES_H_
+
+#include <vector>
+#include <memory>
+
+int LoadCLUIFramesModule(void);
+int UnLoadCLUIFramesModule(void);
+int CLUIFramesGetMinHeight();
+int CLUIFramesOnClistResize(WPARAM wParam, LPARAM lParam);
+int SizeFramesByWindowRect(RECT *r);
+int CLUIFramesResizeFrames(RECT *rc);
+
+typedef struct tagProtocolData {
+ char *RealName;
+ int protopos;
+ boolean show;
+} ProtocolData;
+
+typedef struct
+{
+ int order;
+ int realpos;
+}SortData;
+
+//============
+#define CLUIFRAMESSETALIGN "CLUIFramesSetAlign"
+
+#define CLUIFRAMESSETALIGNALTOP "CLUIFramesSetAlignalTop"
+#define CLUIFRAMESSETALIGNALCLIENT "CLUIFramesSetAlignalClient"
+#define CLUIFRAMESSETALIGNALBOTTOM "CLUIFramesSetAlignalBottom"
+#define CLUIFRAMESMOVEUP "CLUIFramesMoveUp"
+#define CLUIFRAMESMOVEDOWN "CLUIFramesMoveDown"
+
+struct FrameMenuHandles
+{
+ HGENMENU MainMenuItem;
+ HGENMENU MIVisible, MITitle, MITBVisible, MILock, MIColl, MIFloating, MIAlignRoot;
+ HGENMENU MIAlignTop, MIAlignClient, MIAlignBottom;
+ HGENMENU MIBorder, MISkinned;
+};
+
+struct FrameTitleBar
+{
+ HWND hwnd;
+ HWND TitleBarbutt;
+ HWND hwndTip;
+
+ LPTSTR tbname;
+ LPTSTR tooltip;
+
+ HMENU hmenu;
+ HICON hicon;
+
+ bool ShowTitleBar;
+ bool ShowTitleBarTip;
+ int oldstyles;
+ POINT oldpos;
+ RECT wndSize;
+};
+
+struct DockOpt
+{
+ HWND hwndLeft;
+ HWND hwndRight;
+};
+
+struct FRAMEWND
+{
+ int id;
+ HWND hWnd;
+ RECT wndSize;
+ LPTSTR name;
+ int align;
+ int height;
+ int dwFlags;
+ bool Locked;
+ bool visible;
+ bool needhide;
+ bool collapsed;
+ bool floating;
+ bool minmaxenabled;
+ bool UseBorder;
+ int prevvisframe;
+ int HeightWhenCollapsed;
+ FrameTitleBar TitleBar;
+ FrameMenuHandles MenuHandles;
+ int oldstyles;
+ HWND ContainerWnd;
+ POINT FloatingPos;
+ POINT FloatingSize;
+ int order;
+ DockOpt dockOpt;
+ HWND OwnerWindow;
+ bool Skinned;
+ RECT oldWndSize;
+ WNDPROC wndProc;
+};
+
+#define OFFSET_PROTOPOS 200
+#define OFFSET_VISIBLE 400
+
+#define CLUIFrameTitleBarClassName _T("CLUIFrameTitleBar")
+#define CLUIFrameModule "CLUIFrames"
+
+class CLUIFrames {
+
+public:
+ CLUIFrames() {
+ InitializeCriticalSection(&csFrameHook);
+ }
+
+ ~CLUIFrames() {
+ DeleteCriticalSection(&csFrameHook);
+ }
+ static CLUIFrames& getInstance() {
+ static CLUIFrames _instance;
+
+ return _instance;
+ }
+
+private:
+ bool isRunning;
+
+ FRAMEWND *Frames;
+ FRAMEWND *wndFrameCLC, *wndFrameEventArea, *wndFrameViewMode;
+
+ size_t nFramescount;
+ CRITICAL_SECTION csFrameHook;
+ std::vector<std::unique_ptr<FRAMEWND>> m_Frames;
+
+ // inline functions
+ int __forceinline btoint(BOOLEAN b)
+ {
+ return(b ? 1 : 0);
+ }
+
+ void __forceinline lockfrm()
+ {
+ if (isRunning)
+ EnterCriticalSection(&csFrameHook);
+ }
+
+ void __forceinline ulockfrm()
+ {
+ LeaveCriticalSection(&csFrameHook);
+ }
+};
+#endif
+
diff --git a/plugins/Clist_ng/CLUIFrames/framesmenu.cpp b/plugins/Clist_ng/CLUIFrames/framesmenu.cpp new file mode 100644 index 0000000000..9cd0d60df4 --- /dev/null +++ b/plugins/Clist_ng/CLUIFrames/framesmenu.cpp @@ -0,0 +1,116 @@ +#include <commonheaders.h>
+
+//========================== Frames
+HANDLE hFrameMenuObject;
+static HANDLE hPreBuildFrameMenuEvent;
+
+//contactmenu exec param(ownerdata)
+//also used in checkservice
+typedef struct{
+ char *szServiceName;
+ int Frameid;
+ INT_PTR param1;
+} FrameMenuExecParam, *lpFrameMenuExecParam;
+
+INT_PTR FreeOwnerDataFrameMenu(WPARAM wParam, LPARAM lParam)
+{
+ lpFrameMenuExecParam cmep = (lpFrameMenuExecParam)lParam;
+ if (cmep != NULL){
+ mir_free(cmep->szServiceName);
+ mir_free(cmep);
+ }
+ return 0;
+}
+
+static INT_PTR AddContextFrameMenuItem(WPARAM wParam, LPARAM lParam)
+{
+ CMenuItem *mi = (CMenuItem *)lParam;
+
+ TMO_MenuItem tmi;
+ if (!pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ tmi.root = (mi->flags & CMIF_ROOTHANDLE) ? mi->hParentMenu : NULL;
+
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)mir_alloc(sizeof(FrameMenuExecParam));
+ if (fmep == NULL)
+ return 0;
+
+ fmep->szServiceName = mir_strdup(mi->pszService);
+ fmep->Frameid = mi->popupPosition;
+ fmep->param1 = (INT_PTR)mi->pszContactOwner;
+ tmi.ownerdata = fmep;
+
+ return CallService(MO_ADDNEWMENUITEM, (WPARAM)hFrameMenuObject, (LPARAM)&tmi);
+}
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR FrameMenuExecService(WPARAM wParam, LPARAM lParam)
+{
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)wParam;
+ if (fmep == NULL)
+ return -1;
+
+ CallService(fmep->szServiceName, lParam, fmep->param1);
+ RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
+ return 0;
+}
+
+//true - ok,false ignore
+INT_PTR FrameMenuCheckService(WPARAM wParam, LPARAM lParam)
+{
+ PCheckProcParam pcpp = (PCheckProcParam)wParam;
+ if (pcpp == NULL)
+ return FALSE;
+
+ TMO_MenuItem mi;
+ if (CallService(MO_GETMENUITEM, (WPARAM)pcpp->MenuItemHandle, (LPARAM)&mi) == 0) {
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)mi.ownerdata;
+ if (fmep != NULL) {
+ //pcpp->wParam - frameid
+ if (((WPARAM)fmep->Frameid == pcpp->wParam) || fmep->Frameid == -1)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static INT_PTR ContextFrameMenuNotify(WPARAM wParam, LPARAM lParam)
+{
+ NotifyEventHooks(hPreBuildFrameMenuEvent, wParam, lParam);
+ return 0;
+}
+
+static INT_PTR BuildContextFrameMenu(WPARAM wParam, LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hFrameMenuObject;
+ param.wParam = wParam;
+ param.lParam = lParam;
+
+ HMENU hMenu = CreatePopupMenu();
+ ContextFrameMenuNotify(wParam, -1);
+ CallService(MO_BUILDMENU, (WPARAM)hMenu, (LPARAM)¶m);
+ return (INT_PTR)hMenu;
+}
+
+//========================== Frames end
+
+int InitFramesMenus(void)
+{
+ CreateServiceFunction("FrameMenuExecService", FrameMenuExecService);
+ CreateServiceFunction("FrameMenuCheckService", FrameMenuCheckService);
+ CreateServiceFunction("FrameMenuFreeService", FreeOwnerDataFrameMenu);
+
+ CreateServiceFunction("CList/AddContextFrameMenuItem", AddContextFrameMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDFRAMECONTEXT, BuildContextFrameMenu);
+ CreateServiceFunction(MS_CLIST_FRAMEMENUNOTIFY, ContextFrameMenuNotify);
+ hPreBuildFrameMenuEvent = CreateHookableEvent(ME_CLIST_PREBUILDFRAMEMENU);
+
+ // frame menu object
+ hFrameMenuObject = MO_CreateMenuObject("FrameMenu", LPGEN("Frame menu"), "FrameMenuCheckService", "FrameMenuExecService");
+ MO_SetMenuObjectParam(hFrameMenuObject, OPT_MENUOBJECT_SET_FREE_SERVICE, "FrameMenuFreeService");
+ return 0;
+}
diff --git a/plugins/Clist_ng/CLUIFrames/groupmenu.cpp b/plugins/Clist_ng/CLUIFrames/groupmenu.cpp new file mode 100644 index 0000000000..f7567b5527 --- /dev/null +++ b/plugins/Clist_ng/CLUIFrames/groupmenu.cpp @@ -0,0 +1,573 @@ +/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
+Copyright (c) 2000-03 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.
+*/
+
+#include <commonheaders.h>
+
+//////////////////////////////Group MENU/////////////////////////
+HANDLE hGroupMenuObject;
+HANDLE hPreBuildGroupMenuEvent;
+
+HGENMENU hGroupMainMenuItemProxy;
+HGENMENU hHideShowMainMenuItem;
+HGENMENU hGroupStatusMenuItemProxy;
+HGENMENU hAppearanceMenuItemProxy;
+HGENMENU hEventAreaMenuItemProxy;
+
+static HMENU hMenuOldContext;
+
+HGENMENU hHideOfflineUsersMenuItem;
+HGENMENU hHideOfflineUsersOutHereMenuItem;
+HGENMENU hHideEmptyGroupsMenuItem;
+HGENMENU hDisableGroupsMenuItem;
+HGENMENU hNewGroupMenuItem;
+HGENMENU hNewSubGroupMenuItem;
+
+void InitSubGroupMenus(void);
+
+//Groupmenu exec param(ownerdata)
+typedef struct {
+ char *szServiceName;
+ int Param1, Param2;
+} GroupMenuExecParam, *lpGroupMenuExecParam;
+
+static INT_PTR BuildGroupMenu(WPARAM wParam, LPARAM lParam)
+{
+ int tick;
+ HMENU hMenu;
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hGroupMenuObject;
+
+ //hMenu = hMainMenu;
+ hMenu = CreatePopupMenu();
+ //hMenu = wParam;
+ tick = GetTickCount();
+
+ NotifyEventHooks(hPreBuildGroupMenuEvent, 0, 0);
+
+ CallService(MO_BUILDMENU, (WPARAM)hMenu, (LPARAM)¶m);
+ //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0));
+ tick = GetTickCount() - tick;
+ return (INT_PTR)hMenu;
+}
+
+static INT_PTR AddGroupMenuItem(WPARAM wParam, LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM *)lParam;
+ if (!pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)mir_alloc(sizeof(GroupMenuExecParam));
+ if (mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ lpGroupMenuParam gmp = (lpGroupMenuParam)wParam;
+ if (gmp != NULL) {
+ mmep->Param1 = gmp->wParam;
+ mmep->Param2 = gmp->lParam;
+ }
+ tmi.ownerdata = mmep;
+
+ char buf[1024];
+ mir_snprintf(buf, SIZEOF(buf), "%s/%s", mi->pszService, mi->pszName);
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM, (WPARAM)hGroupMenuObject, (LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)buf;
+ CallService(MO_SETOPTIONSMENUITEM, 0, (LPARAM)&op);
+ return (INT_PTR)op.Handle;
+}
+
+INT_PTR GroupMenuCheckService(WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+INT_PTR GroupMenuonAddService(WPARAM wParam, LPARAM lParam)
+{
+ MENUITEMINFO *mii = (MENUITEMINFO *)wParam;
+ if (mii == NULL) return 0;
+
+ if (hHideShowMainMenuItem == (HANDLE)lParam) {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+
+ }
+ if (hGroupMainMenuItemProxy == (HANDLE)lParam) {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN, 0, 0);
+ }
+
+ if (hGroupStatusMenuItemProxy == (HANDLE)lParam) {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS, 0, 0);
+ }
+ if (hAppearanceMenuItemProxy == (HANDLE)lParam) {
+ hMenuOldContext = GetSubMenu(LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)), 3);
+ TranslateMenu(hMenuOldContext);
+
+ CheckMenuItem(hMenuOldContext, POPUP_FRAME, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hMenuOldContext, POPUP_BUTTONS, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hMenuOldContext, POPUP_SHOWMETAICONS, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_USEMETAICONS ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hMenuOldContext, POPUP_SHOWSTATUSICONS, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_FRAME_STATUSICONS ? MF_CHECKED : MF_UNCHECKED));
+
+ mii->fMask |= MIIM_SUBMENU;
+ mii->hSubMenu = (HMENU)hMenuOldContext;
+ }
+ return (TRUE);
+};
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR GroupMenuExecService(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam != 0) {
+ lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)wParam;
+ if (!strcmp(mmep->szServiceName, "Help/AboutCommand")) {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ CallService(mmep->szServiceName, mmep->Param1, lParam);
+ }
+ else
+ CallService(mmep->szServiceName, mmep->Param1, mmep->Param2);
+
+ }
+ return 1;
+}
+
+INT_PTR FreeOwnerDataGroupMenu(WPARAM wParam, LPARAM lParam)
+{
+ lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)lParam;
+ if (mmep != NULL) {
+ mir_free(mmep->szServiceName);
+ mir_free(mmep);
+ }
+ return 0;
+}
+
+INT_PTR HideGroupsHelper(WPARAM wParam, LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr((HWND)CallService(MS_CLUI_GETHWNDTREE, 0, 0), GWL_STYLE) & CLS_HIDEEMPTYGROUPS);
+ cfg::writeByte("CList", "HideEmptyGroups", (BYTE)newVal);
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE, 0, 0), CLM_SETHIDEEMPTYGROUPS, newVal, 0);
+ return 0;
+}
+
+INT_PTR UseGroupsHelper(WPARAM wParam, LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr((HWND)CallService(MS_CLUI_GETHWNDTREE, 0, 0), GWL_STYLE) & CLS_USEGROUPS);
+ cfg::writeByte("CList", "UseGroups", (BYTE)newVal);
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE, 0, 0), CLM_SETUSEGROUPS, newVal, 0);
+ return 0;
+}
+
+INT_PTR HideOfflineRootHelper(WPARAM wParam, LPARAM lParam)
+{
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE, 0, 0), CLM_SETHIDEOFFLINEROOT,
+ !SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE, 0, 0), CLM_GETHIDEOFFLINEROOT, 0, 0),
+ 0);
+ return 0;
+}
+
+static int OnBuildGroupMenu(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.flags = CMIM_FLAGS | (cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT) ? CMIF_CHECKED : 0);
+ Menu_ModifyItem(hHideOfflineUsersMenuItem, &mi);
+
+ mi.flags = CMIM_FLAGS | (SendMessage(pcli->hwndContactTree, CLM_GETHIDEOFFLINEROOT, 0, 0) ? CMIF_CHECKED : 0);
+ Menu_ModifyItem(hHideOfflineUsersOutHereMenuItem, &mi);
+
+ mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_HIDEEMPTYGROUPS ? CMIF_CHECKED : 0);
+ Menu_ModifyItem(hHideEmptyGroupsMenuItem, &mi);
+
+ mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_USEGROUPS ? 0 : CMIF_CHECKED);
+ Menu_ModifyItem(hDisableGroupsMenuItem, &mi);
+
+ mi.flags = CMIM_FLAGS;
+ Menu_ModifyItem(hGroupMainMenuItemProxy, &mi);
+
+ mi.flags = CMIM_FLAGS;
+ Menu_ModifyItem(hAppearanceMenuItemProxy, &mi);
+ return 0;
+}
+
+IconItemT iconItem[] = {
+ { LPGENT("New group"), "new_group", IDI_ADDGROUP },
+ { LPGENT("Contact list"), "clist", IDI_CLIST }
+};
+
+void InitIconLibMenuIcons(void)
+{
+ Icon_RegisterT(g_hInst, LPGENT("Contact list"), iconItem, SIZEOF(iconItem));
+}
+
+void InitGroupMenus(void)
+{
+ CreateServiceFunction("CLISTMENUSGroup/ExecService", GroupMenuExecService);
+ CreateServiceFunction("CLISTMENUSGroup/FreeOwnerDataGroupMenu", FreeOwnerDataGroupMenu);
+ CreateServiceFunction("CLISTMENUSGroup/GroupMenuonAddService", GroupMenuonAddService);
+ CreateServiceFunction("CLISTMENUSGroup/HideGroupsHelper", HideGroupsHelper);
+ CreateServiceFunction("CLISTMENUSGroup/UseGroupsHelper", UseGroupsHelper);
+ CreateServiceFunction("CLISTMENUSGroup/HideOfflineRootHelper", HideOfflineRootHelper);
+
+ CreateServiceFunction("CList/AddGroupMenuItem", AddGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDGROUP, BuildGroupMenu);
+ hPreBuildGroupMenuEvent = CreateHookableEvent(ME_CLIST_PREBUILDGROUPMENU);
+ HookEvent(ME_CLIST_PREBUILDGROUPMENU, OnBuildGroupMenu);
+
+ InitSubGroupMenus();
+
+ //Group menu
+ hGroupMenuObject = MO_CreateMenuObject("GroupMenu", LPGEN("Group menu"), 0, "CLISTMENUSGroup/ExecService");
+ MO_SetMenuObjectParam(hGroupMenuObject, OPT_USERDEFINEDITEMS, TRUE);
+ MO_SetMenuObjectParam(hGroupMenuObject, OPT_MENUOBJECT_SET_FREE_SERVICE, "CLISTMENUSGroup/FreeOwnerDataGroupMenu");
+ MO_SetMenuObjectParam(hGroupMenuObject, OPT_MENUOBJECT_SET_ONADD_SERVICE, "CLISTMENUSGroup/GroupMenuonAddService");
+ {
+ //add exit command to menu
+ GroupMenuParam gmp;
+
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.position = 1900000;
+ mi.pszService = "CloseAction";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_EXIT);
+ mi.pszName = LPGEN("E&xit");
+ AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500;
+ mi.pszService = MS_CLIST_SHOWHIDE;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_SHOWHIDE);
+ mi.pszName = LPGEN("&Hide/show");
+ hHideShowMainMenuItem = (HGENMENU)AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 200000;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_FINDUSER);
+ mi.pszService = "FindAdd/FindAddCommand";
+ mi.pszName = LPGEN("&Find/add contacts...");
+ AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300000;
+ mi.pszService = "";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MAINMENU);
+ mi.pszName = LPGEN("&Main menu");
+ hGroupMainMenuItemProxy = (HGENMENU)AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300100;
+ mi.pszService = "";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_STATUS);
+ mi.pszName = LPGEN("&Status");
+ hGroupStatusMenuItemProxy = (HGENMENU)AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 390100;
+ mi.pszService = "";
+ mi.icolibItem = iconItem[1].hIcolib;
+ mi.pszName = LPGEN("Appearance");
+ hAppearanceMenuItemProxy = (HGENMENU)AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 400000;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS);
+ mi.pszService = "Options/OptionsCommand";
+ mi.pszName = LPGEN("&Options...");
+ AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500000;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA);
+ mi.pszService = "CLN/About";
+ mi.pszName = LPGEN("&About the contact list...");
+ AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100000;
+ mi.icolibItem = iconItem[0].hIcolib;
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&New group");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_NEWGROUP;
+ hNewGroupMenuItem = (HGENMENU)AddGroupMenuItem((WPARAM)&gmp, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100001;
+ mi.hIcon = NULL;
+ mi.pszService = MS_CLIST_SETHIDEOFFLINE;
+ mi.pszName = LPGEN("&Hide offline users");
+ gmp.lParam = 0;
+ gmp.wParam = -1;
+ hHideOfflineUsersMenuItem = (HGENMENU)AddGroupMenuItem((WPARAM)&gmp, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100002;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/HideOfflineRootHelper";
+ mi.pszName = LPGEN("Hide &offline users out here");
+ hHideOfflineUsersOutHereMenuItem = (HGENMENU)AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100003;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/HideGroupsHelper";
+ mi.pszName = LPGEN("Hide &empty groups");
+ hHideEmptyGroupsMenuItem = (HGENMENU)AddGroupMenuItem(0, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100004;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/UseGroupsHelper";
+ mi.pszName = LPGEN("Disable &groups");
+ hDisableGroupsMenuItem = (HGENMENU)AddGroupMenuItem(0, (LPARAM)&mi);
+ }
+}
+
+HANDLE hSubGroupMenuObject;
+
+HANDLE hSubGroupMainMenuItemProxy;
+//HANDLE hHideShowMainMenuItem;
+HANDLE hSubGroupStatusMenuItemProxy;
+HANDLE hPreBuildSubGroupMenuEvent;
+HGENMENU hHideOfflineUsersHereMenuItem;
+
+//SubGroupmenu exec param(ownerdata)
+typedef struct {
+ char *szServiceName;
+ int Param1, Param2;
+} SubGroupMenuExecParam, *lpSubGroupMenuExecParam;
+
+static int OnBuildSubGroupMenu(WPARAM wParam, LPARAM lParam)
+{
+ ClcGroup *group = (ClcGroup *)wParam;
+ if (group == 0)
+ return 0;
+
+ //contact->group
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.flags = CMIM_FLAGS | (group->hideOffline ? CMIF_CHECKED : 0);
+ Menu_ModifyItem(hHideOfflineUsersHereMenuItem, &mi);
+ return 0;
+}
+
+static INT_PTR BuildSubGroupMenu(WPARAM wParam, LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hSubGroupMenuObject;
+ param.wParam = wParam;
+
+ HMENU hMenu = CreatePopupMenu();
+ int tick = GetTickCount();
+ NotifyEventHooks(hPreBuildSubGroupMenuEvent, wParam, 0);
+
+ CallService(MO_BUILDMENU, (WPARAM)hMenu, (LPARAM)¶m);
+ tick = GetTickCount() - tick;
+ return (INT_PTR)hMenu;
+}
+
+static INT_PTR AddSubGroupMenuItem(WPARAM wParam, LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM *)lParam;
+ if (!pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)mir_alloc(sizeof(SubGroupMenuExecParam));
+ if (mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ lpGroupMenuParam gmp = (lpGroupMenuParam)wParam;
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ if (gmp != NULL) {
+ mmep->Param1 = gmp->wParam;
+ mmep->Param2 = gmp->lParam;
+ }
+ tmi.ownerdata = mmep;
+
+ char buf[1024];
+ mir_snprintf(buf, SIZEOF(buf), "%s/%s", mi->pszService, mi->pszName);
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM, (WPARAM)hSubGroupMenuObject, (LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)buf;
+ CallService(MO_SETOPTIONSMENUITEM, 0, (LPARAM)&op);
+ return (INT_PTR)op.Handle;
+}
+
+INT_PTR SubGroupMenuCheckService(WPARAM wParam, LPARAM lParam) {
+ //not used
+ return 0;
+};
+
+INT_PTR SubGroupMenuonAddService(WPARAM wParam, LPARAM lParam) {
+
+ MENUITEMINFO *mii = (MENUITEMINFO *)wParam;
+
+ if (mii == NULL) return 0;
+
+ /*
+ if (hHideShowMainMenuItem == (HANDLE)lParam) {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+ }
+ if (hSubGroupMainMenuItemProxy == (HANDLE)lParam) {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN, 0, 0);
+ }
+
+ if (hSubGroupStatusMenuItemProxy == (HANDLE)lParam) {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS, 0, 0);
+ }
+ */
+ return TRUE;
+};
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR SubGroupMenuExecService(WPARAM wParam, LPARAM lParam) {
+ if (wParam != 0) {
+ lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)wParam;
+ if (!strcmp(mmep->szServiceName, "Help/AboutCommand")) {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ CallService(mmep->szServiceName, mmep->Param1, lParam);
+ }
+ else
+ CallService(mmep->szServiceName, mmep->Param1, mmep->Param2);
+ }
+ return 1;
+}
+
+INT_PTR FreeOwnerDataSubGroupMenu(WPARAM wParam, LPARAM lParam)
+{
+ lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)lParam;
+ if (mmep != NULL) {
+ mir_free(mmep->szServiceName);
+ mir_free(mmep);
+ }
+ return 0;
+}
+
+//wparam menu handle to pass to clc.c
+INT_PTR GroupMenuExecProxy(WPARAM wParam, LPARAM lParam)
+{
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE, 0, 0), WM_COMMAND, wParam, 0);
+ return 0;
+}
+
+void InitSubGroupMenus(void)
+{
+ CreateServiceFunction("CLISTMENUSSubGroup/ExecService", SubGroupMenuExecService);
+ CreateServiceFunction("CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu", FreeOwnerDataSubGroupMenu);
+ CreateServiceFunction("CLISTMENUSSubGroup/SubGroupMenuonAddService", SubGroupMenuonAddService);
+ CreateServiceFunction("CLISTMENUSSubGroup/GroupMenuExecProxy", GroupMenuExecProxy);
+
+ //CreateServiceFunction("CLISTMENUSSubGroup/HideSubGroupsHelper", HideSubGroupsHelper);
+ //CreateServiceFunction("CLISTMENUSSubGroup/UseSubGroupsHelper", UseSubGroupsHelper);
+ //CreateServiceFunction("CLISTMENUSSubGroup/HideOfflineRootHelper", HideOfflineRootHelper);
+
+ CreateServiceFunction("CList/AddSubGroupMenuItem", AddSubGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDSUBGROUP, BuildSubGroupMenu);
+ hPreBuildSubGroupMenuEvent = CreateHookableEvent(ME_CLIST_PREBUILDSUBGROUPMENU);
+ HookEvent(ME_CLIST_PREBUILDSUBGROUPMENU, OnBuildSubGroupMenu);
+
+ // SubGroup menu
+ hSubGroupMenuObject = MO_CreateMenuObject("SubGroupMenu", LPGEN("Subgroup menu"), 0, "CLISTMENUSSubGroup/ExecService");
+ MO_SetMenuObjectParam(hSubGroupMenuObject, OPT_USERDEFINEDITEMS, TRUE);
+ MO_SetMenuObjectParam(hSubGroupMenuObject, OPT_MENUOBJECT_SET_FREE_SERVICE, "CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu");
+ MO_SetMenuObjectParam(hSubGroupMenuObject, OPT_MENUOBJECT_SET_ONADD_SERVICE, "CLISTMENUSSubGroup/SubGroupMenuonAddService");
+
+ {
+ //add exit command to menu
+ GroupMenuParam gmp;
+
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.position = 1000;
+ mi.icolibItem = iconItem[0].hIcolib;
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&New subgroup");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_NEWSUBGROUP;
+ hNewSubGroupMenuItem = (HGENMENU)AddSubGroupMenuItem((WPARAM)&gmp, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1001;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Hide offline users in here");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_GROUPHIDEOFFLINE;
+ hHideOfflineUsersHereMenuItem = (HGENMENU)AddSubGroupMenuItem((WPARAM)&gmp, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900001;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_RENAME);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Rename group");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_RENAMEGROUP;
+ AddSubGroupMenuItem((WPARAM)&gmp, (LPARAM)&mi);
+
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900002;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_DELETE);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Delete group");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_DELETEGROUP;
+ AddSubGroupMenuItem((WPARAM)&gmp, (LPARAM)&mi);
+ }
+}
+
+//////////////////////////////END SubGroup MENU/////////////////////////
diff --git a/plugins/Clist_ng/CLUIFrames/movetogroup.cpp b/plugins/Clist_ng/CLUIFrames/movetogroup.cpp new file mode 100644 index 0000000000..6753b8a46c --- /dev/null +++ b/plugins/Clist_ng/CLUIFrames/movetogroup.cpp @@ -0,0 +1,89 @@ +/*
+ * 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
+ * -----------------------------------------------------------------------
+ * The CLUI frames module was first written many years ago for Miranda 0.2
+ * as part of the multiwindow patch. Later it was converted to a contact
+ * list plugin (clist_mw) on which all modern contact list plugins for
+ * miranda are still somewhat based.
+ *
+ * original author of the CLUI frames module is a guy with the nick name
+ * Bethoven
+ *
+ * $Id: movetogroup.cpp 109 2010-09-06 00:48:29Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+
+HANDLE hOnCntMenuBuild;
+HGENMENU hPriorityItem = 0, hFloatingItem = 0;
+
+static int OnContactMenuBuild(WPARAM wParam, LPARAM lParam)
+{
+ CMenuItem mi;
+ BYTE bSetting;
+
+ bSetting = cfg::getByte("CList", "flt_enabled", 0);
+ if (bSetting && !hFloatingItem) {
+ mi.position=200000;
+ mi.pszService="CList/SetContactFloating";
+ mi.name.a = LPGEN("&Floating Contact");
+ if (pcli) {
+ if (SendMessage(pcli->hwndContactTree, CLM_QUERYFLOATINGCONTACT, wParam, 0))
+ mi.flags=CMIF_CHECKED;
+ }
+ hFloatingItem = Menu_AddContactMenuItem(&mi);
+ }
+ else if (!bSetting && hFloatingItem) {
+ //CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)hFloatingItem, 0);
+ hFloatingItem = 0;
+ }
+ else {
+ if (pcli) {
+ if (SendMessage(pcli->hwndContactTree, CLM_QUERYFLOATINGCONTACT, wParam, 0)) {
+ mi.flags |= CMIF_CHECKED;
+ Menu_SetChecked(hFloatingItem, true);
+ }
+ }
+ }
+ return 0;
+}
+
+int MTG_OnmodulesLoad(WPARAM wParam,LPARAM lParam)
+{
+ hOnCntMenuBuild=HookEvent(ME_CLIST_PREBUILDCONTACTMENU,OnContactMenuBuild);
+ return 0;
+}
+
+int UnloadMoveToGroup(void)
+{
+ if (hOnCntMenuBuild)
+ UnhookEvent(hOnCntMenuBuild);
+
+ return 0;
+}
diff --git a/plugins/Clist_ng/INCLUDE/clc.h b/plugins/Clist_ng/INCLUDE/clc.h new file mode 100644 index 0000000000..421f6ac62a --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/clc.h @@ -0,0 +1,586 @@ +/*
+ * 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-2015 by silvercircle _at_ gmail _dot_ com and contributors
+ */
+
+#ifndef __CLC_H_
+#define __CLC_H_
+
+#define NR_DSPOVERRIDES 5
+
+#define DSP_OVR_OFFLINE 0
+#define DSP_OVR_ONLINE 1
+#define DSP_OVR_SELECTED 2
+#define DSP_OVR_HOVERED 3
+#define DSP_OVR_PRIORITY 4
+
+struct TDspOverride {
+ bool fActive;
+ char bAvatar;
+ char bSecondLine;
+ char bIcon;
+ BYTE exIconOrder[EXICON_COUNT];
+};
+
+struct TDisplayProfile {
+ DWORD dwFlags;
+ DWORD dwExtraImageMask;
+ int exIconScale;
+ BOOL bCenterStatusIcons;
+ BOOL bDimIdle, bNoOfflineAvatars,
+ bShowLocalTime, bShowLocalTimeSelective,
+ bDontSeparateOffline, bCenterGroupNames;
+ BYTE dualRowMode;
+ COLORREF avatarBorder;
+ int avatarSize;
+ DWORD clcExStyle;
+ DWORD clcOfflineModes;
+ BYTE sortOrder[3], bUseDCMirroring, bGroupAlign;
+ BYTE avatarPadding;
+ BYTE bLeftMargin, bRightMargin, bRowSpacing,
+ bGroupIndent, bRowHeight, bGroupRowHeight;
+ BYTE exIconOrder[EXICON_COUNT];
+ BYTE bReserved[16];
+ TDspOverride dspOverride[NR_DSPOVERRIDES];
+};
+
+class CLC
+{
+public:
+
+ static LRESULT CALLBACK wndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void Paint (HWND hwnd, ClcData *dat, HDC hdc, RECT *rcPaint);
+ static void PaintItem (HDC hdcMem, ClcGroup *group, struct ClcContact *contact, int indent,
+ int y, struct ClcData *dat, int index, HWND hwnd, DWORD style,
+ RECT *clRect, BOOL *bFirstNGdrawn, int groupCountsFontTopShift, int rowHeight);
+ static int AddContactToGroup (ClcData *dat, ClcGroup *group, MCONTACT hContact);
+ static void RebuildEntireList (HWND hwnd, ClcData *dat);
+ static ClcGroup* RemoveItemFromGroup (HWND hwnd, ClcGroup *group, ClcContact *contact, int updateTotalCount);
+ static CListEvent* AddEvent (CLISTEVENT *cle);
+ static int RemoveEvent (MCONTACT hContact, MEVENT hDbEvent);
+ static ClcGroup* AddGroup (HWND hwnd, ClcData *dat, const wchar_t *szName, DWORD flags, int groupId, int calcTotalMembers);
+ static int AddInfoItemToGroup (ClcGroup *group, int flags, const wchar_t *pszText);
+ static int fnIconFromStatusMode ( const char* szProto, int status, MCONTACT hContact );
+ static int IconFromStatusMode (const char *szProto, int status, MCONTACT hContact, HICON *phIcon);
+ static void LoadClcOptions (HWND hwnd, ClcData *dat, BOOL first);
+ static void LoadContactTree ();
+ static LRESULT ProcessExternalMessages (HWND hwnd, ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void RecalcScrollBar (HWND hwnd, ClcData *dat);
+ static INT_PTR TrayIconProcessMessage (WPARAM wParam, LPARAM lParam);
+
+ static int SettingChanged (WPARAM wParam, LPARAM lParam);
+ static void ScrollTo (HWND hwnd, ClcData *dat, int desty, int noSmooth);
+ static ClcContact* CreateClcContact ();
+ static CListEvent* fnCreateEvent ();
+ static int HitTest (HWND hwnd, ClcData *dat, int testx, int testy, ClcContact **contact,
+ ClcGroup **group, DWORD *flags);
+ static int RTL_HitTest (HWND hwnd, ClcData *dat, int testx, int testy, ClcContact *hitcontact,
+ DWORD *flags, int indent, int hit);
+
+ static int loadModule (void);
+ static int preshutdown (WPARAM wParam, LPARAM lParam);
+ static int shutDown (WPARAM wParam, LPARAM lParam);
+ static int findItem (HWND hwnd, ClcData *dat, HANDLE hItem, ClcContact **contact, ClcGroup **subgroup, int *isVisible);
+ static int SetHideOffline (WPARAM wParam, LPARAM lParam);
+ static int CompareContacts (const ClcContact* c1, const ClcContact* c2);
+ static void BeginRenameSelection (HWND hwnd, ClcData *dat);
+ static void countAvatars (ClcData *dat);
+
+
+ static inline int getStatusOnlineness(int status, bool ignoreConnectingState)
+ {
+ if(!ignoreConnectingState) {
+ if(status >= ID_STATUS_CONNECTING && status < ID_STATUS_OFFLINE)
+ return 120;
+ }
+
+ if(status >= ID_STATUS_ONLINE && status <= ID_STATUS_OUTTOLUNCH)
+ return(_status2onlineness[status - ID_STATUS_OFFLINE]);
+ return 0;
+ }
+
+ static inline int getGeneralisedStatus ()
+ {
+ int status, thisStatus, statusOnlineness, thisOnlineness;
+
+ status = ID_STATUS_OFFLINE;
+ statusOnlineness = 0;
+
+ thisStatus = cfg::maxStatus;
+ if (thisStatus == ID_STATUS_INVISIBLE)
+ return ID_STATUS_INVISIBLE;
+ thisOnlineness = getStatusOnlineness(thisStatus, true);
+ if (thisOnlineness > statusOnlineness) {
+ status = thisStatus;
+ statusOnlineness = thisOnlineness;
+ }
+ return status;
+ }
+
+ static LRESULT (CALLBACK* saveContactListControlWndProc) (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ /*
+ static int (* saveAddContactToGroup ) (ClcData *dat, ClcGroup *group, MCONTACT hContact);
+ static ClcGroup* (* saveRemoveItemFromGroup ) (HWND hwnd, ClcGroup *group, ClcContact *contact, int updateTotalCount);
+ static CListEvent* (* saveAddEvent ) (CLISTEVENT *cle);
+ static int (* saveRemoveEvent ) (MCONTACT hContact, HANDLE hDbEvent);
+ static ClcGroup* (* saveAddGroup ) (HWND hwnd, ClcData *dat, const wchar_t *szName, DWORD flags, int groupId, int calcTotalMembers);
+ static int (* saveAddInfoItemToGroup ) (ClcGroup *group, int flags, const wchar_t *pszText);
+ static int (* saveIconFromStatusMode ) (const char *szProto, int status, MCONTACT hContact );
+ static void (* saveLoadClcOptions ) (HWND hwnd, ClcData *dat, BOOL first);
+ static LRESULT (* saveProcessExternalMessages ) (HWND hwnd, ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void (* saveRecalcScrollBar ) (HWND hwnd, ClcData *dat);
+ static INT_PTR (* saveTrayIconProcessMessage ) (WPARAM wParam, LPARAM lParam);
+ */
+ static bool fHottrackDone, fInPaint;
+ static int iHottrackItem;
+ static HANDLE hSettingsChanged, hDBEvent;
+ static HIMAGELIST hClistImages;
+ static HANDLE hTheme;
+ static unsigned int uNrAvatars;
+ static TDisplayProfile dsp_default;
+ static int _status2onlineness[];
+
+};
+
+#define MAXEXTRACOLUMNS 16
+
+#define INTM_XSTATUSCHANGED (WM_USER+26)
+#define INTM_METACHANGEDEVENT (WM_USER+27)
+#define INTM_CODEPAGECHANGED (WM_USER+28)
+#define INTM_CLIENTCHANGED (WM_USER+29)
+#define INTM_AVATARCHANGED (WM_USER+30)
+#define INTM_STATUSMSGCHANGED (WM_USER+31)
+#define INTM_SORTCLC (WM_USER+32)
+#define INTM_STATUSCHANGED (WM_USER+33)
+#define INTM_METACHANGED (WM_USER+34)
+#define INTM_INVALIDATECONTACT (WM_USER+35)
+#define INTM_FORCESORT (WM_USER+36)
+
+#define DEFAULT_TITLEBAR_HEIGHT 18
+
+#define CLS_SKINNEDFRAME 0x0800 //this control will be the main contact list (v. 0.3.4.3+ 2004/11/02)
+
+#define TIMERID_RENAME 10
+#define TIMERID_DRAGAUTOSCROLL 11
+#define TIMERID_INFOTIP 13
+#define TIMERID_SORT 15
+#define TIMERID_REFRESH 18
+#define TIMERID_PAINT 19
+struct ClcGroup;
+
+#define CONTACTF_ONLINE 1
+#define CONTACTF_INVISTO 2
+#define CONTACTF_VISTO 4
+#define CONTACTF_NOTONLIST 8
+#define CONTACTF_CHECKED 16
+#define CONTACTF_IDLE 32
+#define CONTACTF_STICKY 64
+#define CONTACTF_PRIORITY 128
+
+#define STATUSMSG_XSTATUSID 1
+#define STATUSMSG_XSTATUSNAME 2
+#define STATUSMSG_CLIST 4
+#define STATUSMSG_YIM 8
+#define STATUSMSG_GG 16
+#define STATUSMSG_XSTATUS 32
+
+#define STATUSMSG_NOTFOUND 0
+
+#define SMSG_MAXLEN 700
+
+#define EXTRAIMAGECACHESIZE 1000
+
+// extra cache contact flags
+
+#define ECF_RTLNICK 1
+#define ECF_RTLSTATUSMSG 2
+#define ECF_FORCEAVATAR 4
+#define ECF_HIDEAVATAR 8
+#define ECF_FORCEOVERLAY 16
+#define ECF_HIDEOVERLAY 32
+#define ECF_FORCELOCALTIME 64
+#define ECF_HIDELOCALTIME 128
+#define ECF_FORCEVISIBILITY 256
+#define ECF_HIDEVISIBILITY 512
+#define ECF_HASREALTIMEZONE 1024
+
+// other contact flags (struct ClCContact;
+
+#define ECF_AVATAR 1
+#define ECF_SECONDLINE 2
+
+struct ContactFloater {
+ ContactFloater* pNextFloater;
+ HWND hwnd;
+ HDC hdc;
+ HBITMAP hbm, hbmOld;
+ MCONTACT hContact;
+};
+
+typedef struct ContactFloater CONTACTFLOATER;
+
+#define DSPF_CENTERSTATUSICON 1
+#define DSPF_DIMIDLE 2
+#define DSPF_NOFFLINEAVATARS 4
+#define DSPF_SHOWLOCALTIME 8
+#define DSPF_LOCALTIMESELECTIVE 16
+#define DSPF_DONTSEPARATEOFFLINE 32
+#define DSPF_CENTERGROUPNAMES 64
+
+/* Extra icons settings */
+typedef struct _OrderTreeData
+{
+ BYTE ID;
+ wchar_t * Name;
+ BYTE Position;
+ BOOL Visible;
+ BOOL fReserved;
+} *PORDERTREEDATA, ORDERTREEDATA;
+
+#define DSP_PROFILES_MODULE "CLG_DspProfiles" // db module for display profile overrides
+
+struct ClcContact : public ClcContactBase
+{
+ BOOL bIsMeta;
+ BYTE xStatus;
+ int xStatusIcon;
+ MCONTACT hSubContact;
+ char *metaProto;
+ DWORD codePage;
+ WORD wStatus;
+ int avatarLeft, extraIconRightBegin;
+ int isRtl;
+ DWORD cFlags;
+ BYTE bSecondLine;
+ BYTE bSecondLineLocal;
+ DWORD dwDFlags;
+ avatarCacheEntry *ace;
+ int extraCacheEntry;
+};
+
+#define DRAGSTAGE_NOTMOVED 0
+#define DRAGSTAGE_ACTIVE 1
+#define DRAGSTAGEM_STAGE 0x00FF
+#define DRAGSTAGEF_MAYBERENAME 0x8000
+#define DRAGSTAGEF_OUTSIDE 0x4000
+
+#define FONTID_CONTACTS 0
+#define FONTID_INVIS 1
+#define FONTID_OFFLINE 2
+#define FONTID_NOTONLIST 3
+#define FONTID_GROUPS 4
+#define FONTID_GROUPCOUNTS 5
+#define FONTID_DIVIDERS 6
+#define FONTID_OFFINVIS 7
+#define FONTID_STATUS 8
+#define FONTID_FRAMETITLE 9
+#define FONTID_EVENTAREA 10
+#define FONTID_TIMESTAMP 11
+#define FONTID_LAST FONTID_TIMESTAMP
+
+class CLCPaintHelper;
+
+struct ClcData : public ClcDataBase
+{
+ int *row_heights;
+ int row_heights_size;
+ int row_heights_allocated;
+
+ int row_border;
+ int min_row_heigh, group_row_height;
+
+ int currentFontID;
+ int rightMargin;
+ BYTE SelectMode;
+ BYTE isMultiSelect;
+ HWND hwndParent;
+ DWORD lastSort;
+ BOOL bNeedPaint, bisEmbedded, bHideSubcontacts;
+ DWORD lastRepaint;
+ BOOL forceScroll;
+ int oldSelection;
+ CLCPaintHelper *ph;
+};
+
+
+#define CLUI_FRAME_SHOWBOTTOMBUTTONS 2
+#define CLUI_SHOWCLIENTICONS 4
+#define CLUI_SHOWVISI 8
+#define CLUI_FRAME_CLISTSUNKEN 16
+#define CLUI_SHOWXSTATUS 32
+#define CLUI_FRAME_BUTTONSFLAT 64
+#define CLUI_FRAME_BUTTONSCLASSIC 128
+#define CLUI_USEMETAICONS 256
+#define CLUI_FRAME_AUTOHIDENOTIFY 512
+#define CLUI_STICKYEVENTS 2048
+#define CLUI_FRAME_SBARSHOW 4096
+#define CLUI_STATUSASTEXT 8192
+#define CLUI_FULLROWSELECT 16384
+#define CLUI_FRAME_BUTTONBARSUNKEN 65536
+#define CLUI_FRAME_AVATARS 0x20000
+#define CLUI_FRAME_AVATARSLEFT 0x40000
+#define CLUI_FRAME_GDIPLUS 0x80000
+#define CLUI_FRAME_AVATARBORDER 0x100000
+#define CLUI_FRAME_STATUSICONS 0x200000
+#define CLUI_FRAME_AVATARSRIGHTWITHNICK 0x400000
+#define CLUI_FRAME_TRANSPARENTAVATAR 0x800000
+//#define CLUI_FRAME_ROUNDAVATAR 0x1000000
+#define CLUI_FRAME_ALWAYSALIGNNICK 0x2000000
+#define CLUI_FRAME_AVATARSRIGHT 0x4000000
+#define CLUI_FRAME_SHOWSTATUSMSG 0x8000000
+#define CLUI_FRAME_OVERLAYICONS 0x10000000
+#define CLUI_FRAME_SELECTIVEICONS 0x20000000
+// #define CLUI_FRAME_ROUNDEDFRAME 0x40000000
+#define CLUI_FRAME_NOGROUPICON 0x80000000
+
+#define MULTIROW_NEVER 0
+#define MULTIROW_ALWAYS 1
+#define MULTIROW_IFNEEDED 2
+
+#define CLUI_USE_FLOATER 1
+#define CLUI_FLOATER_AUTOHIDE 2
+#define CLUI_FLOATER_EVENTS 4
+
+#define CLC_GROUPALIGN_LEFT 0
+#define CLC_GROUPALIGN_RIGHT 1
+#define CLC_GROUPALIGN_AUTO 2
+
+#define SORTBY_NAME 1
+#define SORTBY_PROTO 2
+#define SORTBY_STATUS 3
+#define SORTBY_LASTMSG 4
+#define SORTBY_FREQUENCY 5
+#define SORTBY_PRIOCONTACTS 6
+
+struct IconDesc {
+ char *szName;
+ char *szDesc;
+ int uId; // icon ID
+};
+
+struct NotifyMenuItemExData {
+ MCONTACT hContact;
+ int iIcon; // icon index in the image list
+ HICON hIcon; // corresponding icon handle
+ MEVENT hDbEvent;
+};
+
+#define BUTTON_HEIGHT_D 21
+#define BUTTON_WIDTH_D 21
+// #define NOTIFY_HEIGHT 24
+
+#define TOPBUTTON_PUSH 1
+#define TOPBUTTON_SENDONDOWN 2
+
+struct CluiTopButton {
+ HWND hwnd;
+ HICON hIcon, hAltIcon;
+ UINT id, idIcon, idAltIcon;
+ char *szIcoLibIcon, *szIcoLibAltIcon;
+ DWORD flags;
+ DWORD visibilityOrder;
+ wchar_t *szTooltip;
+};
+
+struct TrayIconInfo {
+ union {
+ HICON hIcon;
+ int iIcon;
+ };
+};
+
+typedef struct {
+ char protoName[50];
+ UINT menuID;
+ BOOL added;
+ HICON hIcon;
+} protoMenu;
+
+DWORD INTSORT_GetLastMsgTime(MCONTACT hContact);
+int InitCustomMenus(void);
+
+void DoSelectionDefaultAction(HWND hwnd, struct ClcData *dat);
+
+#define DROPTARGET_OUTSIDE 0
+#define DROPTARGET_ONSELF 1
+#define DROPTARGET_ONNOTHING 2
+#define DROPTARGET_ONGROUP 3
+#define DROPTARGET_ONCONTACT 4
+#define DROPTARGET_INSERTION 5
+
+BYTE GetCachedStatusMsg(int iExtraCacheEntry, char *szProto);
+void GetExtendedInfo(struct ClcContact *contact, struct ClcData *dat);
+extern LRESULT CALLBACK NewStatusBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int FrameNCCalcSize(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar);
+int FrameNCPaint(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar);
+
+void FreeProtocolData( void );
+void DSP_LoadFromDefaults(TDisplayProfile *);
+
+void GetClientID(struct ClcContact *contact, char *client);
+int LoadCLCButtonModule(void);
+void SetButtonStates(HWND hwnd);
+void IcoLibReloadIcons();
+int AvatarChanged(WPARAM wParam, LPARAM lParam);
+void ClearIcons(int mode);
+int GetBasicFontID(struct ClcContact * contact);
+extern int __fastcall CLVM_GetContactHiddenStatus(MCONTACT hContact, char *szStatus, struct ClcData *dat);
+void CreateViewModeFrame();
+void ReloadExtraInfo(MCONTACT hContact);
+void LoadAvatarForContact(struct ClcContact *p);
+void ApplyViewMode(const char *name);
+DWORD CalcXMask(MCONTACT hContact);
+
+void Reload3dBevelColors();
+void ReloadThemedOptions();
+void CreateButtonBar(HWND hWnd);
+void SetButtonToSkinned();
+void RTL_DetectAndSet(struct ClcContact *contact, MCONTACT hContact);
+void RTL_DetectGroupName(struct ClcContact *group);
+void CLN_LoadAllIcons(BOOL mode);
+void ReloadSkinItemsToCache();
+void SFL_RegisterWindowClass();
+void SFL_UnregisterWindowClass();
+void SFL_Create();
+void SFL_Destroy();
+void SFL_SetState(int iMode);
+void SFL_SetSize();
+void SFL_PaintNotifyArea();
+void SFL_Update(HICON hIcon, int iIcon, HIMAGELIST hIml, const wchar_t *szText, BOOL refresh);
+
+void FLT_Update(struct ClcData *dat, struct ClcContact *contact);
+int FLT_CheckAvail();
+void FLT_Create(int iEntry);
+void FLT_SetSize(struct TExtraCache *centry, LONG width, LONG height);
+void FLT_SyncWithClist();
+void FLT_ReadOptions();
+void FLT_WriteOptions();
+void FLT_RefreshAll();
+
+//clcopts.c
+int ClcOptInit(WPARAM wParam, LPARAM lParam);
+void CluiProtocolStatusChanged( int parStatus, const char* szProto );
+
+void LoadSkinItemToCache(struct TExtraCache *cEntry, const char *szProto);
+
+int Docking_IsDocked(WPARAM wParam, LPARAM lParam);
+
+// Menus
+
+int ClcSoundHook(WPARAM wParam, LPARAM lParam);
+
+int CoolSB_SetupScrollBar(HWND hwnd);
+
+#define NIIF_INTERN_UNICODE 0x00000100
+
+#define SETTING_WINDOWSTYLE_DEFAULT 0
+
+#define SETTING_TRAYICON_SINGLE 0
+#define SETTING_TRAYICON_CYCLE 1
+#define SETTING_TRAYICON_MULTI 2
+
+#define SETTING_STATE_HIDDEN 0
+#define SETTING_STATE_MINIMIZED 1
+#define SETTING_STATE_NORMAL 2
+
+#define SETTING_BRINGTOFRONT_DEFAULT 0
+
+#define SETTING_WINDOWSTYLE_TOOLWINDOW 1
+#define SETTING_WINDOWSTYLE_THINBORDER 2
+#define SETTING_WINDOWSTYLE_NOBORDER 3
+
+#define BM_SETPRIVATEICON (WM_USER + 6)
+#define BM_SETIMLICON (WM_USER + 7)
+#define BM_SETSKINNED (WM_USER + 8)
+#define BM_SETASMENUACTION (WM_USER + 9)
+#define BM_SETBTNITEM (WM_USER+10)
+
+#define EIMG_SHOW_RES0 8
+#define EIMG_SHOW_EMAIL 1
+#define EIMG_SHOW_WEB 2
+#define EIMG_SHOW_SMS 4
+#define EIMG_SHOW_ADV1 16
+#define EIMG_SHOW_ADV2 32
+#define EIMG_SHOW_ADV3 512
+#define EIMG_SHOW_CLIENT 64
+#define EIMG_SHOW_ADV4 1024
+#define EIMG_SHOW_RES1 128
+#define EIMG_SHOW_RES2 256
+
+#define CLCHT_ONITEMEXTRAEX 0x1000 //on an extra icon, HIBYTE(HIWORD()) says which
+#define CLCHT_ONAVATAR 0x2000
+#define CLCHT_ONITEMSPACE 0x4000
+
+#define CLM_SETEXTRAIMAGEINT (CLM_FIRST+101)
+#define CLM_SETSTICKY (CLM_FIRST+100)
+#define CLM_ISMULTISELECT (CLM_FIRST+102)
+#define CLM_SETEXTRAIMAGEINTMETA (CLM_FIRST+104)
+#define CLM_GETSTATUSMSG (CLM_FIRST+105)
+#define CLM_SETHIDESUBCONTACTS (CLM_FIRST+106)
+#define CLM_TOGGLEPRIORITYCONTACT (CLM_FIRST+107)
+#define CLM_QUERYPRIORITYCONTACT (CLM_FIRST+108)
+#define CLM_TOGGLEFLOATINGCONTACT (CLM_FIRST+109)
+#define CLM_QUERYFLOATINGCONTACT (CLM_FIRST+110)
+
+#define IDC_RESETMODES 110
+#define IDC_SELECTMODE 108
+#define IDC_CONFIGUREMODES 109
+
+#define NR_CLIENTS 40
+
+/*
+ * status and contact floater flags
+ */
+
+#define FLT_SIMPLE 1
+#define FLT_AVATARS 2
+#define FLT_DUALROW 4
+#define FLT_EXTRAICONS 8
+#define FLT_SYNCWITHCLIST 16
+#define FLT_AUTOHIDE 32
+#define FLT_SNAP 64
+#define FLT_BORDER 128
+#define FLT_ROUNDED 256
+#define FLT_FILLSTDCOLOR 512
+#define FLT_SHOWTOOLTIPS 1024
+#define FLT_ONTOP 2048
+
+typedef struct _floatopts {
+ DWORD dwFlags;
+ BYTE pad_left, pad_right, pad_top, pad_bottom;
+ DWORD width;
+ COLORREF border_colour;
+ BYTE trans, act_trans;
+ BYTE enabled;
+ BYTE def_hover_time;
+ WORD hover_time;
+} FLOATINGOPTIONS;
+
+extern FLOATINGOPTIONS g_floatoptions;
+
+#endif /* __CLC_H_*/
diff --git a/plugins/Clist_ng/INCLUDE/clist.h b/plugins/Clist_ng/INCLUDE/clist.h new file mode 100644 index 0000000000..9c6050b8cf --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/clist.h @@ -0,0 +1,56 @@ +/*
+ * 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: clist.h 102 2010-08-31 02:48:29Z silvercircle $
+ *
+ */
+
+HTREEITEM GetTreeItemByHContact(HANDLE hContact);
+void SortContacts(void);
+
+#define CLUIINTM_REDRAW (WM_USER+100)
+#define CLUIINTM_STATUSBARUPDATE (WM_USER+101)
+#define CLUIINTM_REMOVEFROMTASKBAR (WM_USER+102)
+
+#define CLVM_FILTER_PROTOS 1
+#define CLVM_FILTER_GROUPS 2
+#define CLVM_FILTER_STATUS 4
+#define CLVM_FILTER_VARIABLES 8
+#define CLVM_STICKY_CONTACTS 16
+#define CLVM_FILTER_STICKYSTATUS 32
+#define CLVM_FILTER_LASTMSG 64
+#define CLVM_FILTER_LASTMSG_OLDERTHAN 128
+#define CLVM_FILTER_LASTMSG_NEWERTHAN 256
+
+#define CLVM_PROTOGROUP_OP 1
+#define CLVM_GROUPSTATUS_OP 2
+#define CLVM_AUTOCLEAR 4
+#define CLVM_INCLUDED_UNGROUPED 8
+#define CLVM_USELASTMSG 16
+
+#define CLVM_MODULE "CLVM_W"
diff --git a/plugins/Clist_ng/INCLUDE/clui.h b/plugins/Clist_ng/INCLUDE/clui.h new file mode 100644 index 0000000000..a09aa7f43a --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/clui.h @@ -0,0 +1,168 @@ +/*
+* 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_nicer plugin for Miranda.
+*
+* (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+*
+* $Id$
+*
+*/
+
+#ifndef __CLUI_H_
+#define __CLUI_H_
+
+#define TM_AUTOALPHA 1
+#define TIMERID_AUTOSIZE 100
+#define MENU_MIRANDAMENU 0xFFFF1234
+
+#define EXICON_COUNT 11
+
+struct TCluiData {
+ DWORD dwFlags;
+ int soundsOff;
+ BYTE bMetaAvail;
+ BYTE bAvatarServiceAvail, tabSRMM_Avail;
+ HICON hIconVisible, hIconInvisible, hIconChatactive, hIconConnecting;
+ int notifyActive;
+ int hIconNotify;
+ HMENU hMenuNotify;
+ int iLastEventAdded;
+ int wNextMenuID;
+ MCONTACT hUpdateContact;
+ wchar_t* szNoEvents;
+ BOOL forceResize;
+ COLORREF avatarBorder;
+ HBRUSH hBrushAvatarBorder;
+ HBRUSH hBrushCLCBk, hBrushCLCGroupsBk;
+ int avatarSize;
+ BOOL bForceRefetchOnPaint;
+ BYTE dualRowMode;
+ BYTE avatarPadding;
+ BYTE isTransparent;
+ BYTE alpha, autoalpha;
+ BYTE fadeinout;
+ BYTE autosize;
+ BYTE gapBetweenFrames;
+ BYTE titleBarHeight;
+ DWORD dwExtraImageMask;
+ BYTE bRowSpacing;
+ HDC hdcBg;
+ HBITMAP hbmBg, hbmBgOld;
+ SIZE dcSize;
+ POINT ptW;
+ BOOL bNoOfflineAvatars;
+ BOOL bEventAreaEnabled;
+ BOOL bDblClkAvatars;
+ BOOL bApplyIndentToBg;
+ BOOL bEqualSections;
+ DWORD bFilterEffective;
+ BOOL bCenterStatusIcons;
+ BOOL bUsePerProto;
+ BOOL bOverridePerStatusColors;
+ BOOL bDontSeparateOffline;
+ wchar_t groupFilter[2048];
+ char protoFilter[2048];
+ DWORD lastMsgFilter;
+ char current_viewmode[256], old_viewmode[256];
+ BYTE boldHideOffline;
+ DWORD statusMaskFilter;
+ DWORD stickyMaskFilter;
+ DWORD filterFlags;
+ COLORREF colorkey;
+ char szMetaName[256];
+ BOOL bMetaEnabled;
+ BOOL bNoTrayTips;
+ int exIconScale;
+ BOOL bShowLocalTime;
+ BOOL bShowLocalTimeSelective;
+ BYTE bSkinnedButtonMode;
+ BYTE bFirstRun;
+ BYTE bUseDCMirroring;
+ BYTE bUseFloater;
+ SIZE szOldCTreeSize;
+ BYTE sortOrder[3];
+ BYTE bGroupAlign;
+ BYTE bSkinnedScrollbar;
+ DWORD langPackCP;
+ int group_padding;
+ DWORD t_now;
+ BYTE exIconOrder[EXICON_COUNT];
+ BOOL realTimeSaving;
+ FILETIME ft;
+ SYSTEMTIME st;
+};
+
+class CLUI
+{
+public:
+ static void Tweak_It (const COLORREF clr);
+ static void layoutButtons (HWND hwnd, RECT *rc);
+ static HWND preCreateCLC (HWND parent);
+ static int createCLC (HWND parent);
+ static void loadModule (void);
+ static int modulesLoaded (WPARAM wParam, LPARAM lParam);
+ static LRESULT CALLBACK wndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void configureGeometry (int mode);
+ static void reloadExtraIcons ();
+ static void loadExtraIconModule ();
+ static void removeFromTaskBar (HWND hWnd);
+ static void addToTaskBar (HWND hWnd);
+ static DWORD getWindowStyle (BYTE style);
+ static void applyBorderStyle ();
+ static LRESULT CALLBACK eventAreaWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void setFrameButtonStates (MCONTACT hPassedContact);
+ static void Show (HWND hwnd);
+ static void setButtonStates (HWND hwnd);
+ static void configureWindowLayout ();
+ static void hideShowNotifyFrame ();
+ static void configureEventArea (HWND hwnd);
+ static void updateLayers ();
+ static void setLayeredAttributes (COLORREF clr, BYTE alpha, DWORD flags);
+ static inline void Redraw ();
+ static HPEN hPenFrames;
+ static int fading_active;
+ static bool fInSizing;
+ static LRESULT (CALLBACK* saveContactListWndProc ) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+ static WNDPROC OldStatusBarProc;
+ static RECT newRect, rcWPC, cluiPos;
+ static UPDATELAYEREDWINDOWINFO ulwInfo;
+ static BLENDFUNCTION bf;
+ static HIMAGELIST hExtraImages;
+ static TImageItem* bgImageItem, *bgImageItem_nonAero, *bgClientItem;
+ static TButtonItem* buttonItems;
+#ifdef _USE_D2D
+ static ID2D1HwndRenderTarget* renderTarget;
+#endif
+};
+
+void CLUI::Redraw()
+{
+ RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
+}
+
+int MTG_OnmodulesLoad (WPARAM wParam,LPARAM lParam);
+//void InitGroupMenus ();
+
+#endif /* __CLUI_H_ */
diff --git a/plugins/Clist_ng/INCLUDE/config.h b/plugins/Clist_ng/INCLUDE/config.h new file mode 100644 index 0000000000..9b73859366 --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/config.h @@ -0,0 +1,272 @@ +/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks
+ *
+ * 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_nicer plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: config.h 134 2010-10-01 10:23:10Z silvercircle $
+ *
+ */
+
+#include <stdexcept>
+
+#ifndef __CONFIG_H_
+#define __CONFIG_H_
+
+#define DEFAULT_MODULE "Clist"
+#define SKIN_REQUIRED_VERSION 5
+
+#define IS_THEMED (Api::sysState.isThemed)
+#define IS_AERO (Api::sysState.isAero)
+
+typedef BOOL (WINAPI *PGF)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG);
+
+typedef int (__cdecl *pfnDrawAvatar)(HDC hdcOrig, HDC hdcMem, RECT *rc, struct ClcContact *contact, int y, struct ClcData *dat, int selected, WORD cstatus, int rowHeight);
+typedef BOOL (WINAPI *pfnSetLayeredWindowAttributes_t)(HWND, COLORREF, BYTE, DWORD);
+typedef BOOL (WINAPI *pfnUpdateLayeredWindow_t)(HWND, HDC, POINT *, SIZE *, HDC, POINT *, COLORREF, BLENDFUNCTION *, DWORD);
+typedef HMONITOR(WINAPI *pfnMonitorFromWindow_t)(HWND, DWORD);
+typedef BOOL (WINAPI *pfnGetMonitorInfo_t)(HMONITOR, LPMONITORINFO);
+typedef BOOL (WINAPI *pfnTrackMouseEvent_t)(LPTRACKMOUSEEVENT);
+typedef DWORD (WINAPI *pfnSetLayout_t)(HDC, DWORD);
+typedef void (__cdecl *pfnDrawAlpha_t)(HDC hdcwnd, PRECT rc, DWORD basecolor, BYTE alpha, DWORD basecolor2, BOOL transparent, DWORD FLG_GRADIENT, DWORD FLG_CORNER, DWORD BORDERSTYLE, TImageItem *item);
+typedef BOOL (WINAPI *pfnAlphaBlend_t)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
+
+typedef BOOL (WINAPI *pfnIsThemeActive_t)();
+typedef HANDLE (WINAPI *pfnOpenThemeData_t)(HWND, LPCWSTR);
+typedef UINT (WINAPI *pfnDrawThemeBackground_t)(HANDLE, HDC, int, int, RECT *, RECT *);
+typedef UINT (WINAPI *pfnCloseThemeData_t)(HANDLE);
+typedef UINT (WINAPI *pfnDrawThemeText_t)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, RECT *);
+typedef UINT (WINAPI *pfnDrawThemeTextEx_t)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, RECT *, const DTTOPTS *);
+typedef BOOL (WINAPI *pfnIsThemeBackgroundPartiallyTransparent_t)(HANDLE, int, int);
+typedef HRESULT (WINAPI *pfnDrawThemeParentBackground_t)(HWND, HDC, RECT *);
+typedef HRESULT (WINAPI *pfnGetThemeBackgroundContentRect_t)(HANDLE, HDC, int, int, const RECT *, const RECT *);
+typedef BOOL (WINAPI *pfnEnableThemeDialogTexture_t)(HANDLE, DWORD);
+typedef HRESULT (WINAPI *pfnDwmExtendFrameIntoClientArea_t)(HWND hwnd, const MARGINS *margins);
+typedef HRESULT (WINAPI *pfnDwmIsCompositionEnabled_t)(BOOL *);
+
+typedef HRESULT (WINAPI *pfnBufferedPaintInit_t)(void);
+typedef HRESULT (WINAPI *pfnBufferedPaintUninit_t)(void);
+typedef HANDLE (WINAPI *pfnBeginBufferedPaint_t)(HDC, RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *);
+typedef HRESULT (WINAPI *pfnEndBufferedPaint_t)(HANDLE, BOOL);
+typedef HRESULT (WINAPI *pfnBufferedPaintSetAlpha_t)(HANDLE, const RECT *, BYTE);
+typedef HRESULT (WINAPI *pfnBufferedPaintClear_t)(HANDLE, const RECT *);
+typedef HRESULT (WINAPI *pfnDwmBlurBehindWindow_t)(HWND, DWM_BLURBEHIND *);
+typedef HRESULT (WINAPI *pfnDwmGetColorizationColor_t)(DWORD *, BOOL *);
+typedef HRESULT (WINAPI *pfnGetBufferedPaintBits_t)(HANDLE, RGBQUAD **, int *);
+typedef ULONGLONG(WINAPI *pfnGetTickCount64_t)(void);
+
+struct ContactFloater;
+
+struct TExtraCache {
+ BYTE iExtraImage[20];
+ MCONTACT hContact;
+ HANDLE hTimeZone;
+ DWORD iExtraValid;
+ BYTE valid;
+ wchar_t* statusMsg;
+ BYTE bStatusMsgValid;
+ DWORD dwCFlags;
+ DWORD dwXMask; // local extra icon mask, calculated from CLN_xmask
+ TStatusItem *status_item, *proto_status_item;
+ ContactFloater *floater; // associated floating contact window
+ DWORD dwLastMsgTime; // last message received (unix timestamp)
+ DWORD msgFrequency; // "message rate" - for sorting by activity
+ BOOL isChatRoom; // a chat room
+};
+
+class CRTException : public std::runtime_error
+{
+public:
+ CRTException(const char *szMsg, const wchar_t *szParam);
+ ~CRTException() {}
+
+ void display() const;
+
+private:
+ wchar_t m_szParam[MAX_PATH];
+};
+
+struct TSkinDescription {
+ ULONG ulID; // resource id
+ wchar_t tszName[30]; // file name
+};
+
+class cfg
+{
+public:
+ static void initCache();
+ static int onInit(); // early stage inite (read base path, extract resources)
+
+ static DWORD getDword(const MCONTACT hContact, const char *szModule, const char *szSetting, DWORD uDefault);
+ static DWORD getDword(const char *szModule, const char *szSetting, DWORD uDefault);
+ static DWORD getDword(const char *szSetting, DWORD uDefault);
+
+ static WORD getWord(const MCONTACT hContact, const char *szModule, const char *szSetting, WORD uDefault);
+ static WORD getWord(const char *szModule, const char *szSetting, WORD uDefault);
+ static WORD getWord(const char *szSetting, WORD uDefault);
+
+ static int getByte(const MCONTACT hContact, const char *szModule, const char *szSetting, int uDefault);
+ static int getByte(const char *szModule, const char *szSetting, int uDefault);
+ static int getByte(const char *szSetting, int uDefault);
+
+ static INT_PTR getTString(const MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
+ static INT_PTR getString(const MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
+
+ static INT_PTR writeDword(const MCONTACT hContact, const char *szModule, const char *szSetting, DWORD value);
+ static INT_PTR writeDword(const char *szModule, const char *szSetting, DWORD value);
+
+ static INT_PTR writeWord(const MCONTACT hContact, const char *szModule, const char *szSetting, WORD value);
+ static INT_PTR writeWord(const char *szModule, const char *szSetting, WORD value);
+
+ static INT_PTR writeByte(const MCONTACT hContact, const char *szModule, const char *szSetting, BYTE value);
+ static INT_PTR writeByte(const char *szModule, const char *szSetting, BYTE value);
+
+ static INT_PTR writeTString(const MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *st);
+ static INT_PTR writeString(const MCONTACT hContact, const char *szModule, const char *szSetting, const char *st);
+ static int getCache(const MCONTACT hContact, const char *szProto);
+ static void FS_RegisterFonts();
+ static CLUIFrames *FrameMgr;
+
+ /*
+ * option dialog procedures
+ */
+ static INT_PTR CALLBACK DlgProcClcMainOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcViewModesSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcFloatingContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK SkinOptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcCluiOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcGenOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK TabOptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcDspGroups(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcDspItems(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcDspAdvanced(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcDspClasses(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcXIcons(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcDspProfiles(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+ static void ReloadExtraIcons();
+ static void extractBaseSkin(bool fForceOverwrite);
+
+public:
+ static TCluiData dat;
+ static ClcData* clcdat;
+ static TExtraCache* eCache;
+ static int nextCacheEntry, maxCacheEntry;
+ static int maxStatus;
+
+ static CRITICAL_SECTION cachecs;
+
+ static bool shutDown;
+ static bool isAero;
+ static wchar_t szProfileDir[MAX_PATH];
+ static bool fBaseSkinValid;
+ static FI_INTERFACE* fif;
+
+ static TSkinDescription cfg::my_default_skin[];
+};
+
+struct TSysConfig {
+ bool isVistaPlus;
+ bool isSevenPlus;
+};
+
+struct TSysState {
+ bool isThemed;
+ bool isAero;
+ bool isDwmActive;
+};
+
+class Api
+{
+public:
+ static int onInit();
+ static void onUnload();
+ static void updateState();
+
+ static void Ex_CopyEditToClipboard(HWND hWnd);
+ static INT_PTR CALLBACK Ex_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ static void Ex_Handler();
+ static int Ex_ShowDialog(EXCEPTION_POINTERS *ep, const char *szFile, int line, wchar_t* szReason, bool fAllowContinue);
+
+ /*
+ * helpers
+ */
+
+ static PGF pfnGradientFill;
+ static pfnAlphaBlend_t pfnAlphaBlend;
+ static pfnGetTickCount64_t pfnGetTickCount64;
+ /*
+ * uxtheme
+ */
+
+ static pfnIsThemeActive_t pfnIsThemeActive;
+ static pfnOpenThemeData_t pfnOpenThemeData;
+ static pfnDrawThemeBackground_t pfnDrawThemeBackground;
+ static pfnCloseThemeData_t pfnCloseThemeData;
+ static pfnDrawThemeText_t pfnDrawThemeText;
+ static pfnDrawThemeTextEx_t pfnDrawThemeTextEx;
+ static pfnIsThemeBackgroundPartiallyTransparent_t pfnIsThemeBackgroundPartiallyTransparent;
+ static pfnDrawThemeParentBackground_t pfnDrawThemeParentBackground;
+ static pfnGetThemeBackgroundContentRect_t pfnGetThemeBackgroundContentRect;
+ static pfnEnableThemeDialogTexture_t pfnEnableThemeDialogTexture;
+
+ /*
+ * UxTheme buffered paint API (Vista+)
+ */
+ static pfnBufferedPaintInit_t pfnBufferedPaintInit;
+ static pfnBufferedPaintUninit_t pfnBufferedPaintUninit;
+ static pfnBeginBufferedPaint_t pfnBeginBufferedPaint;
+ static pfnEndBufferedPaint_t pfnEndBufferedPaint;
+ static pfnBufferedPaintSetAlpha_t pfnBufferedPaintSetAlpha;
+ static pfnBufferedPaintClear_t pfnBufferedPaintClear;
+ static pfnGetBufferedPaintBits_t pfnGetBufferedPaintBits;
+
+ /*
+ * DWM
+ */
+ static pfnDwmBlurBehindWindow_t pfnDwmBlurBehindWindow;
+ static pfnDwmGetColorizationColor_t pfnDwmGetColorizationColor;;
+ static pfnDwmExtendFrameIntoClientArea_t pfnDwmExtendFrameIntoClientArea;
+ static pfnDwmIsCompositionEnabled_t pfnDwmIsCompositionEnabled;
+
+ static TSysConfig sysConfig;
+ static TSysState sysState;
+
+ static EXCEPTION_RECORD exRecord;
+ static CONTEXT exCtx;
+ static LRESULT exLastResult;
+ static char exSzFile[MAX_PATH];
+ static wchar_t exReason[256];
+ static int exLine;
+ static bool exAllowContinue;
+
+ static HMODULE hUxTheme, hDwm;
+};
+
+
+#endif /* __CONFIG_H_*/
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_*/ + diff --git a/plugins/Clist_ng/INCLUDE/m_cln_skinedit.h b/plugins/Clist_ng/INCLUDE/m_cln_skinedit.h new file mode 100644 index 0000000000..6022874a39 --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/m_cln_skinedit.h @@ -0,0 +1,201 @@ +
+/*
+ * services
+ */
+
+#define MS_CLNSE_INVOKE "CLN_Skinedit/Invoke"
+#define MS_CLNSE_FILLBYCURRENTSEL "CLN_Skinedit/FillByCurrentSel"
+
+/*
+ * data structs
+ */
+
+struct TImageItem {
+ char szName[40];
+ HBITMAP hbm;
+ BYTE bLeft, bRight, bTop, bBottom; // sizing margins
+ BYTE alpha;
+ DWORD dwFlags;
+ HDC hdc;
+ HBITMAP hbmOld;
+ LONG inner_height, inner_width;
+ LONG width, height;
+ BLENDFUNCTION bf;
+ BYTE bStretch;
+ HBRUSH fillBrush;
+ LONG glyphMetrics[4];
+ TImageItem *nextItem;
+};
+
+struct TButtonItem {
+ char szName[40];
+ HWND hWnd;
+ LONG xOff, yOff;
+ //LONG xOff_framed, yOff_framed;
+ LONG width, height;
+ TImageItem *imgNormal, *imgPressed, *imgHover;
+ LONG normalGlyphMetrics[4];
+ LONG hoverGlyphMetrics[4];
+ LONG pressedGlyphMetrics[4];
+ DWORD dwFlags, dwStockFlags;
+ DWORD uId;
+ TCHAR szTip[256];
+ char szService[256];
+ char szModule[256], szSetting[256];
+ BYTE bValuePush[256], bValueRelease[256];
+ DWORD type;
+ void (*pfnAction)(TButtonItem *item, HWND hwndDlg, struct MessageWindowData *dat, HWND hwndItem);
+ void (*pfnCallback)(TButtonItem *item, HWND hwndDlg, struct MessageWindowData *dat, HWND hwndItem);
+ TCHAR tszLabel[40];
+ TButtonItem *nextItem;
+};
+
+typedef struct _tagButtonSet {
+ TButtonItem *items;
+ LONG left, top, right, bottom; // client area offsets, calculated from button layout
+} ButtonSet;
+
+typedef agg::span_gradient<agg::rgba8, agg::span_interpolator_linear<>, agg::gradient_x, agg::pod_auto_array<agg::rgba8, 256> > span_gradient_x_t;
+typedef agg::span_gradient<agg::rgba8, agg::span_interpolator_linear<>, agg::gradient_y, agg::pod_auto_array<agg::rgba8, 256> > span_gradient_y_t;
+typedef agg::span_allocator<agg::rgba8> span_allocator_t;
+
+struct TStatusItem {
+ char szName[40];
+ int statusID;
+
+ BYTE GRADIENT;
+ BYTE CORNER;
+
+ DWORD COLOR;
+ DWORD COLOR2;
+ BYTE ALPHA;
+ BYTE ALPHA2;
+
+ DWORD TEXTCOLOR;
+
+ int MARGIN_LEFT;
+ int MARGIN_TOP;
+ int MARGIN_RIGHT;
+ int MARGIN_BOTTOM;
+ BYTE IGNORED;
+ DWORD dwFlags;
+ TImageItem *imageItem;
+
+ agg::rasterizer_scanline_aa<>* agg_ras;
+ agg::rounded_rect* agg_rect;
+ agg::pod_auto_array<agg::rgba8, 256>* color_array;
+
+ span_allocator_t* span_allocator;
+ span_gradient_x_t* span_gradient_x;
+ span_gradient_y_t* span_gradient_y;
+ agg::span_interpolator_linear<>* span_interpolator;
+ agg::gradient_x* gradient_func_x;
+ agg::gradient_y* gradient_func_y;
+ agg::trans_affine* gradient_trans;
+ agg::renderer_scanline_aa<agg::renderer_base<agg::pixfmt_bgra32>, span_allocator_t, span_gradient_x_t>* gradient_renderer_x;
+ agg::renderer_scanline_aa<agg::renderer_base<agg::pixfmt_bgra32>, span_allocator_t, span_gradient_y_t>* gradient_renderer_y;
+ agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_bgra32> >* solid_renderer;
+
+ agg::renderer_base<agg::pixfmt_bgra32>* rbase;
+ agg::pixfmt_bgra32* pixfmt;
+ agg::rounded_rect* rect;
+};
+
+typedef struct {
+ BOOL bGRADIENT;
+ BOOL bCORNER;
+ BOOL bCOLOR;
+ BOOL bCOLOR2;
+ BOOL bTEXTCOLOR;
+ BOOL bALPHA;
+ BOOL bMARGIN_LEFT;
+ BOOL bMARGIN_TOP;
+ BOOL bMARGIN_RIGHT;
+ BOOL bMARGIN_BOTTOM;
+ BOOL bIGNORED;
+ BOOL bALPHA2;
+ BOOL bFlags;
+} ChangedSItems_t;
+
+typedef struct _tagSkinDescription {
+ DWORD cbSize;
+ TStatusItem *StatusItems;
+ int lastItem;
+ int firstItem;
+ char szModule[100];
+ HWND hWndParent, hWndTab;
+ HWND hwndCLUI;
+ HWND hwndSkinEdit; /* out param */
+ HWND hwndImageEdit; /* out param */
+ HMENU hMenuItems;
+ void (*pfnSaveCompleteStruct)(void);
+ void (*pfnClcOptionsChanged )(void);
+ void* (*pfnMalloc)(unsigned int);
+ void (*pfnFree)(void);
+ void* (*pfnRealloc)(void *, unsigned int);
+ void* reserved[20];
+} SKINDESCRIPTION;
+
+// defines
+
+// FLAGS
+#define CORNER_NONE 0
+#define CORNER_ACTIVE 1
+#define CORNER_TL 2
+#define CORNER_TR 4
+#define CORNER_BR 8
+#define CORNER_BL 16
+
+#define GRADIENT_NONE 0
+#define GRADIENT_ACTIVE 1
+#define GRADIENT_LR 2
+#define GRADIENT_RL 4
+#define GRADIENT_TB 8
+#define GRADIENT_BT 16
+
+#define IMAGE_PERPIXEL_ALPHA 1
+#define IMAGE_FLAG_DIVIDED 2
+#define IMAGE_FILLSOLID 4
+#define IMAGE_GLYPH 8
+
+#define IMAGE_STRETCH_V 1
+#define IMAGE_STRETCH_H 2
+#define IMAGE_STRETCH_B 4
+
+#define BUTTON_ISINTERNAL 0x1
+#define BUTTON_ISTOGGLE 0x2
+#define BUTTON_ISSERVICE 0x4
+#define BUTTON_ISPROTOSERVICE 0x8
+#define BUTTON_PASSHCONTACTW 0x10
+#define BUTTON_PASSHCONTACTL 0x20
+#define BUTTON_ISDBACTION 0x40
+#define BUTTON_ISCONTACTDBACTION 0x80
+#define BUTTON_DBACTIONONCONTACT 0x100
+#define BUTTON_ISSIDEBAR 0x200
+#define BUTTON_NORMALGLYPHISICON 0x400
+#define BUTTON_PRESSEDGLYPHISICON 0x800
+#define BUTTON_HOVERGLYPHISICON 0x1000
+#define BUTTON_HASLABEL 0x2000
+#define BUTTON_HALIGN_R 0x4000
+#define BUTTON_VALIGN_B 0x8000
+#define BUTTON_FRAMELESS_ONLY 0x10000
+#define BUTTON_FAKE_CAPTIONBUTTON 0x20000
+
+#define CLCDEFAULT_GRADIENT 0
+#define CLCDEFAULT_CORNER 0
+
+#define CLCDEFAULT_COLOR 0xd0d0d0
+#define CLCDEFAULT_COLOR2 0xd0d0d0
+
+#define CLCDEFAULT_TEXTCOLOR 0x000000
+
+#define CLCDEFAULT_COLOR2_TRANSPARENT 1
+
+#define CLCDEFAULT_ALPHA 100
+#define CLCDEFAULT_MRGN_LEFT 0
+#define CLCDEFAULT_MRGN_TOP 0
+#define CLCDEFAULT_MRGN_RIGHT 0
+#define CLCDEFAULT_MRGN_BOTTOM 0
+#define CLCDEFAULT_IGNORE 1
+
+HWND SkinEdit_Invoke(WPARAM wParam, LPARAM lParam);
diff --git a/plugins/Clist_ng/INCLUDE/resource.h b/plugins/Clist_ng/INCLUDE/resource.h new file mode 100644 index 0000000000..c989272b01 --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/resource.h @@ -0,0 +1,449 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by C:\tabsrmm\trunk\miranda\plugins\clist_NG\resource.rc
+//
+#define IDD_OPT_VIEWMODES 1
+#define IDD_OPT_FLOATING 3
+#define IDD_OPT_SKIN 4
+#define IDD_QUICKIGNORE 5
+#define IDD_OPT 6
+#define IDI_FOLDER 7
+#define IDI_POPUPON 8
+#define IDI_ICON1 9
+#define IDI_POPUPOFF 9
+#define IDD_EXCEPTION 20
+#define IDD_OPTIONSDIALOG 101
+#define IDD_CLNABOUT 102
+#define IDD_OPT_CLIST 126
+#define IDI_ADDGROUP 143
+#define IDI_CLIST 146
+#define IDI_OPTIONS 163
+#define IDI_DELETE 175
+#define IDI_CLVM_OPTIONS 176
+#define IDI_CLVM_SELECT 177
+#define IDI_RENAME 173
+#define IDR_CONTEXT 180
+#define IDC_DROP 183
+#define IDR_CLISTMENU 199
+#define IDD_WARNING 201
+#define IDI_ADDCONTACT 210
+#define IDC_HYPERLINKHAND 214
+#define IDC_DROPUSER 215
+#define IDD_OPT_CLUI 218
+#define IDD_OPT_XICONS 219
+#define IDD_OPT_CLC 228
+#define IDD_OPT_SBAR 234
+#define IDD_DELETECONTACT 254
+#define IDD_OPT_DSPPROFILES 300
+#define IDD_OPT_DSPADVANCED 301
+#define IDD_OPT_DSPITEMS 302
+#define IDD_OPT_DSPGROUPS 303
+#define IDD_OPT_DSPCLASSES 304
+#define IDD_SKINITEMEDIT 601
+#define IDD_IMAGEITEMEDIT 602
+#define IDR_SKIN_BASE 801
+#define IDR_SKIN_BACK 802
+#define IDR_SKIN_GLYPHS 803
+#define IDR_SKIN_BACKAERO 804
+#define IDC_ACTIVEPERC 1000
+#define IDC_OPTIONSTAB 1000
+#define IDC_ALWAYSSTATUS 1009
+#define IDC_APPLY 1011
+#define IDC_AUTOSIZE 1013
+#define IDC_AUTOSIZEUPWARD 1014
+#define IDC_AVATARSIZESPIN 1015
+#define IDC_STATUSICONSCENTERED 1020
+#define IDC_NOTRAYINFOTIPS 1020
+#define IDC_SHOWXSTATUS 1020
+#define IDC_AUTOCLEAR 1020
+#define IDC_FLT_SIMPLELAYOUT 1020
+#define IDC_IGN_MSGEVENTS 1020
+#define IDC_AUTOCLEARVAL 1021
+#define IDC_MARKLOCKED 1021
+#define IDC_IGN_FILEEVENTS 1021
+#define IDC_AUTOCLEARSPIN 1022
+#define IDC_IGN_URLEVENTS 1022
+#define IDC_LASTMSG 1023
+#define IDC_IGN_AUTH 1023
+#define IDC_IGN_ADD 1024
+#define IDC_CONFIRMDELETE 1025
+#define IDC_IGN_ONLINE 1025
+#define IDC_IGN_ALWAYSONLINE 1026
+#define IDC_IGN_ALWAYSOFFLINE 1027
+#define IDC_IGN_PRIORITY 1028
+#define IDC_DISABLEGROUPS 1030
+#define IDC_USEPERPROTO 1041
+#define IDC_OVERRIDEPERSTATUSCOLOR 1042
+#define IDC_SETALLBUTTONSKINNED 1043
+#define IDC_EVENTSONTOP 1044
+#define IDC_EXTRA_ICON_EMAIL 1045
+#define IDC_DONTSEPARATE 1045
+#define IDC_EXTRA_ICON_SMS 1047
+#define IDC_EXTRA_ICON_RES0 1054
+#define IDC_EXTRA_ICON_WEB 1055
+#define IDC_FADEINOUT 1056
+#define IDC_EXTRA_ICON_ADV2 1057
+#define IDC_FADEINOUT2 1057
+#define IDC_USEAERO 1057
+#define IDC_EXTRA_ICON_RES1 1058
+#define IDC_EXTRA_ICON_RES2 1059
+#define IDC_EXTRA_ICON_ADV3 1060
+#define IDC_EXTRAORDER 1061
+#define IDC_FRAMEGAP 1064
+#define IDC_FRAMEGAPSPIN 1065
+#define IDC_FULLROWSELECT 1067
+#define IDC_LOCALTIME 1068
+#define IDC_EXICONSCALE 1068
+#define IDC_EXICONSCALESPIN 1069
+#define IDC_GREYOUT 1072
+#define IDC_ONTOP 1074
+#define IDC_CLIENTDRAG 1076
+#define IDC_HIDEEMPTYGROUPS 1077
+#define IDC_HIDEOFFLINE 1081
+#define IDC_HIDEOFFLINEOPTS 1082
+#define IDC_HKREADMSG 1083
+#define IDC_HKSEARCH 1084
+#define IDC_EXTRA_ICON_ADV4 1085
+#define IDC_HKSHOWOPTIONS 1086
+#define IDC_LEFTMARGINSPIN 1092
+#define IDC_NETSEARCH 1101
+#define IDC_NOGROUPICON 1102
+#define IDC_ONECLK 1105
+#define IDC_SEARCHURL 1106
+#define IDC_BUILDTIME 1108
+#define IDC_READMSG 1119
+#define IDC_RIGHTMARGIN 1121
+#define IDC_ROWGAP 1122
+#define IDC_TRANSPARENT 1124
+#define IDC_ROWHEIGHT 1125
+#define IDC_TRANSINACTIVE 1126
+#define IDC_GROUPROWHEIGHT 1126
+#define IDC_TRANSACTIVE 1128
+#define IDC_SEARCHNEWWND 1139
+#define IDC_SHOWBOTTOMBUTTONS 1148
+#define IDC_STATIC11 1154
+#define IDC_STATIC12 1155
+#define IDC_STATIC21 1156
+#define IDC_STATIC13 1156
+#define IDC_STATIC22 1157
+#define IDC_STATIC14 1157
+#define IDC_STATIC15 1158
+#define IDC_HKSHOWHIDE 1162
+#define IDC_EXTRA_ICON_CLIENT 1164
+#define IDC_EXTRA_ICON_ADV1 1166
+#define IDC_SHOWHIDE 1170
+#define IDC_CENTERGROUPNAMES 1173
+#define IDC_SHOWOPTIONS 1174
+#define IDC_APPLYINDENTBG 1174
+#define IDC_COPYRIGHT 1178
+#define IDC_VERSION 1179
+#define IDC_SHOWSTATUSICONS 1180
+#define IDC_INACTIVEPERC 1187
+#define IDC_SHOWSTATUSMSG 1188
+#define IDC_SHOWLOCALTIME 1189
+#define IDC_SHOWVISIBILITY 1190
+#define IDC_SHOWLOCALTIMEONLYWHENDIFFERENT 1191
+#define IDC_EXCEPTION_DETAILS 1200
+#define IDC_COPY_EXCEPTION 1201
+#define IDC_EX_REASON 1202
+#define IDC_WHITERECT 1225
+#define IDC_AUTOHIDE 1235
+#define IDC_HIDETIME 1236
+#define IDC_ALWAYSHIDEONTASKBAR 1237
+#define IDC_MAXSIZEHEIGHT 1254
+#define IDC_MAXSIZESPIN 1255
+#define IDC_SMOOTHTIME 1283
+#define IDC_SMOOTHTIMESPIN 1284
+#define IDC_ROWHEIGHTSPIN 1286
+#define IDC_GROUPROWHEIGHTSPIN 1287
+#define IDC_GREYOUTOPTS 1288
+#define IDC_GROUPINDENT 1289
+#define IDC_GROUPINDENTSPIN 1290
+#define IDC_LEFTMARGIN 1291
+#define IDC_RIGHTMARGINSPIN 1294
+#define IDC_ROWGAPSPIN 1295
+#define IDC_DONTCYCLE 1315
+#define IDC_PRIMARYSTATUS 1316
+#define IDC_CYCLE 1317
+#define IDC_CYCLETIME 1318
+#define IDC_CYCLETIMESPIN 1319
+#define IDC_HIDETIMESPIN 1320
+#define IDC_MULTITRAY 1321
+#define IDC_ALWAYSMULTI 1322
+#define IDC_SHOWICON 1323
+#define IDC_SORTTHEN 1323
+#define IDC_SHOWPROTO 1324
+#define IDC_SORTFINALLY 1324
+#define IDC_SHOWSTATUS 1325
+#define IDC_EQUALSECTIONS 1326
+#define IDC_SHOWSBAR 1329
+#define IDC_RIGHTMIRANDA 1330
+#define IDC_RIGHTSTATUS 1331
+#define IDC_STCLISTGROUP 1350
+#define IDC_DISABLEDRAGDROP 1351
+#define IDC_NOTEDITLABELS 1352
+#define IDC_SHOWSELALWAYS 1353
+#define IDC_TRACKSELECT 1354
+#define IDC_SHOWGROUPCOUNTS 1355
+#define IDC_HIDECOUNTSWHENEMPTY 1356
+#define IDC_DIVIDERONOFF 1357
+#define IDC_NOTNOTRANSLUCENTSEL 1358
+#define IDC_LINEWITHGROUPS 1359
+#define IDC_QUICKSEARCHVISONLY 1360
+#define IDC_SORTGROUPSALPHA 1361
+#define IDC_NOTNOSMOOTHSCROLLING 1362
+#define IDC_STWINDOWGROUP 1364
+#define IDC_STATIC01 1365
+#define IDC_STATIC6 1366
+#define IDC_SORTPRIMARY 1420
+#define IDC_HIDE 1534
+#define IDC_TOPLINE 1535
+#define IDC_HOTKEYURLSTR 1567
+#define IDC_BRINGTOFRONT 1579
+#define IDC_LOGO 1591
+#define IDC_BLINKTIME 1607
+#define IDC_BLINKSPIN 1608
+#define IDC_DISABLEBLINK 1609
+#define IDC_IDLE 1610
+#define IDC_DBLCLKAVATARS 1611
+#define IDC_NOSCROLLBAR 1613
+#define IDC_ADDVIEWMODE 1633
+#define IDC_IGN_ALL 1633
+#define IDC_EXPORT 1634
+#define IDC_DELETEVIEWMODE 1634
+#define IDC_IGN_NONE 1634
+#define IDC_IGN_ADDPERMANENTLY 1635
+#define IDC_EXPORT2 1635
+#define IDC_SAVEASMOD 1635
+#define IDC_DSP_LOADDEFAULT 1636
+#define IDC_ONDESKTOP 1657
+#define IDC_ICONBLINK 1660
+#define IDC_APPLYLASTVIEWMODE 1661
+#define IDC_MRGN_BOTTOM 1670
+#define IDC_MRGN_LEFT 1671
+#define IDC_ALPHASPIN 1682
+#define IDC_ALPHASPIN2 1683
+#define IDC_ITEMS 1688
+#define IDC_CORNER 1689
+#define IDC_MRGN_TOP_SPIN 1693
+#define IDC_MRGN_RIGHT_SPIN 1694
+#define IDC_MRGN_BOTTOM_SPIN 1695
+#define IDC_MRGN_LEFT_SPIN 1696
+#define IDC_GRADIENT 1699
+#define IDC_GRADIENT_LR 1700
+#define IDC_GRADIENT_RL 1701
+#define IDC_GRADIENT_TB 1702
+#define IDC_BASECOLOUR 1703
+#define IDC_ALPHA 1704
+#define IDC_MRGN_TOP 1705
+#define IDC_MRGN_RIGHT 1706
+#define IDC_GRADIENT_BT 1707
+#define IDC_BASECOLOUR2 1708
+#define IDC_TEXTCOLOUR 1709
+#define IDC_CORNER_TL 1710
+#define IDC_CORNER_TR 1711
+#define IDC_CORNER_BR 1712
+#define IDC_CORNER_BL 1713
+#define IDC_COLORLABLE 1714
+#define IDC_MARGINLABLE 1715
+#define IDC_ALPHA2 1715
+#define IDC_ALPHALABLE 1716
+#define IDC_IGNORE 1717
+#define IDC_COLOR2LABLE 1718
+#define IDC_ALPHALABLE2 1719
+#define IDC_TEXTCOLOURLABLE 1720
+#define IDC_IGNORESELFORGROUPS 1722
+#define IDC_CLISTAVATARS 1729
+#define IDC_ALIGNMENT 1730
+#define IDC_AVATARSBORDER 1732
+#define IDC_AVATARBORDERCLR 1733
+#define IDC_DUALROWMODE 1735
+#define IDC_CLISTALIGN 1737
+#define IDC_CLISTSUNKEN 1738
+#define IDC_EVENTAREAAUTOHIDE 1740
+#define IDC_ALWAYSALIGNNICK 1744
+#define IDC_SELECTIVEICONS 1746
+#define IDC_OVERLAYICONS 1747
+#define IDC_AVATARHEIGHT 1748
+#define IDC_NOAVATARSOFFLINE 1749
+#define IDC_AVATARPADDING 1753
+#define IDC_GRPTOPPADDING 1753
+#define IDC_AVATARPADDINGSPIN 1754
+#define IDC_GRPPADDINGSPIN 1754
+#define IDC_LASTITEMPADDING 1755
+#define IDC_LASTITEMPADDINGSPIN 1756
+#define IDC_TBHIDEOFFLINE 1800
+#define IDC_TBHIDEGROUPS 1801
+#define IDC_TBSOUND 1802
+#define IDC_TBFINDANDADD 1803
+#define IDC_TBOPTIONS 1804
+#define IDC_TBMINIMIZE 1805
+#define IDC_TBMENU 1806
+#define IDC_TBGLOBALSTATUS 1807
+#define IDC_TABSRMMSLIST 1808
+#define IDC_TABSRMMMENU 1809
+#define IDC_TBSELECTVIEWMODE 1810
+#define IDC_TBCLEARVIEWMODE 1811
+#define IDC_TBCONFIGUREVIEWMODE 1812
+#define IDC_TBTOPMENU 1813
+#define IDC_TBTOPSTATUS 1814
+#define IDC_TBFOLDER 1815
+#define IDC_TBPOPUP 1816
+#define IDC_TBACCOUNTS 1817
+#define IDC_TBFIRSTUID 1820
+#define IDC_NOTIFYBUTTON 1900
+#define IDC_CLNICER 2002
+#define IDC_SUPPORT 2003
+#define IDI_OVL_OFFLINE 2050
+#define IDI_OVL_ONLINE 2051
+#define IDI_OVL_AWAY 2052
+#define IDI_OVL_DND 2053
+#define IDI_OVL_NA 2054
+#define IDI_OVL_OCCUPIED 2055
+#define IDI_OVL_FREEFORCHAT 2056
+#define IDI_OVL_INVISIBLE 2057
+#define IDI_OVL_ONTHEPHONE 2058
+#define IDI_OVL_OUTTOLUNCH 2059
+#define IDI_HIDEOFFLINE 2100
+#define IDI_HIDEGROUPS 2101
+#define IDI_SOUNDSON 2102
+#define IDI_FINDANDADD 2103
+#define IDI_TBOPTIONS 2104
+#define IDI_MINIMIZE 2105
+#define IDI_SOUNDSOFF 2106
+#define IDI_TABSRMMSESSIONLIST 2107
+#define IDI_TABSRMMMENU 2108
+#define IDI_CLVISIBLE 2109
+#define IDI_CLINVISIBLE 2110
+#define IDC_WARNTEXT 2110
+#define IDI_PROTOCONNECTING 2111
+#define IDC_DONTSHOWAGAIN 2111
+#define IDI_TBTOPMENU 2112
+#define IDC_CAPTION 2112
+#define IDI_TBACCOUNTS 2113
+#define IDC_WARNICON 2113
+#define IDC_WARNGROUP 2114
+#define IDC_FLT_DEFHOVERTIME 2200
+#define IDC_SKINROOTFOLDER 3201
+#define IDC_SKINNAME 3202
+#define IDC_RESCANSKIN 3203
+#define IDC_HELP_GENERAL 3204
+#define IDC_SKINNAME2 3205
+#define IDC_WINDOWSTYLE 3205
+#define IDC_CLUIFRAMESBDR 25492
+#define IDC_FLT_PADLEFTSPIN 25494
+#define IDC_FLT_PADLEFT 25495
+#define IDC_GROUPALIGN 25499
+#define IDC_CURVIEWMODE2 25503
+#define ID_ICQ_EXIT 40001
+#define IDC_STATIC7 40002
+#define POPUP_HIDEEMPTYGROUPS 40003
+#define POPUP_NEWSUBGROUP 40004
+#define POPUP_HIDEOFFLINE 40005
+#define POPUP_GROUPHIDEOFFLINE 40006
+#define POPUP_HIDEOFFLINEROOT 40007
+#define POPUP_DISABLEGROUPS 40008
+#define IDC_VIEWMODES 40010
+#define IDC_PROTOCOLS 40011
+#define IDC_GROUPS 40012
+#define IDC_STATUSMODES 40013
+#define IDC_NEWVIEMODE 40014
+#define POPUP_HIDEMIRANDA 40017
+#define IDC_TAB 40017
+#define IDC_STATIC1 40018
+#define IDC_STATIC2 40019
+#define IDC_STATIC3 40020
+#define POPUP_VISIBILITY 40021
+#define IDC_STATIC16 40021
+#define IDC_STATIC4 40022
+#define IDC_STATIC5 40023
+#define IDC_CLIST 40025
+#define IDC_STATIC8 40026
+#define IDC_STATIC9 40027
+#define IDC_CLEARALL 40028
+#define POPUP_FRAME 40029
+#define IDC_STATIC10 40029
+#define POPUP_BUTTONS 40030
+#define IDC_PROTOGROUPOP 40030
+#define POPUP_MOVEMARKEDHERE 40031
+#define IDC_GROUPSTATUSOP 40031
+#define IDC_LASTMESSAGEOP 40032
+#define ID_BUTTONS_ONLINE 40033
+#define ID_BUTTONBAR_INCREASEBUTTONSIZE 40034
+#define IDC_LASTMESSAGEUNIT 40034
+#define ID_BUTTONBAR_DECREASEBUTTONSIZE 40035
+#define ID_BUTTONBAR_FLATBUTTONS 40036
+#define IDC_FLT_AVATARS 40036
+#define IDC_HIDECONTACT 40036
+#define ID_BUTTONBAR_NOVISUALSTYLES 40037
+#define IDC_FLT_DUALROWS 40037
+#define IDC_FLT_EXTRAICONS 40038
+#define ID_TRAY_HIDE 40038
+#define ID_TRAY_EXIT 40039
+#define IDC_FLT_SYNCED 40039
+#define IDC_FLT_AUTOHIDE 40040
+#define IDC_FLT_FILLSTD 40041
+#define IDC_FLT_FILLSTD2 40042
+#define IDC_FLT_ONTOP 40042
+#define IDC_FLT_PADRIGHT 40043
+#define IDC_LASTMSGVALUE 40043
+#define IDC_FLT_PADRIGHTSPIN 40044
+#define IDC_FLT_PADTOP 40045
+#define IDC_FLT_PADTOPSPIN 40046
+#define IDC_FLT_PADBOTTOM 40047
+#define IDC_RELOADSKIN 40047
+#define IDC_FLT_PADBOTTOMSPIN 40048
+#define IDC_UNLOAD 40048
+#define ID_BUTTONBAR_DRAWSUNKENFRAME 40049
+#define POPUP_NEWGROUP 40050
+#define IDC_SECONDLINEMODE 40050
+#define POPUP_SHOWSTATUSICONS 40051
+#define IDC_OVERLAYICON 40051
+#define IDC_SHOWLOCALTIME1 40052
+#define POPUP_RENAMEGROUP 40052
+#define POPUP_DELETEGROUP 40053
+#define ID_BUTTONBAR_SKINNEDTOOLBAR 40054
+#define IDC_FLT_ENABLED 40054
+#define IDC_FLT_OPACITY 40055
+#define IDC_FLT_ACTIVEOPACITY 40056
+#define POPUP_FLOATER 40057
+#define POPUP_FLOATER_AUTOHIDE 40058
+#define IDC_FLT_WIDTH 40058
+#define IDC_AVATARDISPMODE 40059
+#define IDC_FLT_WIDTHSPIN 40059
+#define POPUP_FLOATER_EVENTS 40060
+#define IDC_FLT_SNAP 40060
+#define IDC_FLT_ACTIVEOPACITYVALUE 40061
+#define IDC_FLT_BORDER 40062
+#define IDC_CHECK1 40065
+#define IDC_SNAPTOEDGES 40065
+#define IDC_SKIP_UNDERLAY 40065
+#define IDC_DSPCLASS_AVATAR 40065
+#define IDC_FLT_WIDTHSPIN2 40066
+#define IDC_SKIP_IMAGE 40066
+#define IDC_DSPCLASS 40066
+#define IDC_FLT_HOVERTIME 40067
+#define IDC_DSPCLASS_SECONDLINE 40067
+#define IDC_BUTTON1 40067
+#define IDC_RESETXICONS 40067
+#define IDC_FLT_SHOWTOOLTIPS 40068
+#define IDC_DSPCLASS_ICON 40068
+#define IDC_FLT_HOVERTIMESPIN 40069
+#define IDC_DSPCLASS_ENABLE_SELECTED 40069
+#define IDC_FLT_OPACITYVALUE 40070
+#define IDC_DSPCLASS_ENABLE_SELECTED2 40070
+#define IDC_DSPCLASS_ENABLE_HOVERED 40070
+#define IDC_FLT_BGCOLOUR 40071
+#define IDC_FLT_BORDERCOLOUR 40072
+#define POPUP_SHOWMETAICONS 40073
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 10
+#define _APS_NEXT_COMMAND_VALUE 40061
+#define _APS_NEXT_CONTROL_VALUE 40068
+#define _APS_NEXT_SYMED_VALUE 40154
+#endif
+#endif
diff --git a/plugins/Clist_ng/INCLUDE/rowheight_funcs.h b/plugins/Clist_ng/INCLUDE/rowheight_funcs.h new file mode 100644 index 0000000000..a99ec4e83b --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/rowheight_funcs.h @@ -0,0 +1,137 @@ +/*
+* 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: rowheight_funcs.h 133 2010-09-30 06:27:18Z silvercircle $
+*
+* dynamic row height calculation for contact row. heavily used when
+* painting a clc control with dynamic row heights.
+*
+*/
+
+#ifndef __ROWHEIGHT_FUNCS_H__
+#define __ROWHEIGHT_FUNCS_H__
+
+#define ROW_SPACE_BEETWEEN_LINES 0
+#define ICON_HEIGHT 16
+
+class RowHeight {
+
+public:
+ static BOOL Alloc(ClcData *dat, int size);
+ static BOOL Init(ClcData *dat);
+ static void Free(ClcData *dat);
+ static void Clear(ClcData *dat);
+
+ // Calc and store max row height
+ static int getMaxRowHeight(ClcData *dat, const HWND hwnd);
+
+ // Calc and store row height
+ static inline int getRowHeight(ClcData *dat, ClcContact* contact, int item, DWORD style, CLCPaintHelper* ph)
+ {
+ int height = 0;
+ BYTE secondLine;
+ BOOL fAvatar;
+
+ if (!Alloc(dat, item + 1))
+ return -1;
+
+ height = dat->fontInfo[GetBasicFontID(contact)].fontHeight;
+
+ ph->fAvatar = ph->fSecondLine = false;
+
+ if(!dat->bisEmbedded) {
+ secondLine = contact->bSecondLineLocal;
+ if(255 == secondLine)
+ secondLine = ph->dsp ? (ph->dsp->bSecondLine == 0 ? contact->bSecondLine : (ph->dsp->bSecondLine == 1 ? MULTIROW_ALWAYS : MULTIROW_NEVER)) : contact->bSecondLine;
+ if(secondLine != MULTIROW_NEVER && contact->type == CLCIT_CONTACT) {
+ if ((secondLine == MULTIROW_ALWAYS || ((cfg::dat.dwFlags & CLUI_FRAME_SHOWSTATUSMSG && secondLine == MULTIROW_IFNEEDED) && (contact->xStatus > 0 || cfg::eCache[contact->extraCacheEntry].bStatusMsgValid > STATUSMSG_XSTATUSID)))) {
+ height += (dat->fontInfo[FONTID_STATUS].fontHeight + cfg::dat.avatarPadding);
+ ph->fSecondLine = true;
+ }
+ }
+
+ // Avatar size
+ if(!(contact->dwDFlags & (ECF_HIDEAVATAR | ECF_FORCEAVATAR))) { // no per contact show/hide, consider dsp override
+ if(ph->dsp)
+ fAvatar = (ph->dsp->bAvatar == 0 ? contact->cFlags & ECF_AVATAR : (ph->dsp->bAvatar == -1 ? FALSE : TRUE));
+ else
+ fAvatar = contact->cFlags & ECF_AVATAR;
+ if (fAvatar && contact->type == CLCIT_CONTACT && contact->ace != NULL) {
+ height = max(height, cfg::dat.avatarSize + cfg::dat.avatarPadding);
+ ph->fAvatar = true;
+ }
+ }
+ else {
+ if (contact->cFlags & ECF_AVATAR && contact->type == CLCIT_CONTACT && contact->ace != NULL) {
+ height = max(height, cfg::dat.avatarSize + cfg::dat.avatarPadding);
+ ph->fAvatar = true;
+ }
+ }
+ }
+
+ // Checkbox size
+ if((style&CLS_CHECKBOXES && contact->type==CLCIT_CONTACT) ||
+ (style&CLS_GROUPCHECKBOXES && contact->type==CLCIT_GROUP) ||
+ (contact->type==CLCIT_INFO && contact->flags&CLCIIF_CHECKBOX))
+ {
+ height = max(height, dat->checkboxSize);
+ }
+
+ //height += 2 * dat->row_border;
+ // Min size
+ height = max(height, contact->type == CLCIT_GROUP ? dat->group_row_height : dat->min_row_heigh);
+ height += cfg::dat.bRowSpacing;
+
+ dat->row_heights[item] = height;
+
+ return height;
+ }
+
+ // Calc and store row height for all itens in the list
+ static void calcRowHeights (ClcData *dat, HWND hwnd, CLCPaintHelper* ph);
+
+ // Calc item top Y (using stored data)
+ static int getItemTopY (ClcData *dat, int item);
+
+ // Calc item bottom Y (using stored data)
+ static int getItemBottomY (ClcData *dat, int item);
+
+ // Calc total height of rows (using stored data)
+ static int getTotalHeight (ClcData *dat);
+
+ // Return the line that pos_y is at or -1 (using stored data). Y start at 0
+ static int hitTest (ClcData *dat, int pos_y);
+
+ // Returns the height of the chosen row
+ static int getHeight (ClcData *dat, int item);
+
+ // returns the height for a floating contact
+ static int getFloatingRowHeight(const ClcData *dat, HWND hwnd, ClcContact *contact, DWORD dwFlags);
+};
+
+#endif // __ROWHEIGHT_FUNCS_H__
diff --git a/plugins/Clist_ng/INCLUDE/skin.h b/plugins/Clist_ng/INCLUDE/skin.h new file mode 100644 index 0000000000..0c8d13e2aa --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/skin.h @@ -0,0 +1,214 @@ +/*
+ * 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-2015 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * clist_ng skin helper classes and functions. No low level Gfx here, just
+ * managing the skin data structures...
+ *
+ * drawing is mostly in Gfx
+ *
+ * TODO implement settings override system. Allow user to save modified
+ * skin settings to a separate override file and use these modified settings
+ * when loading the skin.
+ *
+ * TODO implement logic to determine whether a skin has changed to optimize
+ * loading performance (e.g. no need to import fonts and color settings when
+ *
+ * TODO implement replacement for the old clist_nicer style "per contact" skin
+ * items. Allow colorization of contact rows on a per user base. The settings
+ * could be added to the "Contact list settings" dialog.
+ */
+
+#ifndef __SKIN_H_
+#define __SKIN_H_
+
+#define ID_EXTBKOFFLINE 0
+#define ID_EXTBKONLINE 1
+#define ID_EXTBKAWAY 2
+#define ID_EXTBKDND 3
+#define ID_EXTBKNA 4
+#define ID_EXTBKOCCUPIED 5
+#define ID_EXTBKFREECHAT 6
+#define ID_EXTBKINVISIBLE 7
+#define ID_EXTBKONTHEPHONE 8
+#define ID_EXTBKOUTTOLUNCH 9
+
+#define ID_EXTBKIDLE 10
+#define ID_EXTBKEXPANDEDGROUP 11
+#define ID_EXTBKCOLLAPSEDDGROUP 12
+#define ID_EXTBKEMPTYGROUPS 13
+#define ID_EXTBKFIRSTITEM 14
+#define ID_EXTBKSINGLEITEM 15
+#define ID_EXTBKLASTITEM 16
+
+
+#define ID_EXTBKFIRSTITEM_NG 17
+#define ID_EXTBKSINGLEITEM_NG 18
+#define ID_EXTBKLASTITEM_NG 19
+
+#define ID_EXTBKEVEN_CNTCTPOS 20
+#define ID_EXTBKODD_CNTCTPOS 21
+
+#define ID_EXTBKSELECTION 22
+#define ID_EXTBKHOTTRACK 23
+#define ID_EXTBKFRAMETITLE 24
+#define ID_EXTBKEVTAREA 25
+#define ID_EXTBKSTATUSBAR 26
+#define ID_EXTBKBUTTONSPRESSED 27
+#define ID_EXTBKBUTTONSNPRESSED 28
+#define ID_EXTBKBUTTONSMOUSEOVER 29
+#define ID_EXTBKSTATUSFLOATER 30
+#define ID_EXTBKOWNEDFRAMEBORDER 31
+#define ID_EXTBKOWNEDFRAMEBORDERTB 32
+#define ID_EXTBKAVATARFRAME 33
+#define ID_EXTBKAVATARFRAMEOFFLINE 34
+#define ID_EXTBK_LAST_D 34
+
+#define ID_EXTBKSEPARATOR 40200
+
+void extbk_import(char *file, HWND hwndDlg);
+TStatusItem *GetProtocolStatusItem(const char *szProto);
+void SaveNonStatusItemsSettings(HWND hwndDlg);
+
+#define SKIN_DB_MODULE "CLNgSkin" // database module for clng skinning
+
+/*
+ * flags for status item rendering
+ */
+#define AGG_USE_SOLID_RENDERER 1 // item has no gradient -> use a faster solid renderer
+#define AGG_USE_GRADIENT_X_RENDERER 2 // item has horizontal gradient -> use agg::gradient_x function
+#define AGG_USE_GRADIENT_Y_RENDERER 4 // item has vertical gradient -> use agg::gradient_y function
+#define S_ITEM_SKIP_UNDERLAY 8 // skip all gradient underlays and render the image item only
+#define S_ITEM_TEXT_AERO_GLOW 16 // render text with aero glow instead of solid color
+#define S_ITEM_IMAGE_ONLY 32 // this item cannot be used with gradients (only for image skinning)
+#define S_ITEM_SKIP_IMAGE 64 // skip all gradient underlays and render the image item only
+
+/*
+ * this structure describes all relevant settings that are needed
+ * for a skin except the skin items themselves. Usually, they are loaded
+ * from the skin definition (.cng), but the user can override them.
+ * Most of these settings are available on the option pages.
+ *
+ * These settings are copied to the database under ClNGSkin and have a m prefix.
+ * (e.g. cLeftFramed member name = "mLeftFramed" in the db.
+ */
+struct TSkinMetrics {
+ BYTE cLeft, cTop, cRight, cBottom; // these are the currently _effective_ values and are calculated
+ // from the other margins, never saved anywhere, only exist at runtime
+ BYTE cLeftFramed, cTopFramed, cRightFramed, cBottomFramed; // margins when using a window frame
+ BYTE cLeftSkinned, cTopSkinned, cRightSkinned, cBottomSkinned; // margins when using a window skin
+ BYTE cLeftButtonset, cTopButtonset, cRightButtonset, cBottomButtonset; // additional margins for the button sets
+ BYTE bWindowStyle; // border style (none, toolbar or normal title bar
+ BYTE cButtonHeight; // height of the bottom buttons
+ BYTE bSBarHeight; // status bar height adjustment (for skinned mode only)
+ DWORD dwTopOffset, dwBottomOffset; // cTop + additional paddings (rare)
+ BYTE cFakeCaption; // for frameless skin mode - artificial caption bar height, will be added to top aligned buttons
+ // which do not have the title bar attribute
+ BYTE cFakeLeftBorder;
+ BYTE cFakeRightBorder;
+ BYTE cFakeBtmBorder;
+ bool fHaveFrame; // quick boolean, true if clist window has a frame
+ bool fHaveAeroSkin; // true if using the background skin in aero mode
+ bool fHaveColorkey; // true if using a background skin in non-aero mode and
+ // we need a colorkey to get transparent areas
+ DWORD cCornerRadius; // corner radius used for gradient items
+};
+
+/*
+ * settings for a skin (everything else with the exception of geometry information
+ *
+ * Database module: ClNGSkin and values have a s prefix.
+ * e.gl member crColorKey = sColorKey in the db.
+ */
+struct TSkinSettings {
+ COLORREF crColorKey; // the colorkey for LWA_COLORKEY
+ bool fTransparentFrames; // make owned frames transparent
+ COLORREF crFramesColorKey; // background color which should be made transparent in frames
+ BYTE bFramesAlpha; // constant alpha for translucent frames
+ bool fUseAero; // may be used to disable aero regardless of operating system state
+ bool fHaveAeroBG; // we have a valid background item for aero mode
+ wchar_t wszSkinBaseFolder[MAX_PATH]; // internal use only - base directory of the currently loaded skin
+ wchar_t wszSkinName[MAX_PATH]; // internal use only - base name of the skin (the .cng file without extension)
+};
+/*
+ * the Skin class has helper functions to manage skin items and stores the
+ * items (image items, button items and status items
+ */
+class Skin
+{
+public:
+ static void Unload ();
+ static void freeImageItem (TImageItem *item);
+ static void exportToFile (const char *file);
+ static void exportSettingsToFile (const char *file);
+
+ static void renderNamedImageItem (const char *szItemname, RECT* rc, const HDC hdc);
+ static void colorizeGlyphByName (const char* szGlyphName, const COLORREF clr, float h, float s, float v);
+ static void Activate ();
+ static void setAeroMargins ();
+ static void updateAeroState ();
+ static void setupAGGItemContext (TStatusItem* item);
+
+ static int ID_EXTBK_LAST;
+ static TStatusItem* statusItems;
+ static TImageItem* imageItems;
+ static TImageItem* glyphItem;
+
+ static TSkinMetrics metrics;
+ static TSkinSettings settings;
+};
+
+/*
+ * the skin loader class is a helper for reading and writing skin definition files
+ */
+class SkinLoader
+{
+public:
+ SkinLoader(const wchar_t* wszFilename);
+ ~SkinLoader() {};
+
+public:
+ bool isValid () const { return(m_isValid); }
+ HRESULT Load ();
+ DWORD readInt (const char* szSection, const char* szValue, DWORD dwDefault = 0);
+ HRESULT loadItems ();
+ void readButtonItem (const char *itemName, const char *file);
+ void readImageItem (const char *itemname, const char *szFileName);
+ void createImageItem (TImageItem *item, const char *fileName, HDC hdc);
+ void loadFonts ();
+ void loadBaseItems ();
+ void readItem (TStatusItem *this_item, const char *szItem);
+
+ static UINT nextButtonID;
+
+private:
+ bool m_isValid;
+ char m_szFilename[MAX_PATH];
+ wchar_t m_wszFilename[MAX_PATH];
+};
+
+#endif /* __SKIN_H_ */
diff --git a/plugins/Clist_ng/INCLUDE/utils.h b/plugins/Clist_ng/INCLUDE/utils.h new file mode 100644 index 0000000000..24555ff01e --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/utils.h @@ -0,0 +1,137 @@ +/*
+ * 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: utils.h 128 2010-09-26 12:12:56Z silvercircle $
+ */
+
+
+#ifndef __UTILS_H_
+#define __UTILS_H_
+
+class Utils
+{
+public:
+ static void TSAPI enableDlgControl (const HWND hwnd, UINT id, BOOL fEnable);
+ static void TSAPI showDlgControl (const HWND hwnd, UINT id, int showCmd);
+ static HMODULE loadSystemLibrary (const wchar_t* szFilename, bool useGetHandle = false);
+ static void extractResource (const HMODULE h, const UINT uID, const wchar_t* tszName, const wchar_t* tszPath,
+ const wchar_t* tszFilename, bool fForceOverwrite);
+ static void ensureTralingBackslash (wchar_t *szPathname);
+ static DWORD __fastcall hexStringToLong (const char *szSource);
+
+ static int pathIsAbsolute (const wchar_t* path);
+ static size_t pathToRelative (const wchar_t* pSrc, wchar_t* pOut, const wchar_t* szBase = 0);
+ static size_t pathToAbsolute (const wchar_t* pSrc, wchar_t* pOut, const wchar_t* szBase = 0);
+ static const wchar_t* striStr (const wchar_t* szString, const wchar_t* szSearchFor);
+ static const wchar_t* extractURLFromRichEdit (const ENLINK* _e, const HWND hwndRich);
+
+ template<class T, class U, class V, class W> static HRESULT writeProfile(T* _section, U* _key, V* _value, W* _file)
+ {
+ size_t _s = sizeof(T);
+
+ if(_s == 1)
+ return(WritePrivateProfileStringA((char *)_section, (char *)_key, (char *)_value, (char *)_file));
+ else
+ return(WritePrivateProfileStringW((wchar_t *)_section, (wchar_t *)_key, (wchar_t *)_value, (wchar_t *)_file));
+ }
+
+ template<class T, class U, class V> static HRESULT writeProfile(T* _section, U* _key, DWORD _value, const V* _file)
+ {
+ T sValue[1024];
+
+ size_t _s = sizeof(T);
+ if(_s == 1) {
+ _snprintf((char *)sValue, 1024, "%d", _value);
+ sValue[1023] = 0;
+ return(WritePrivateProfileStringA((char *)_section, (char *)_key, (char *)sValue, (char *)_file));
+ }
+ else {
+ _snwprintf((wchar_t *)sValue, 1024, L"%d", _value);
+ sValue[1023] = 0;
+ return(WritePrivateProfileStringW((wchar_t *)_section, (wchar_t *)_key, (wchar_t *)sValue, (wchar_t *)_file));
+ }
+ }
+};
+
+/**
+ * implement a warning dialog with a "do not show this again" check
+ * box
+ */
+
+class WarningDlg {
+
+public:
+ /*
+ * the warning IDs
+ */
+ enum {
+ WARN_RELNOTES = 0,
+ WARN_SKIN_LOADER_ERROR = 1,
+ WARN_SKIN_OVERWRITE = 2,
+ WARN_LAST = 3,
+ };
+
+ /*
+ * the flags (low word is reserved for default windows flags like MB_OK etc.
+ */
+
+ enum {
+ CWF_UNTRANSLATED = 0x00010000, // do not translate the msg (useful for some error messages)
+ CWF_NOALLOWHIDE = 0x00020000 // critical message, hide the "do not show this again" check box
+ };
+
+ WarningDlg(const wchar_t* tszTitle, const wchar_t* tszText, const UINT uId, const DWORD dwFlags);
+ ~WarningDlg();
+
+public:
+ /*
+ * static function to construct and show the dialog, returns the
+ * user's choice
+ */
+ static LRESULT show (const int uId, DWORD dwFlags = 0, const wchar_t* tszTxt = 0);
+ static void destroyAll ();
+ LRESULT ShowDialog () const;
+
+private:
+ UINT m_uId;
+ HFONT m_hFontCaption;
+ DWORD m_dwFlags;
+ HWND m_hwnd;
+ bool m_fIsModal;
+ pSmartWstring m_pszTitle, m_pszText;
+
+ INT_PTR CALLBACK dlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK stubDlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static __int64 getMask (); // get bit mask for disabled message classes
+
+private:
+ static MWindowList hWindowList;
+ static wchar_t* m_warnings[WARN_LAST];
+};
+
+#endif /* __UTILS_H_ */
diff --git a/plugins/Clist_ng/INCLUDE/vsstyle.h b/plugins/Clist_ng/INCLUDE/vsstyle.h new file mode 100644 index 0000000000..b65e223b51 --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/vsstyle.h @@ -0,0 +1,1606 @@ +//-------------------------------------------------------------------------//
+// VisualStyle Style Guide symbols
+//-------------------------------------------------------------------------//
+
+#ifndef __VSSTYLE_H__
+#define __VSSTYLE_H__
+
+//
+// property symbol definitions
+//
+
+#define TMTVS_RESERVEDLOW 100000
+#define TMTVS_RESERVEDHIGH 19999
+
+
+
+//
+// AEROWIZARDSTYLE class parts and states
+//
+#define VSCLASS_AEROWIZARDSTYLE L"AEROWIZARDSTYLE"
+#define VSCLASS_AEROWIZARD L"AEROWIZARD"
+
+enum AEROWIZARDPARTS {
+ AW_TITLEBAR = 1,
+ AW_HEADERAREA = 2,
+ AW_CONTENTAREA = 3,
+ AW_COMMANDAREA = 4,
+ AW_BUTTON = 5,
+};
+
+#define AEROWIZARDSTYLEPARTS AEROWIZARDPARTS;
+
+enum TITLEBARSTATES {
+ AW_S_TITLEBAR_ACTIVE = 1,
+ AW_S_TITLEBAR_INACTIVE = 2,
+};
+
+enum HEADERAREASTATES {
+ AW_S_HEADERAREA_NOMARGIN = 1,
+};
+
+enum CONTENTAREASTATES {
+ AW_S_CONTENTAREA_NOMARGIN = 1,
+};
+
+
+//
+// BUTTONSTYLE class parts and states
+//
+#define VSCLASS_BUTTONSTYLE L"BUTTONSTYLE"
+#define VSCLASS_BUTTON L"BUTTON"
+
+enum BUTTONPARTS {
+ BP_PUSHBUTTON = 1,
+ BP_RADIOBUTTON = 2,
+ BP_CHECKBOX = 3,
+ BP_GROUPBOX = 4,
+ BP_USERBUTTON = 5,
+ BP_COMMANDLINK = 6,
+ BP_COMMANDLINKGLYPH = 7,
+};
+
+#define BUTTONSTYLEPARTS BUTTONPARTS;
+
+enum PUSHBUTTONSTATES {
+ PBS_NORMAL = 1,
+ PBS_HOT = 2,
+ PBS_PRESSED = 3,
+ PBS_DISABLED = 4,
+ PBS_DEFAULTED = 5,
+ PBS_DEFAULTED_ANIMATING = 6,
+};
+
+enum RADIOBUTTONSTATES {
+ RBS_UNCHECKEDNORMAL = 1,
+ RBS_UNCHECKEDHOT = 2,
+ RBS_UNCHECKEDPRESSED = 3,
+ RBS_UNCHECKEDDISABLED = 4,
+ RBS_CHECKEDNORMAL = 5,
+ RBS_CHECKEDHOT = 6,
+ RBS_CHECKEDPRESSED = 7,
+ RBS_CHECKEDDISABLED = 8,
+};
+
+enum CHECKBOXSTATES {
+ CBS_UNCHECKEDNORMAL = 1,
+ CBS_UNCHECKEDHOT = 2,
+ CBS_UNCHECKEDPRESSED = 3,
+ CBS_UNCHECKEDDISABLED = 4,
+ CBS_CHECKEDNORMAL = 5,
+ CBS_CHECKEDHOT = 6,
+ CBS_CHECKEDPRESSED = 7,
+ CBS_CHECKEDDISABLED = 8,
+ CBS_MIXEDNORMAL = 9,
+ CBS_MIXEDHOT = 10,
+ CBS_MIXEDPRESSED = 11,
+ CBS_MIXEDDISABLED = 12,
+ CBS_IMPLICITNORMAL = 13,
+ CBS_IMPLICITHOT = 14,
+ CBS_IMPLICITPRESSED = 15,
+ CBS_IMPLICITDISABLED = 16,
+ CBS_EXCLUDEDNORMAL = 17,
+ CBS_EXCLUDEDHOT = 18,
+ CBS_EXCLUDEDPRESSED = 19,
+ CBS_EXCLUDEDDISABLED = 20,
+};
+
+enum GROUPBOXSTATES {
+ GBS_NORMAL = 1,
+ GBS_DISABLED = 2,
+};
+
+enum COMMANDLINKSTATES {
+ CMDLS_NORMAL = 1,
+ CMDLS_HOT = 2,
+ CMDLS_PRESSED = 3,
+ CMDLS_DISABLED = 4,
+ CMDLS_DEFAULTED = 5,
+ CMDLS_DEFAULTED_ANIMATING = 6,
+};
+
+enum COMMANDLINKGLYPHSTATES {
+ CMDLGS_NORMAL = 1,
+ CMDLGS_HOT = 2,
+ CMDLGS_PRESSED = 3,
+ CMDLGS_DISABLED = 4,
+ CMDLGS_DEFAULTED = 5,
+};
+
+
+//
+// COMBOBOXSTYLE class parts and states
+//
+#define VSCLASS_COMBOBOXSTYLE L"COMBOBOXSTYLE"
+#define VSCLASS_COMBOBOX L"COMBOBOX"
+
+enum COMBOBOXPARTS {
+ CP_DROPDOWNBUTTON = 1,
+ CP_BACKGROUND = 2,
+ CP_TRANSPARENTBACKGROUND = 3,
+ CP_BORDER = 4,
+ CP_READONLY = 5,
+ CP_DROPDOWNBUTTONRIGHT = 6,
+ CP_DROPDOWNBUTTONLEFT = 7,
+ CP_CUEBANNER = 8,
+};
+
+#define COMBOBOXSTYLEPARTS COMBOBOXPARTS;
+
+enum COMBOBOXSTYLESTATES {
+ CBXS_NORMAL = 1,
+ CBXS_HOT = 2,
+ CBXS_PRESSED = 3,
+ CBXS_DISABLED = 4,
+};
+
+enum DROPDOWNBUTTONRIGHTSTATES {
+ CBXSR_NORMAL = 1,
+ CBXSR_HOT = 2,
+ CBXSR_PRESSED = 3,
+ CBXSR_DISABLED = 4,
+};
+
+enum DROPDOWNBUTTONLEFTSTATES {
+ CBXSL_NORMAL = 1,
+ CBXSL_HOT = 2,
+ CBXSL_PRESSED = 3,
+ CBXSL_DISABLED = 4,
+};
+
+enum TRANSPARENTBACKGROUNDSTATES {
+ CBTBS_NORMAL = 1,
+ CBTBS_HOT = 2,
+ CBTBS_DISABLED = 3,
+ CBTBS_FOCUSED = 4,
+};
+
+enum BORDERSTATES {
+ CBB_NORMAL = 1,
+ CBB_HOT = 2,
+ CBB_FOCUSED = 3,
+ CBB_DISABLED = 4,
+};
+
+enum READONLYSTATES {
+ CBRO_NORMAL = 1,
+ CBRO_HOT = 2,
+ CBRO_PRESSED = 3,
+ CBRO_DISABLED = 4,
+};
+
+enum CUEBANNERSTATES {
+ CBCB_NORMAL = 1,
+ CBCB_HOT = 2,
+ CBCB_PRESSED = 3,
+ CBCB_DISABLED = 4,
+};
+
+
+//
+// COMMUNICATIONSSTYLE class parts and states
+//
+#define VSCLASS_COMMUNICATIONSSTYLE L"COMMUNICATIONSSTYLE"
+#define VSCLASS_COMMUNICATIONS L"COMMUNICATIONS"
+
+enum COMMUNICATIONSPARTS {
+ CSST_TAB = 1,
+};
+
+#define COMMUNICATIONSSTYLEPARTS COMMUNICATIONSPARTS;
+
+enum TABSTATES {
+ CSTB_NORMAL = 1,
+ CSTB_HOT = 2,
+ CSTB_SELECTED = 3,
+};
+
+
+//
+// CONTROLPANELSTYLE class parts and states
+//
+#define VSCLASS_CONTROLPANELSTYLE L"CONTROLPANELSTYLE"
+#define VSCLASS_CONTROLPANEL L"CONTROLPANEL"
+
+enum CONTROLPANELPARTS {
+ CPANEL_NAVIGATIONPANE = 1,
+ CPANEL_CONTENTPANE = 2,
+ CPANEL_NAVIGATIONPANELABEL = 3,
+ CPANEL_CONTENTPANELABEL = 4,
+ CPANEL_TITLE = 5,
+ CPANEL_BODYTEXT = 6,
+ CPANEL_HELPLINK = 7,
+ CPANEL_TASKLINK = 8,
+ CPANEL_GROUPTEXT = 9,
+ CPANEL_CONTENTLINK = 10,
+ CPANEL_SECTIONTITLELINK = 11,
+ CPANEL_LARGECOMMANDAREA = 12,
+ CPANEL_SMALLCOMMANDAREA = 13,
+ CPANEL_BUTTON = 14,
+ CPANEL_MESSAGETEXT = 15,
+ CPANEL_NAVIGATIONPANELINE = 16,
+ CPANEL_CONTENTPANELINE = 17,
+ CPANEL_BANNERAREA = 18,
+ CPANEL_BODYTITLE = 19,
+};
+
+#define CONTROLPANELSTYLEPARTS CONTROLPANELPARTS;
+
+enum HELPLINKSTATES {
+ CPHL_NORMAL = 1,
+ CPHL_HOT = 2,
+ CPHL_PRESSED = 3,
+ CPHL_DISABLED = 4,
+};
+
+enum TASKLINKSTATES {
+ CPTL_NORMAL = 1,
+ CPTL_HOT = 2,
+ CPTL_PRESSED = 3,
+ CPTL_DISABLED = 4,
+ CPTL_PAGE = 5,
+};
+
+enum CONTENTLINKSTATES {
+ CPCL_NORMAL = 1,
+ CPCL_HOT = 2,
+ CPCL_PRESSED = 3,
+ CPCL_DISABLED = 4,
+};
+
+enum SECTIONTITLELINKSTATES {
+ CPSTL_NORMAL = 1,
+ CPSTL_HOT = 2,
+};
+
+
+//
+// DATEPICKERSTYLE class parts and states
+//
+#define VSCLASS_DATEPICKERSTYLE L"DATEPICKERSTYLE"
+#define VSCLASS_DATEPICKER L"DATEPICKER"
+
+enum DATEPICKERPARTS {
+ DP_DATETEXT = 1,
+ DP_DATEBORDER = 2,
+ DP_SHOWCALENDARBUTTONRIGHT = 3,
+};
+
+#define DATEPICKERSTYLEPARTS DATEPICKERPARTS;
+
+enum DATETEXTSTATES {
+ DPDT_NORMAL = 1,
+ DPDT_DISABLED = 2,
+ DPDT_SELECTED = 3,
+};
+
+enum DATEBORDERSTATES {
+ DPDB_NORMAL = 1,
+ DPDB_HOT = 2,
+ DPDB_FOCUSED = 3,
+ DPDB_DISABLED = 4,
+};
+
+enum SHOWCALENDARBUTTONRIGHTSTATES {
+ DPSCBR_NORMAL = 1,
+ DPSCBR_HOT = 2,
+ DPSCBR_PRESSED = 3,
+ DPSCBR_DISABLED = 4,
+};
+
+
+//
+// DRAGDROPSTYLE class parts and states
+//
+#define VSCLASS_DRAGDROPSTYLE L"DRAGDROPSTYLE"
+#define VSCLASS_DRAGDROP L"DRAGDROP"
+
+enum DRAGDROPPARTS {
+ DD_COPY = 1,
+ DD_MOVE = 2,
+ DD_UPDATEMETADATA = 3,
+ DD_CREATELINK = 4,
+ DD_WARNING = 5,
+ DD_NONE = 6,
+ DD_IMAGEBG = 7,
+ DD_TEXTBG = 8,
+};
+
+#define DRAGDROPSTYLEPARTS DRAGDROPPARTS;
+
+enum COPYSTATES {
+ DDCOPY_HIGHLIGHT = 1,
+ DDCOPY_NOHIGHLIGHT = 2,
+};
+
+enum MOVESTATES {
+ DDMOVE_HIGHLIGHT = 1,
+ DDMOVE_NOHIGHLIGHT = 2,
+};
+
+enum UPDATEMETADATASTATES {
+ DDUPDATEMETADATA_HIGHLIGHT = 1,
+ DDUPDATEMETADATA_NOHIGHLIGHT = 2,
+};
+
+enum CREATELINKSTATES {
+ DDCREATELINK_HIGHLIGHT = 1,
+ DDCREATELINK_NOHIGHLIGHT = 2,
+};
+
+enum WARNINGSTATES {
+ DDWARNING_HIGHLIGHT = 1,
+ DDWARNING_NOHIGHLIGHT = 2,
+};
+
+enum NONESTATES {
+ DDNONE_HIGHLIGHT = 1,
+ DDNONE_NOHIGHLIGHT = 2,
+};
+
+
+//
+// EDITSTYLE class parts and states
+//
+#define VSCLASS_EDITSTYLE L"EDITSTYLE"
+#define VSCLASS_EDIT L"EDIT"
+
+enum EDITPARTS {
+ EP_EDITTEXT = 1,
+ EP_CARET = 2,
+ EP_BACKGROUND = 3,
+ EP_PASSWORD = 4,
+ EP_BACKGROUNDWITHBORDER = 5,
+ EP_EDITBORDER_NOSCROLL = 6,
+ EP_EDITBORDER_HSCROLL = 7,
+ EP_EDITBORDER_VSCROLL = 8,
+ EP_EDITBORDER_HVSCROLL = 9,
+};
+
+#define EDITSTYLEPARTS EDITPARTS;
+
+enum EDITTEXTSTATES {
+ ETS_NORMAL = 1,
+ ETS_HOT = 2,
+ ETS_SELECTED = 3,
+ ETS_DISABLED = 4,
+ ETS_FOCUSED = 5,
+ ETS_READONLY = 6,
+ ETS_ASSIST = 7,
+ ETS_CUEBANNER = 8,
+};
+
+enum BACKGROUNDSTATES {
+ EBS_NORMAL = 1,
+ EBS_HOT = 2,
+ EBS_DISABLED = 3,
+ EBS_FOCUSED = 4,
+ EBS_READONLY = 5,
+ EBS_ASSIST = 6,
+};
+
+enum BACKGROUNDWITHBORDERSTATES {
+ EBWBS_NORMAL = 1,
+ EBWBS_HOT = 2,
+ EBWBS_DISABLED = 3,
+ EBWBS_FOCUSED = 4,
+};
+
+enum EDITBORDER_NOSCROLLSTATES {
+ EPSN_NORMAL = 1,
+ EPSN_HOT = 2,
+ EPSN_FOCUSED = 3,
+ EPSN_DISABLED = 4,
+};
+
+enum EDITBORDER_HSCROLLSTATES {
+ EPSH_NORMAL = 1,
+ EPSH_HOT = 2,
+ EPSH_FOCUSED = 3,
+ EPSH_DISABLED = 4,
+};
+
+enum EDITBORDER_VSCROLLSTATES {
+ EPSV_NORMAL = 1,
+ EPSV_HOT = 2,
+ EPSV_FOCUSED = 3,
+ EPSV_DISABLED = 4,
+};
+
+enum EDITBORDER_HVSCROLLSTATES {
+ EPSHV_NORMAL = 1,
+ EPSHV_HOT = 2,
+ EPSHV_FOCUSED = 3,
+ EPSHV_DISABLED = 4,
+};
+
+
+//
+// EXPLORERBARSTYLE class parts and states
+//
+#define VSCLASS_EXPLORERBARSTYLE L"EXPLORERBARSTYLE"
+#define VSCLASS_EXPLORERBAR L"EXPLORERBAR"
+
+enum EXPLORERBARPARTS {
+ EBP_HEADERBACKGROUND = 1,
+ EBP_HEADERCLOSE = 2,
+ EBP_HEADERPIN = 3,
+ EBP_IEBARMENU = 4,
+ EBP_NORMALGROUPBACKGROUND = 5,
+ EBP_NORMALGROUPCOLLAPSE = 6,
+ EBP_NORMALGROUPEXPAND = 7,
+ EBP_NORMALGROUPHEAD = 8,
+ EBP_SPECIALGROUPBACKGROUND = 9,
+ EBP_SPECIALGROUPCOLLAPSE = 10,
+ EBP_SPECIALGROUPEXPAND = 11,
+ EBP_SPECIALGROUPHEAD = 12,
+};
+
+#define EXPLORERBARSTYLEPARTS EXPLORERBARPARTS;
+
+enum HEADERCLOSESTATES {
+ EBHC_NORMAL = 1,
+ EBHC_HOT = 2,
+ EBHC_PRESSED = 3,
+};
+
+enum HEADERPINSTATES {
+ EBHP_NORMAL = 1,
+ EBHP_HOT = 2,
+ EBHP_PRESSED = 3,
+ EBHP_SELECTEDNORMAL = 4,
+ EBHP_SELECTEDHOT = 5,
+ EBHP_SELECTEDPRESSED = 6,
+};
+
+enum IEBARMENUSTATES {
+ EBM_NORMAL = 1,
+ EBM_HOT = 2,
+ EBM_PRESSED = 3,
+};
+
+enum NORMALGROUPCOLLAPSESTATES {
+ EBNGC_NORMAL = 1,
+ EBNGC_HOT = 2,
+ EBNGC_PRESSED = 3,
+};
+
+enum NORMALGROUPEXPANDSTATES {
+ EBNGE_NORMAL = 1,
+ EBNGE_HOT = 2,
+ EBNGE_PRESSED = 3,
+};
+
+enum SPECIALGROUPCOLLAPSESTATES {
+ EBSGC_NORMAL = 1,
+ EBSGC_HOT = 2,
+ EBSGC_PRESSED = 3,
+};
+
+enum SPECIALGROUPEXPANDSTATES {
+ EBSGE_NORMAL = 1,
+ EBSGE_HOT = 2,
+ EBSGE_PRESSED = 3,
+};
+
+
+//
+// FLYOUTSTYLE class parts and states
+//
+#define VSCLASS_FLYOUTSTYLE L"FLYOUTSTYLE"
+#define VSCLASS_FLYOUT L"FLYOUT"
+
+enum FLYOUTPARTS {
+ FLYOUT_HEADER = 1,
+ FLYOUT_BODY = 2,
+ FLYOUT_LABEL = 3,
+ FLYOUT_LINK = 4,
+ FLYOUT_DIVIDER = 5,
+ FLYOUT_WINDOW = 6,
+ FLYOUT_LINKAREA = 7,
+ FLYOUT_LINKHEADER = 8,
+};
+
+#define FLYOUTSTYLEPARTS FLYOUTPARTS;
+
+enum LABELSTATES {
+ FLS_NORMAL = 1,
+ FLS_SELECTED = 2,
+ FLS_EMPHASIZED = 3,
+ FLS_DISABLED = 4,
+};
+
+enum LINKSTATES {
+ FLYOUTLINK_NORMAL = 1,
+ FLYOUTLINK_HOVER = 2,
+};
+
+enum BODYSTATES {
+ FBS_NORMAL = 1,
+ FBS_EMPHASIZED = 2,
+};
+
+enum LINKHEADERSTATES {
+ FLH_NORMAL = 1,
+ FLH_HOVER = 2,
+};
+
+
+//
+// HEADERSTYLE class parts and states
+//
+#define VSCLASS_HEADERSTYLE L"HEADERSTYLE"
+#define VSCLASS_HEADER L"HEADER"
+
+enum HEADERPARTS {
+ HP_HEADERITEM = 1,
+ HP_HEADERITEMLEFT = 2,
+ HP_HEADERITEMRIGHT = 3,
+ HP_HEADERSORTARROW = 4,
+ HP_HEADERDROPDOWN = 5,
+ HP_HEADERDROPDOWNFILTER = 6,
+ HP_HEADEROVERFLOW = 7,
+};
+
+#define HEADERSTYLEPARTS HEADERPARTS;
+
+enum HEADERSTYLESTATES {
+ HBG_DETAILS = 1,
+ HBG_ICON = 2,
+};
+
+enum HEADERITEMSTATES {
+ HIS_NORMAL = 1,
+ HIS_HOT = 2,
+ HIS_PRESSED = 3,
+ HIS_SORTEDNORMAL = 4,
+ HIS_SORTEDHOT = 5,
+ HIS_SORTEDPRESSED = 6,
+ HIS_ICONNORMAL = 7,
+ HIS_ICONHOT = 8,
+ HIS_ICONPRESSED = 9,
+ HIS_ICONSORTEDNORMAL = 10,
+ HIS_ICONSORTEDHOT = 11,
+ HIS_ICONSORTEDPRESSED = 12,
+};
+
+enum HEADERITEMLEFTSTATES {
+ HILS_NORMAL = 1,
+ HILS_HOT = 2,
+ HILS_PRESSED = 3,
+};
+
+enum HEADERITEMRIGHTSTATES {
+ HIRS_NORMAL = 1,
+ HIRS_HOT = 2,
+ HIRS_PRESSED = 3,
+};
+
+enum HEADERSORTARROWSTATES {
+ HSAS_SORTEDUP = 1,
+ HSAS_SORTEDDOWN = 2,
+};
+
+enum HEADERDROPDOWNSTATES {
+ HDDS_NORMAL = 1,
+ HDDS_SOFTHOT = 2,
+ HDDS_HOT = 3,
+};
+
+enum HEADERDROPDOWNFILTERSTATES {
+ HDDFS_NORMAL = 1,
+ HDDFS_SOFTHOT = 2,
+ HDDFS_HOT = 3,
+};
+
+enum HEADEROVERFLOWSTATES {
+ HOFS_NORMAL = 1,
+ HOFS_HOT = 2,
+};
+
+
+//
+// LISTBOXSTYLE class parts and states
+//
+#define VSCLASS_LISTBOXSTYLE L"LISTBOXSTYLE"
+#define VSCLASS_LISTBOX L"LISTBOX"
+
+enum LISTBOXPARTS {
+ LBCP_BORDER_HSCROLL = 1,
+ LBCP_BORDER_HVSCROLL = 2,
+ LBCP_BORDER_NOSCROLL = 3,
+ LBCP_BORDER_VSCROLL = 4,
+ LBCP_ITEM = 5,
+};
+
+#define LISTBOXSTYLEPARTS LISTBOXPARTS;
+
+enum BORDER_HSCROLLSTATES {
+ LBPSH_NORMAL = 1,
+ LBPSH_FOCUSED = 2,
+ LBPSH_HOT = 3,
+ LBPSH_DISABLED = 4,
+};
+
+enum BORDER_HVSCROLLSTATES {
+ LBPSHV_NORMAL = 1,
+ LBPSHV_FOCUSED = 2,
+ LBPSHV_HOT = 3,
+ LBPSHV_DISABLED = 4,
+};
+
+enum BORDER_NOSCROLLSTATES {
+ LBPSN_NORMAL = 1,
+ LBPSN_FOCUSED = 2,
+ LBPSN_HOT = 3,
+ LBPSN_DISABLED = 4,
+};
+
+enum BORDER_VSCROLLSTATES {
+ LBPSV_NORMAL = 1,
+ LBPSV_FOCUSED = 2,
+ LBPSV_HOT = 3,
+ LBPSV_DISABLED = 4,
+};
+
+enum ITEMSTATES {
+ LBPSI_HOT = 1,
+ LBPSI_HOTSELECTED = 2,
+ LBPSI_SELECTED = 3,
+ LBPSI_SELECTEDNOTFOCUS = 4,
+};
+
+
+//
+// LISTVIEWSTYLE class parts and states
+//
+#define VSCLASS_LISTVIEWSTYLE L"LISTVIEWSTYLE"
+#define VSCLASS_LISTVIEW L"LISTVIEW"
+
+enum LISTVIEWPARTS {
+ LVP_LISTITEM = 1,
+ LVP_LISTGROUP = 2,
+ LVP_LISTDETAIL = 3,
+ LVP_LISTSORTEDDETAIL = 4,
+ LVP_EMPTYTEXT = 5,
+ LVP_GROUPHEADER = 6,
+ LVP_GROUPHEADERLINE = 7,
+ LVP_EXPANDBUTTON = 8,
+ LVP_COLLAPSEBUTTON = 9,
+ LVP_COLUMNDETAIL = 10,
+};
+
+#define LISTVIEWSTYLEPARTS LISTVIEWPARTS;
+
+enum LISTITEMSTATES {
+ LISS_NORMAL = 1,
+ LISS_HOT = 2,
+ LISS_SELECTED = 3,
+ LISS_DISABLED = 4,
+ LISS_SELECTEDNOTFOCUS = 5,
+ LISS_HOTSELECTED = 6,
+};
+
+enum GROUPHEADERSTATES {
+ LVGH_OPEN = 1,
+ LVGH_OPENHOT = 2,
+ LVGH_OPENSELECTED = 3,
+ LVGH_OPENSELECTEDHOT = 4,
+ LVGH_OPENSELECTEDNOTFOCUSED = 5,
+ LVGH_OPENSELECTEDNOTFOCUSEDHOT = 6,
+ LVGH_OPENMIXEDSELECTION = 7,
+ LVGH_OPENMIXEDSELECTIONHOT = 8,
+ LVGH_CLOSE = 9,
+ LVGH_CLOSEHOT = 10,
+ LVGH_CLOSESELECTED = 11,
+ LVGH_CLOSESELECTEDHOT = 12,
+ LVGH_CLOSESELECTEDNOTFOCUSED = 13,
+ LVGH_CLOSESELECTEDNOTFOCUSEDHOT = 14,
+ LVGH_CLOSEMIXEDSELECTION = 15,
+ LVGH_CLOSEMIXEDSELECTIONHOT = 16,
+};
+
+enum GROUPHEADERLINESTATES {
+ LVGHL_OPEN = 1,
+ LVGHL_OPENHOT = 2,
+ LVGHL_OPENSELECTED = 3,
+ LVGHL_OPENSELECTEDHOT = 4,
+ LVGHL_OPENSELECTEDNOTFOCUSED = 5,
+ LVGHL_OPENSELECTEDNOTFOCUSEDHOT = 6,
+ LVGHL_OPENMIXEDSELECTION = 7,
+ LVGHL_OPENMIXEDSELECTIONHOT = 8,
+ LVGHL_CLOSE = 9,
+ LVGHL_CLOSEHOT = 10,
+ LVGHL_CLOSESELECTED = 11,
+ LVGHL_CLOSESELECTEDHOT = 12,
+ LVGHL_CLOSESELECTEDNOTFOCUSED = 13,
+ LVGHL_CLOSESELECTEDNOTFOCUSEDHOT = 14,
+ LVGHL_CLOSEMIXEDSELECTION = 15,
+ LVGHL_CLOSEMIXEDSELECTIONHOT = 16,
+};
+
+enum EXPANDBUTTONSTATES {
+ LVEB_NORMAL = 1,
+ LVEB_HOVER = 2,
+ LVEB_PUSHED = 3,
+};
+
+enum COLLAPSEBUTTONSTATES {
+ LVCB_NORMAL = 1,
+ LVCB_HOVER = 2,
+ LVCB_PUSHED = 3,
+};
+
+
+//
+// MENUSTYLE class parts and states
+//
+#define VSCLASS_MENUSTYLE L"MENUSTYLE"
+#define VSCLASS_MENU L"MENU"
+
+enum MENUPARTS {
+ MENU_MENUITEM_TMSCHEMA = 1,
+ MENU_MENUDROPDOWN_TMSCHEMA = 2,
+ MENU_MENUBARITEM_TMSCHEMA = 3,
+ MENU_MENUBARDROPDOWN_TMSCHEMA = 4,
+ MENU_CHEVRON_TMSCHEMA = 5,
+ MENU_SEPARATOR_TMSCHEMA = 6,
+ MENU_BARBACKGROUND = 7,
+ MENU_BARITEM = 8,
+ MENU_POPUPBACKGROUND = 9,
+ MENU_POPUPBORDERS = 10,
+ MENU_POPUPCHECK = 11,
+ MENU_POPUPCHECKBACKGROUND = 12,
+ MENU_POPUPGUTTER = 13,
+ MENU_POPUPITEM = 14,
+ MENU_POPUPSEPARATOR = 15,
+ MENU_POPUPSUBMENU = 16,
+ MENU_SYSTEMCLOSE = 17,
+ MENU_SYSTEMMAXIMIZE = 18,
+ MENU_SYSTEMMINIMIZE = 19,
+ MENU_SYSTEMRESTORE = 20,
+};
+
+#define MENUSTYLEPARTS MENUPARTS;
+
+enum BARBACKGROUNDSTATES {
+ MB_ACTIVE = 1,
+ MB_INACTIVE = 2,
+};
+
+enum BARITEMSTATES {
+ MBI_NORMAL = 1,
+ MBI_HOT = 2,
+ MBI_PUSHED = 3,
+ MBI_DISABLED = 4,
+ MBI_DISABLEDHOT = 5,
+ MBI_DISABLEDPUSHED = 6,
+};
+
+enum POPUPCHECKSTATES {
+ MC_CHECKMARKNORMAL = 1,
+ MC_CHECKMARKDISABLED = 2,
+ MC_BULLETNORMAL = 3,
+ MC_BULLETDISABLED = 4,
+};
+
+enum POPUPCHECKBACKGROUNDSTATES {
+ MCB_DISABLED = 1,
+ MCB_NORMAL = 2,
+ MCB_BITMAP = 3,
+};
+
+enum POPUPITEMSTATES {
+ MPI_NORMAL = 1,
+ MPI_HOT = 2,
+ MPI_DISABLED = 3,
+ MPI_DISABLEDHOT = 4,
+};
+
+enum POPUPSUBMENUSTATES {
+ MSM_NORMAL = 1,
+ MSM_DISABLED = 2,
+};
+
+enum SYSTEMCLOSESTATES {
+ MSYSC_NORMAL = 1,
+ MSYSC_DISABLED = 2,
+};
+
+enum SYSTEMMAXIMIZESTATES {
+ MSYSMX_NORMAL = 1,
+ MSYSMX_DISABLED = 2,
+};
+
+enum SYSTEMMINIMIZESTATES {
+ MSYSMN_NORMAL = 1,
+ MSYSMN_DISABLED = 2,
+};
+
+enum SYSTEMRESTORESTATES {
+ MSYSR_NORMAL = 1,
+ MSYSR_DISABLED = 2,
+};
+
+
+//
+// NAVIGATION class parts and states
+//
+#define VSCLASS_NAVIGATION L"NAVIGATION"
+
+enum NAVIGATIONPARTS {
+ NAV_BACKBUTTON = 1,
+ NAV_FORWARDBUTTON = 2,
+ NAV_MENUBUTTON = 3,
+};
+
+enum NAV_BACKBUTTONSTATES {
+ NAV_BB_NORMAL = 1,
+ NAV_BB_HOT = 2,
+ NAV_BB_PRESSED = 3,
+ NAV_BB_DISABLED = 4,
+};
+
+enum NAV_FORWARDBUTTONSTATES {
+ NAV_FB_NORMAL = 1,
+ NAV_FB_HOT = 2,
+ NAV_FB_PRESSED = 3,
+ NAV_FB_DISABLED = 4,
+};
+
+enum NAV_MENUBUTTONSTATES {
+ NAV_MB_NORMAL = 1,
+ NAV_MB_HOT = 2,
+ NAV_MB_PRESSED = 3,
+ NAV_MB_DISABLED = 4,
+};
+
+
+//
+// PROGRESSSTYLE class parts and states
+//
+#define VSCLASS_PROGRESSSTYLE L"PROGRESSSTYLE"
+#define VSCLASS_PROGRESS L"PROGRESS"
+
+enum PROGRESSPARTS {
+ PP_BAR = 1,
+ PP_BARVERT = 2,
+ PP_CHUNK = 3,
+ PP_CHUNKVERT = 4,
+ PP_FILL = 5,
+ PP_FILLVERT = 6,
+ PP_PULSEOVERLAY = 7,
+ PP_MOVEOVERLAY = 8,
+ PP_PULSEOVERLAYVERT = 9,
+ PP_MOVEOVERLAYVERT = 10,
+ PP_TRANSPARENTBAR = 11,
+ PP_TRANSPARENTBARVERT = 12,
+};
+
+#define PROGRESSSTYLEPARTS PROGRESSPARTS;
+
+enum TRANSPARENTBARSTATES {
+ PBBS_NORMAL = 1,
+ PBBS_PARTIAL = 2,
+};
+
+enum TRANSPARENTBARVERTSTATES {
+ PBBVS_NORMAL = 1,
+ PBBVS_PARTIAL = 2,
+};
+
+enum FILLSTATES {
+ PBFS_NORMAL = 1,
+ PBFS_ERROR = 2,
+ PBFS_PAUSED = 3,
+ PBFS_PARTIAL = 4,
+};
+
+enum FILLVERTSTATES {
+ PBFVS_NORMAL = 1,
+ PBFVS_ERROR = 2,
+ PBFVS_PAUSED = 3,
+ PBFVS_PARTIAL = 4,
+};
+
+
+//
+// REBARSTYLE class parts and states
+//
+#define VSCLASS_REBARSTYLE L"REBARSTYLE"
+#define VSCLASS_REBAR L"REBAR"
+
+enum REBARPARTS {
+ RP_GRIPPER = 1,
+ RP_GRIPPERVERT = 2,
+ RP_BAND = 3,
+ RP_CHEVRON = 4,
+ RP_CHEVRONVERT = 5,
+ RP_BACKGROUND = 6,
+ RP_SPLITTER = 7,
+ RP_SPLITTERVERT = 8,
+};
+
+#define REBARSTYLEPARTS REBARPARTS;
+
+enum CHEVRONSTATES {
+ CHEVS_NORMAL = 1,
+ CHEVS_HOT = 2,
+ CHEVS_PRESSED = 3,
+};
+
+enum CHEVRONVERTSTATES {
+ CHEVSV_NORMAL = 1,
+ CHEVSV_HOT = 2,
+ CHEVSV_PRESSED = 3,
+};
+
+enum SPLITTERSTATES {
+ SPLITS_NORMAL = 1,
+ SPLITS_HOT = 2,
+ SPLITS_PRESSED = 3,
+};
+
+enum SPLITTERVERTSTATES {
+ SPLITSV_NORMAL = 1,
+ SPLITSV_HOT = 2,
+ SPLITSV_PRESSED = 3,
+};
+
+
+//
+// SCROLLBARSTYLE class parts and states
+//
+#define VSCLASS_SCROLLBARSTYLE L"SCROLLBARSTYLE"
+#define VSCLASS_SCROLLBAR L"SCROLLBAR"
+
+enum SCROLLBARPARTS {
+ SBP_ARROWBTN = 1,
+ SBP_THUMBBTNHORZ = 2,
+ SBP_THUMBBTNVERT = 3,
+ SBP_LOWERTRACKHORZ = 4,
+ SBP_UPPERTRACKHORZ = 5,
+ SBP_LOWERTRACKVERT = 6,
+ SBP_UPPERTRACKVERT = 7,
+ SBP_GRIPPERHORZ = 8,
+ SBP_GRIPPERVERT = 9,
+ SBP_SIZEBOX = 10,
+};
+
+#define SCROLLBARSTYLEPARTS SCROLLBARPARTS;
+
+enum ARROWBTNSTATES {
+ ABS_UPNORMAL = 1,
+ ABS_UPHOT = 2,
+ ABS_UPPRESSED = 3,
+ ABS_UPDISABLED = 4,
+ ABS_DOWNNORMAL = 5,
+ ABS_DOWNHOT = 6,
+ ABS_DOWNPRESSED = 7,
+ ABS_DOWNDISABLED = 8,
+ ABS_LEFTNORMAL = 9,
+ ABS_LEFTHOT = 10,
+ ABS_LEFTPRESSED = 11,
+ ABS_LEFTDISABLED = 12,
+ ABS_RIGHTNORMAL = 13,
+ ABS_RIGHTHOT = 14,
+ ABS_RIGHTPRESSED = 15,
+ ABS_RIGHTDISABLED = 16,
+ ABS_UPHOVER = 17,
+ ABS_DOWNHOVER = 18,
+ ABS_LEFTHOVER = 19,
+ ABS_RIGHTHOVER = 20,
+};
+
+enum SCROLLBARSTYLESTATES {
+ SCRBS_NORMAL = 1,
+ SCRBS_HOT = 2,
+ SCRBS_PRESSED = 3,
+ SCRBS_DISABLED = 4,
+ SCRBS_HOVER = 5,
+};
+
+enum SIZEBOXSTATES {
+ SZB_RIGHTALIGN = 1,
+ SZB_LEFTALIGN = 2,
+ SZB_TOPRIGHTALIGN = 3,
+ SZB_TOPLEFTALIGN = 4,
+ SZB_HALFBOTTOMRIGHTALIGN = 5,
+ SZB_HALFBOTTOMLEFTALIGN = 6,
+ SZB_HALFTOPRIGHTALIGN = 7,
+ SZB_HALFTOPLEFTALIGN = 8,
+};
+
+
+//
+// SPINSTYLE class parts and states
+//
+#define VSCLASS_SPINSTYLE L"SPINSTYLE"
+#define VSCLASS_SPIN L"SPIN"
+
+enum SPINPARTS {
+ SPNP_UP = 1,
+ SPNP_DOWN = 2,
+ SPNP_UPHORZ = 3,
+ SPNP_DOWNHORZ = 4,
+};
+
+#define SPINSTYLEPARTS SPINPARTS;
+
+enum UPSTATES {
+ UPS_NORMAL = 1,
+ UPS_HOT = 2,
+ UPS_PRESSED = 3,
+ UPS_DISABLED = 4,
+};
+
+enum DOWNSTATES {
+ DNS_NORMAL = 1,
+ DNS_HOT = 2,
+ DNS_PRESSED = 3,
+ DNS_DISABLED = 4,
+};
+
+enum UPHORZSTATES {
+ UPHZS_NORMAL = 1,
+ UPHZS_HOT = 2,
+ UPHZS_PRESSED = 3,
+ UPHZS_DISABLED = 4,
+};
+
+enum DOWNHORZSTATES {
+ DNHZS_NORMAL = 1,
+ DNHZS_HOT = 2,
+ DNHZS_PRESSED = 3,
+ DNHZS_DISABLED = 4,
+};
+
+
+//
+// STATUSSTYLE class parts and states
+//
+#define VSCLASS_STATUSSTYLE L"STATUSSTYLE"
+#define VSCLASS_STATUS L"STATUS"
+
+enum STATUSPARTS {
+ SP_PANE = 1,
+ SP_GRIPPERPANE = 2,
+ SP_GRIPPER = 3,
+};
+
+#define STATUSSTYLEPARTS STATUSPARTS;
+
+
+//
+// TABSTYLE class parts and states
+//
+#define VSCLASS_TABSTYLE L"TABSTYLE"
+#define VSCLASS_TAB L"TAB"
+
+enum TABPARTS {
+ TABP_TABITEM = 1,
+ TABP_TABITEMLEFTEDGE = 2,
+ TABP_TABITEMRIGHTEDGE = 3,
+ TABP_TABITEMBOTHEDGE = 4,
+ TABP_TOPTABITEM = 5,
+ TABP_TOPTABITEMLEFTEDGE = 6,
+ TABP_TOPTABITEMRIGHTEDGE = 7,
+ TABP_TOPTABITEMBOTHEDGE = 8,
+ TABP_PANE = 9,
+ TABP_BODY = 10,
+ TABP_AEROWIZARDBODY = 11,
+};
+
+#define TABSTYLEPARTS TABPARTS;
+
+enum TABITEMSTATES {
+ TIS_NORMAL = 1,
+ TIS_HOT = 2,
+ TIS_SELECTED = 3,
+ TIS_DISABLED = 4,
+ TIS_FOCUSED = 5,
+};
+
+enum TABITEMLEFTEDGESTATES {
+ TILES_NORMAL = 1,
+ TILES_HOT = 2,
+ TILES_SELECTED = 3,
+ TILES_DISABLED = 4,
+ TILES_FOCUSED = 5,
+};
+
+enum TABITEMRIGHTEDGESTATES {
+ TIRES_NORMAL = 1,
+ TIRES_HOT = 2,
+ TIRES_SELECTED = 3,
+ TIRES_DISABLED = 4,
+ TIRES_FOCUSED = 5,
+};
+
+enum TABITEMBOTHEDGESTATES {
+ TIBES_NORMAL = 1,
+ TIBES_HOT = 2,
+ TIBES_SELECTED = 3,
+ TIBES_DISABLED = 4,
+ TIBES_FOCUSED = 5,
+};
+
+enum TOPTABITEMSTATES {
+ TTIS_NORMAL = 1,
+ TTIS_HOT = 2,
+ TTIS_SELECTED = 3,
+ TTIS_DISABLED = 4,
+ TTIS_FOCUSED = 5,
+};
+
+enum TOPTABITEMLEFTEDGESTATES {
+ TTILES_NORMAL = 1,
+ TTILES_HOT = 2,
+ TTILES_SELECTED = 3,
+ TTILES_DISABLED = 4,
+ TTILES_FOCUSED = 5,
+};
+
+enum TOPTABITEMRIGHTEDGESTATES {
+ TTIRES_NORMAL = 1,
+ TTIRES_HOT = 2,
+ TTIRES_SELECTED = 3,
+ TTIRES_DISABLED = 4,
+ TTIRES_FOCUSED = 5,
+};
+
+enum TOPTABITEMBOTHEDGESTATES {
+ TTIBES_NORMAL = 1,
+ TTIBES_HOT = 2,
+ TTIBES_SELECTED = 3,
+ TTIBES_DISABLED = 4,
+ TTIBES_FOCUSED = 5,
+};
+
+
+//
+// TASKDIALOGSTYLE class parts and states
+//
+#define VSCLASS_TASKDIALOGSTYLE L"TASKDIALOGSTYLE"
+#define VSCLASS_TASKDIALOG L"TASKDIALOG"
+
+enum TASKDIALOGPARTS {
+ TDLG_PRIMARYPANEL = 1,
+ TDLG_MAININSTRUCTIONPANE = 2,
+ TDLG_MAINICON = 3,
+ TDLG_CONTENTPANE = 4,
+ TDLG_CONTENTICON = 5,
+ TDLG_EXPANDEDCONTENT = 6,
+ TDLG_COMMANDLINKPANE = 7,
+ TDLG_SECONDARYPANEL = 8,
+ TDLG_CONTROLPANE = 9,
+ TDLG_BUTTONSECTION = 10,
+ TDLG_BUTTONWRAPPER = 11,
+ TDLG_EXPANDOTEXT = 12,
+ TDLG_EXPANDOBUTTON = 13,
+ TDLG_VERIFICATIONTEXT = 14,
+ TDLG_FOOTNOTEPANE = 15,
+ TDLG_FOOTNOTEAREA = 16,
+ TDLG_FOOTNOTESEPARATOR = 17,
+ TDLG_EXPANDEDFOOTERAREA = 18,
+ TDLG_PROGRESSBAR = 19,
+ TDLG_IMAGEALIGNMENT = 20,
+ TDLG_RADIOBUTTONPANE = 21,
+};
+
+#define TASKDIALOGSTYLEPARTS TASKDIALOGPARTS;
+
+enum CONTENTPANESTATES {
+ TDLGCPS_STANDALONE = 1,
+};
+
+enum EXPANDOBUTTONSTATES {
+ TDLGEBS_NORMAL = 1,
+ TDLGEBS_HOVER = 2,
+ TDLGEBS_PRESSED = 3,
+ TDLGEBS_EXPANDEDNORMAL = 4,
+ TDLGEBS_EXPANDEDHOVER = 5,
+ TDLGEBS_EXPANDEDPRESSED = 6,
+};
+
+
+//
+// TEXTSTYLE class parts and states
+//
+#define VSCLASS_TEXTSTYLE L"TEXTSTYLE"
+
+enum TEXTSTYLEPARTS {
+ TEXT_MAININSTRUCTION = 1,
+ TEXT_INSTRUCTION = 2,
+ TEXT_BODYTITLE = 3,
+ TEXT_BODYTEXT = 4,
+ TEXT_SECONDARYTEXT = 5,
+ TEXT_HYPERLINKTEXT = 6,
+ TEXT_EXPANDED = 7,
+ TEXT_LABEL = 8,
+ TEXT_CONTROLLABEL = 9,
+};
+
+enum HYPERLINKTEXTSTATES {
+ TS_HYPERLINK_NORMAL = 1,
+ TS_HYPERLINK_HOT = 2,
+ TS_HYPERLINK_PRESSED = 3,
+ TS_HYPERLINK_DISABLED = 4,
+};
+
+enum CONTROLLABELSTATES {
+ TS_CONTROLLABEL_NORMAL = 1,
+ TS_CONTROLLABEL_DISABLED = 2,
+};
+
+
+//
+// TOOLBARSTYLE class parts and states
+//
+#define VSCLASS_TOOLBARSTYLE L"TOOLBARSTYLE"
+#define VSCLASS_TOOLBAR L"TOOLBAR"
+
+enum TOOLBARPARTS {
+ TP_BUTTON = 1,
+ TP_DROPDOWNBUTTON = 2,
+ TP_SPLITBUTTON = 3,
+ TP_SPLITBUTTONDROPDOWN = 4,
+ TP_SEPARATOR = 5,
+ TP_SEPARATORVERT = 6,
+ TP_DROPDOWNBUTTONGLYPH = 7,
+};
+
+#define TOOLBARSTYLEPARTS TOOLBARPARTS;
+
+enum TOOLBARSTYLESTATES {
+ TS_NORMAL = 1,
+ TS_HOT = 2,
+ TS_PRESSED = 3,
+ TS_DISABLED = 4,
+ TS_CHECKED = 5,
+ TS_HOTCHECKED = 6,
+ TS_NEARHOT = 7,
+ TS_OTHERSIDEHOT = 8,
+};
+
+
+//
+// TOOLTIPSTYLE class parts and states
+//
+#define VSCLASS_TOOLTIPSTYLE L"TOOLTIPSTYLE"
+#define VSCLASS_TOOLTIP L"TOOLTIP"
+
+enum TOOLTIPPARTS {
+ TTP_STANDARD = 1,
+ TTP_STANDARDTITLE = 2,
+ TTP_BALLOON = 3,
+ TTP_BALLOONTITLE = 4,
+ TTP_CLOSE = 5,
+ TTP_BALLOONSTEM = 6,
+ TTP_WRENCH = 7,
+};
+
+#define TOOLTIPSTYLEPARTS TOOLTIPPARTS;
+
+enum CLOSESTATES {
+ TTCS_NORMAL = 1,
+ TTCS_HOT = 2,
+ TTCS_PRESSED = 3,
+};
+
+enum STANDARDSTATES {
+ TTSS_NORMAL = 1,
+ TTSS_LINK = 2,
+};
+
+enum BALLOONSTATES {
+ TTBS_NORMAL = 1,
+ TTBS_LINK = 2,
+};
+
+enum BALLOONSTEMSTATES {
+ TTBSS_POINTINGUPLEFTWALL = 1,
+ TTBSS_POINTINGUPCENTERED = 2,
+ TTBSS_POINTINGUPRIGHTWALL = 3,
+ TTBSS_POINTINGDOWNRIGHTWALL = 4,
+ TTBSS_POINTINGDOWNCENTERED = 5,
+ TTBSS_POINTINGDOWNLEFTWALL = 6,
+};
+
+enum WRENCHSTATES {
+ TTWS_NORMAL = 1,
+ TTWS_HOT = 2,
+ TTWS_PRESSED = 3,
+};
+
+
+//
+// TRACKBARSTYLE class parts and states
+//
+#define VSCLASS_TRACKBARSTYLE L"TRACKBARSTYLE"
+#define VSCLASS_TRACKBAR L"TRACKBAR"
+
+enum TRACKBARPARTS {
+ TKP_TRACK = 1,
+ TKP_TRACKVERT = 2,
+ TKP_THUMB = 3,
+ TKP_THUMBBOTTOM = 4,
+ TKP_THUMBTOP = 5,
+ TKP_THUMBVERT = 6,
+ TKP_THUMBLEFT = 7,
+ TKP_THUMBRIGHT = 8,
+ TKP_TICS = 9,
+ TKP_TICSVERT = 10,
+};
+
+#define TRACKBARSTYLEPARTS TRACKBARPARTS;
+
+enum TRACKBARSTYLESTATES {
+ TKS_NORMAL = 1,
+};
+
+enum TRACKSTATES {
+ TRS_NORMAL = 1,
+};
+
+enum TRACKVERTSTATES {
+ TRVS_NORMAL = 1,
+};
+
+enum THUMBSTATES {
+ TUS_NORMAL = 1,
+ TUS_HOT = 2,
+ TUS_PRESSED = 3,
+ TUS_FOCUSED = 4,
+ TUS_DISABLED = 5,
+};
+
+enum THUMBBOTTOMSTATES {
+ TUBS_NORMAL = 1,
+ TUBS_HOT = 2,
+ TUBS_PRESSED = 3,
+ TUBS_FOCUSED = 4,
+ TUBS_DISABLED = 5,
+};
+
+enum THUMBTOPSTATES {
+ TUTS_NORMAL = 1,
+ TUTS_HOT = 2,
+ TUTS_PRESSED = 3,
+ TUTS_FOCUSED = 4,
+ TUTS_DISABLED = 5,
+};
+
+enum THUMBVERTSTATES {
+ TUVS_NORMAL = 1,
+ TUVS_HOT = 2,
+ TUVS_PRESSED = 3,
+ TUVS_FOCUSED = 4,
+ TUVS_DISABLED = 5,
+};
+
+enum THUMBLEFTSTATES {
+ TUVLS_NORMAL = 1,
+ TUVLS_HOT = 2,
+ TUVLS_PRESSED = 3,
+ TUVLS_FOCUSED = 4,
+ TUVLS_DISABLED = 5,
+};
+
+enum THUMBRIGHTSTATES {
+ TUVRS_NORMAL = 1,
+ TUVRS_HOT = 2,
+ TUVRS_PRESSED = 3,
+ TUVRS_FOCUSED = 4,
+ TUVRS_DISABLED = 5,
+};
+
+enum TICSSTATES {
+ TSS_NORMAL = 1,
+};
+
+enum TICSVERTSTATES {
+ TSVS_NORMAL = 1,
+};
+
+
+//
+// TREEVIEWSTYLE class parts and states
+//
+#define VSCLASS_TREEVIEWSTYLE L"TREEVIEWSTYLE"
+#define VSCLASS_TREEVIEW L"TREEVIEW"
+
+enum TREEVIEWPARTS {
+ TVP_TREEITEM = 1,
+ TVP_GLYPH = 2,
+ TVP_BRANCH = 3,
+ TVP_HOTGLYPH = 4,
+};
+
+#define TREEVIEWSTYLEPARTS TREEVIEWPARTS;
+
+enum TREEITEMSTATES {
+ TREIS_NORMAL = 1,
+ TREIS_HOT = 2,
+ TREIS_SELECTED = 3,
+ TREIS_DISABLED = 4,
+ TREIS_SELECTEDNOTFOCUS = 5,
+ TREIS_HOTSELECTED = 6,
+};
+
+enum GLYPHSTATES {
+ GLPS_CLOSED = 1,
+ GLPS_OPENED = 2,
+};
+
+enum HOTGLYPHSTATES {
+ HGLPS_CLOSED = 1,
+ HGLPS_OPENED = 2,
+};
+
+
+//
+// WINDOWSTYLE class parts and states
+//
+#define VSCLASS_WINDOWSTYLE L"WINDOWSTYLE"
+#define VSCLASS_WINDOW L"WINDOW"
+
+enum WINDOWPARTS {
+ WP_CAPTION = 1,
+ WP_SMALLCAPTION = 2,
+ WP_MINCAPTION = 3,
+ WP_SMALLMINCAPTION = 4,
+ WP_MAXCAPTION = 5,
+ WP_SMALLMAXCAPTION = 6,
+ WP_FRAMELEFT = 7,
+ WP_FRAMERIGHT = 8,
+ WP_FRAMEBOTTOM = 9,
+ WP_SMALLFRAMELEFT = 10,
+ WP_SMALLFRAMERIGHT = 11,
+ WP_SMALLFRAMEBOTTOM = 12,
+ WP_SYSBUTTON = 13,
+ WP_MDISYSBUTTON = 14,
+ WP_MINBUTTON = 15,
+ WP_MDIMINBUTTON = 16,
+ WP_MAXBUTTON = 17,
+ WP_CLOSEBUTTON = 18,
+ WP_SMALLCLOSEBUTTON = 19,
+ WP_MDICLOSEBUTTON = 20,
+ WP_RESTOREBUTTON = 21,
+ WP_MDIRESTOREBUTTON = 22,
+ WP_HELPBUTTON = 23,
+ WP_MDIHELPBUTTON = 24,
+ WP_HORZSCROLL = 25,
+ WP_HORZTHUMB = 26,
+ WP_VERTSCROLL = 27,
+ WP_VERTTHUMB = 28,
+ WP_DIALOG = 29,
+ WP_CAPTIONSIZINGTEMPLATE = 30,
+ WP_SMALLCAPTIONSIZINGTEMPLATE = 31,
+ WP_FRAMELEFTSIZINGTEMPLATE = 32,
+ WP_SMALLFRAMELEFTSIZINGTEMPLATE = 33,
+ WP_FRAMERIGHTSIZINGTEMPLATE = 34,
+ WP_SMALLFRAMERIGHTSIZINGTEMPLATE = 35,
+ WP_FRAMEBOTTOMSIZINGTEMPLATE = 36,
+ WP_SMALLFRAMEBOTTOMSIZINGTEMPLATE = 37,
+ WP_FRAME = 38,
+};
+
+#define WINDOWSTYLEPARTS WINDOWPARTS;
+
+enum FRAMESTATES {
+ FS_ACTIVE = 1,
+ FS_INACTIVE = 2,
+};
+
+enum CAPTIONSTATES {
+ CS_ACTIVE = 1,
+ CS_INACTIVE = 2,
+ CS_DISABLED = 3,
+};
+
+enum MAXCAPTIONSTATES {
+ MXCS_ACTIVE = 1,
+ MXCS_INACTIVE = 2,
+ MXCS_DISABLED = 3,
+};
+
+enum MINCAPTIONSTATES {
+ MNCS_ACTIVE = 1,
+ MNCS_INACTIVE = 2,
+ MNCS_DISABLED = 3,
+};
+
+enum HORZSCROLLSTATES {
+ HSS_NORMAL = 1,
+ HSS_HOT = 2,
+ HSS_PUSHED = 3,
+ HSS_DISABLED = 4,
+};
+
+enum HORZTHUMBSTATES {
+ HTS_NORMAL = 1,
+ HTS_HOT = 2,
+ HTS_PUSHED = 3,
+ HTS_DISABLED = 4,
+};
+
+enum VERTSCROLLSTATES {
+ VSS_NORMAL = 1,
+ VSS_HOT = 2,
+ VSS_PUSHED = 3,
+ VSS_DISABLED = 4,
+};
+
+enum VERTTHUMBSTATES {
+ VTS_NORMAL = 1,
+ VTS_HOT = 2,
+ VTS_PUSHED = 3,
+ VTS_DISABLED = 4,
+};
+
+enum SYSBUTTONSTATES {
+ SBS_NORMAL = 1,
+ SBS_HOT = 2,
+ SBS_PUSHED = 3,
+ SBS_DISABLED = 4,
+};
+
+enum MINBUTTONSTATES {
+ MINBS_NORMAL = 1,
+ MINBS_HOT = 2,
+ MINBS_PUSHED = 3,
+ MINBS_DISABLED = 4,
+};
+
+enum MAXBUTTONSTATES {
+ MAXBS_NORMAL = 1,
+ MAXBS_HOT = 2,
+ MAXBS_PUSHED = 3,
+ MAXBS_DISABLED = 4,
+};
+
+enum RESTOREBUTTONSTATES {
+ RBS_NORMAL = 1,
+ RBS_HOT = 2,
+ RBS_PUSHED = 3,
+ RBS_DISABLED = 4,
+};
+
+enum HELPBUTTONSTATES {
+ HBS_NORMAL = 1,
+ HBS_HOT = 2,
+ HBS_PUSHED = 3,
+ HBS_DISABLED = 4,
+};
+
+enum CLOSEBUTTONSTATES {
+ CBS_NORMAL = 1,
+ CBS_HOT = 2,
+ CBS_PUSHED = 3,
+ CBS_DISABLED = 4,
+};
+
+
+#endif //__VSSTYLE_H__
+
diff --git a/plugins/Clist_ng/INCLUDE/vssym32.h b/plugins/Clist_ng/INCLUDE/vssym32.h new file mode 100644 index 0000000000..4d2b6fd62d --- /dev/null +++ b/plugins/Clist_ng/INCLUDE/vssym32.h @@ -0,0 +1,712 @@ +//-------------------------------------------------------------------------//
+// VisualStyle Core Win32/ComCtl32 symbols
+//-------------------------------------------------------------------------//
+
+#ifndef __VSSYM32_H__
+#define __VSSYM32_H__
+
+#include "VSStyle.h"
+
+//
+// enumerated property values
+//
+
+enum BGTYPE {
+ BT_IMAGEFILE = 0,
+ BT_BORDERFILL = 1,
+ BT_NONE = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum IMAGELAYOUT {
+ IL_VERTICAL = 0,
+ IL_HORIZONTAL = 1,
+};
+
+
+//
+// enumerated property values
+//
+
+enum BORDERTYPE {
+ BT_RECT = 0,
+ BT_ROUNDRECT = 1,
+ BT_ELLIPSE = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum FILLTYPE {
+ FT_SOLID = 0,
+ FT_VERTGRADIENT = 1,
+ FT_HORZGRADIENT = 2,
+ FT_RADIALGRADIENT = 3,
+ FT_TILEIMAGE = 4,
+};
+
+
+//
+// enumerated property values
+//
+
+enum SIZINGTYPE {
+ ST_TRUESIZE = 0,
+ ST_STRETCH = 1,
+ ST_TILE = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum HALIGN {
+ HA_LEFT = 0,
+ HA_CENTER = 1,
+ HA_RIGHT = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum CONTENTALIGNMENT {
+ CA_LEFT = 0,
+ CA_CENTER = 1,
+ CA_RIGHT = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum VALIGN {
+ VA_TOP = 0,
+ VA_CENTER = 1,
+ VA_BOTTOM = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum OFFSETTYPE {
+ OT_TOPLEFT = 0,
+ OT_TOPRIGHT = 1,
+ OT_TOPMIDDLE = 2,
+ OT_BOTTOMLEFT = 3,
+ OT_BOTTOMRIGHT = 4,
+ OT_BOTTOMMIDDLE = 5,
+ OT_MIDDLELEFT = 6,
+ OT_MIDDLERIGHT = 7,
+ OT_LEFTOFCAPTION = 8,
+ OT_RIGHTOFCAPTION = 9,
+ OT_LEFTOFLASTBUTTON = 10,
+ OT_RIGHTOFLASTBUTTON = 11,
+ OT_ABOVELASTBUTTON = 12,
+ OT_BELOWLASTBUTTON = 13,
+};
+
+
+//
+// enumerated property values
+//
+
+enum ICONEFFECT {
+ ICE_NONE = 0,
+ ICE_GLOW = 1,
+ ICE_SHADOW = 2,
+ ICE_PULSE = 3,
+ ICE_ALPHA = 4,
+};
+
+
+//
+// enumerated property values
+//
+
+enum TEXTSHADOWTYPE {
+ TST_NONE = 0,
+ TST_SINGLE = 1,
+ TST_CONTINUOUS = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum GLYPHTYPE {
+ GT_NONE = 0,
+ GT_IMAGEGLYPH = 1,
+ GT_FONTGLYPH = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum IMAGESELECTTYPE {
+ IST_NONE = 0,
+ IST_SIZE = 1,
+ IST_DPI = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum TRUESIZESCALINGTYPE {
+ TSST_NONE = 0,
+ TSST_SIZE = 1,
+ TSST_DPI = 2,
+};
+
+
+//
+// enumerated property values
+//
+
+enum GLYPHFONTSIZINGTYPE {
+ GFST_NONE = 0,
+ GFST_SIZE = 1,
+ GFST_DPI = 2,
+};
+
+//
+// property symbol definitions
+//
+
+#define TMT_RESERVEDLOW 0
+#define TMT_RESERVEDHIGH 7999
+
+#define TMT_DIBDATA 2
+#define TMT_GLYPHDIBDATA 8
+#define TMT_ENUM 200
+#define TMT_STRING 201
+#define TMT_INT 202
+#define TMT_BOOL 203
+#define TMT_COLOR 204
+#define TMT_MARGINS 205
+#define TMT_FILENAME 206
+#define TMT_SIZE 207
+#define TMT_POSITION 208
+#define TMT_RECT 209
+#define TMT_FONT 210
+#define TMT_INTLIST 211
+#define TMT_HBITMAP 212
+#define TMT_DISKSTREAM 213
+#define TMT_STREAM 214
+#define TMT_BITMAPREF 215
+#define TMT_COLORSCHEMES 401
+#define TMT_SIZES 402
+#define TMT_CHARSET 403
+#define TMT_NAME 600
+#define TMT_DISPLAYNAME 601
+#define TMT_TOOLTIP 602
+#define TMT_COMPANY 603
+#define TMT_AUTHOR 604
+#define TMT_COPYRIGHT 605
+#define TMT_URL 606
+#define TMT_VERSION 607
+#define TMT_DESCRIPTION 608
+#define TMT_FIRST_RCSTRING_NAME TMT_DISPLAYNAME
+#define TMT_LAST_RCSTRING_NAME TMT_DESCRIPTION
+#define TMT_CAPTIONFONT 801
+#define TMT_SMALLCAPTIONFONT 802
+#define TMT_MENUFONT 803
+#define TMT_STATUSFONT 804
+#define TMT_MSGBOXFONT 805
+#define TMT_ICONTITLEFONT 806
+#define TMT_HEADING1FONT 807
+#define TMT_HEADING2FONT 808
+#define TMT_BODYFONT 809
+#define TMT_FIRSTFONT TMT_CAPTIONFONT
+#define TMT_LASTFONT TMT_BODYFONT
+#define TMT_FLATMENUS 1001
+#define TMT_FIRSTBOOL TMT_FLATMENUS
+#define TMT_LASTBOOL TMT_FLATMENUS
+#define TMT_SIZINGBORDERWIDTH 1201
+#define TMT_SCROLLBARWIDTH 1202
+#define TMT_SCROLLBARHEIGHT 1203
+#define TMT_CAPTIONBARWIDTH 1204
+#define TMT_CAPTIONBARHEIGHT 1205
+#define TMT_SMCAPTIONBARWIDTH 1206
+#define TMT_SMCAPTIONBARHEIGHT 1207
+#define TMT_MENUBARWIDTH 1208
+#define TMT_MENUBARHEIGHT 1209
+#define TMT_PADDEDBORDERWIDTH 1210
+#define TMT_FIRSTSIZE TMT_SIZINGBORDERWIDTH
+#define TMT_LASTSIZE TMT_PADDEDBORDERWIDTH
+#define TMT_MINCOLORDEPTH 1301
+#define TMT_FIRSTINT TMT_MINCOLORDEPTH
+#define TMT_LASTINT TMT_MINCOLORDEPTH
+#define TMT_CSSNAME 1401
+#define TMT_XMLNAME 1402
+#define TMT_LASTUPDATED 1403
+#define TMT_ALIAS 1404
+#define TMT_FIRSTSTRING TMT_CSSNAME
+#define TMT_LASTSTRING TMT_ALIAS
+#define TMT_SCROLLBAR 1601
+#define TMT_BACKGROUND 1602
+#define TMT_ACTIVECAPTION 1603
+#define TMT_INACTIVECAPTION 1604
+#define TMT_MENU 1605
+#define TMT_WINDOW 1606
+#define TMT_WINDOWFRAME 1607
+#define TMT_MENUTEXT 1608
+#define TMT_WINDOWTEXT 1609
+#define TMT_CAPTIONTEXT 1610
+#define TMT_ACTIVEBORDER 1611
+#define TMT_INACTIVEBORDER 1612
+#define TMT_APPWORKSPACE 1613
+#define TMT_HIGHLIGHT 1614
+#define TMT_HIGHLIGHTTEXT 1615
+#define TMT_BTNFACE 1616
+#define TMT_BTNSHADOW 1617
+#define TMT_GRAYTEXT 1618
+#define TMT_BTNTEXT 1619
+#define TMT_INACTIVECAPTIONTEXT 1620
+#define TMT_BTNHIGHLIGHT 1621
+#define TMT_DKSHADOW3D 1622
+#define TMT_LIGHT3D 1623
+#define TMT_INFOTEXT 1624
+#define TMT_INFOBK 1625
+#define TMT_BUTTONALTERNATEFACE 1626
+#define TMT_HOTTRACKING 1627
+#define TMT_GRADIENTACTIVECAPTION 1628
+#define TMT_GRADIENTINACTIVECAPTION 1629
+#define TMT_MENUHILIGHT 1630
+#define TMT_MENUBAR 1631
+#define TMT_FIRSTCOLOR TMT_SCROLLBAR
+#define TMT_LASTCOLOR TMT_MENUBAR
+#define TMT_FROMHUE1 1801
+#define TMT_FROMHUE2 1802
+#define TMT_FROMHUE3 1803
+#define TMT_FROMHUE4 1804
+#define TMT_FROMHUE5 1805
+#define TMT_TOHUE1 1806
+#define TMT_TOHUE2 1807
+#define TMT_TOHUE3 1808
+#define TMT_TOHUE4 1809
+#define TMT_TOHUE5 1810
+#define TMT_FROMCOLOR1 2001
+#define TMT_FROMCOLOR2 2002
+#define TMT_FROMCOLOR3 2003
+#define TMT_FROMCOLOR4 2004
+#define TMT_FROMCOLOR5 2005
+#define TMT_TOCOLOR1 2006
+#define TMT_TOCOLOR2 2007
+#define TMT_TOCOLOR3 2008
+#define TMT_TOCOLOR4 2009
+#define TMT_TOCOLOR5 2010
+#define TMT_TRANSPARENT 2201
+#define TMT_AUTOSIZE 2202
+#define TMT_BORDERONLY 2203
+#define TMT_COMPOSITED 2204
+#define TMT_BGFILL 2205
+#define TMT_GLYPHTRANSPARENT 2206
+#define TMT_GLYPHONLY 2207
+#define TMT_ALWAYSSHOWSIZINGBAR 2208
+#define TMT_MIRRORIMAGE 2209
+#define TMT_UNIFORMSIZING 2210
+#define TMT_INTEGRALSIZING 2211
+#define TMT_SOURCEGROW 2212
+#define TMT_SOURCESHRINK 2213
+#define TMT_DRAWBORDERS 2214
+#define TMT_NOETCHEDEFFECT 2215
+#define TMT_TEXTAPPLYOVERLAY 2216
+#define TMT_TEXTGLOW 2217
+#define TMT_TEXTITALIC 2218
+#define TMT_COMPOSITEDOPAQUE 2219
+#define TMT_LOCALIZEDMIRRORIMAGE 2220
+#define TMT_IMAGECOUNT 2401
+#define TMT_ALPHALEVEL 2402
+#define TMT_BORDERSIZE 2403
+#define TMT_ROUNDCORNERWIDTH 2404
+#define TMT_ROUNDCORNERHEIGHT 2405
+#define TMT_GRADIENTRATIO1 2406
+#define TMT_GRADIENTRATIO2 2407
+#define TMT_GRADIENTRATIO3 2408
+#define TMT_GRADIENTRATIO4 2409
+#define TMT_GRADIENTRATIO5 2410
+#define TMT_PROGRESSCHUNKSIZE 2411
+#define TMT_PROGRESSSPACESIZE 2412
+#define TMT_SATURATION 2413
+#define TMT_TEXTBORDERSIZE 2414
+#define TMT_ALPHATHRESHOLD 2415
+#define TMT_WIDTH 2416
+#define TMT_HEIGHT 2417
+#define TMT_GLYPHINDEX 2418
+#define TMT_TRUESIZESTRETCHMARK 2419
+#define TMT_MINDPI1 2420
+#define TMT_MINDPI2 2421
+#define TMT_MINDPI3 2422
+#define TMT_MINDPI4 2423
+#define TMT_MINDPI5 2424
+#define TMT_TEXTGLOWSIZE 2425
+#define TMT_FRAMESPERSECOND 2426
+#define TMT_PIXELSPERFRAME 2427
+#define TMT_ANIMATIONDELAY 2428
+#define TMT_GLOWINTENSITY 2429
+#define TMT_OPACITY 2430
+#define TMT_COLORIZATIONCOLOR 2431
+#define TMT_COLORIZATIONOPACITY 2432
+#define TMT_GLYPHFONT 2601
+#define TMT_IMAGEFILE 3001
+#define TMT_IMAGEFILE1 3002
+#define TMT_IMAGEFILE2 3003
+#define TMT_IMAGEFILE3 3004
+#define TMT_IMAGEFILE4 3005
+#define TMT_IMAGEFILE5 3006
+#define TMT_GLYPHIMAGEFILE 3008
+#define TMT_TEXT 3201
+#define TMT_CLASSICVALUE 3202
+#define TMT_OFFSET 3401
+#define TMT_TEXTSHADOWOFFSET 3402
+#define TMT_MINSIZE 3403
+#define TMT_MINSIZE1 3404
+#define TMT_MINSIZE2 3405
+#define TMT_MINSIZE3 3406
+#define TMT_MINSIZE4 3407
+#define TMT_MINSIZE5 3408
+#define TMT_NORMALSIZE 3409
+#define TMT_SIZINGMARGINS 3601
+#define TMT_CONTENTMARGINS 3602
+#define TMT_CAPTIONMARGINS 3603
+#define TMT_BORDERCOLOR 3801
+#define TMT_FILLCOLOR 3802
+#define TMT_TEXTCOLOR 3803
+#define TMT_EDGELIGHTCOLOR 3804
+#define TMT_EDGEHIGHLIGHTCOLOR 3805
+#define TMT_EDGESHADOWCOLOR 3806
+#define TMT_EDGEDKSHADOWCOLOR 3807
+#define TMT_EDGEFILLCOLOR 3808
+#define TMT_TRANSPARENTCOLOR 3809
+#define TMT_GRADIENTCOLOR1 3810
+#define TMT_GRADIENTCOLOR2 3811
+#define TMT_GRADIENTCOLOR3 3812
+#define TMT_GRADIENTCOLOR4 3813
+#define TMT_GRADIENTCOLOR5 3814
+#define TMT_SHADOWCOLOR 3815
+#define TMT_GLOWCOLOR 3816
+#define TMT_TEXTBORDERCOLOR 3817
+#define TMT_TEXTSHADOWCOLOR 3818
+#define TMT_GLYPHTEXTCOLOR 3819
+#define TMT_GLYPHTRANSPARENTCOLOR 3820
+#define TMT_FILLCOLORHINT 3821
+#define TMT_BORDERCOLORHINT 3822
+#define TMT_ACCENTCOLORHINT 3823
+#define TMT_TEXTCOLORHINT 3824
+#define TMT_HEADING1TEXTCOLOR 3825
+#define TMT_HEADING2TEXTCOLOR 3826
+#define TMT_BODYTEXTCOLOR 3827
+#define TMT_BGTYPE 4001
+#define TMT_BORDERTYPE 4002
+#define TMT_FILLTYPE 4003
+#define TMT_SIZINGTYPE 4004
+#define TMT_HALIGN 4005
+#define TMT_CONTENTALIGNMENT 4006
+#define TMT_VALIGN 4007
+#define TMT_OFFSETTYPE 4008
+#define TMT_ICONEFFECT 4009
+#define TMT_TEXTSHADOWTYPE 4010
+#define TMT_IMAGELAYOUT 4011
+#define TMT_GLYPHTYPE 4012
+#define TMT_IMAGESELECTTYPE 4013
+#define TMT_GLYPHFONTSIZINGTYPE 4014
+#define TMT_TRUESIZESCALINGTYPE 4015
+#define TMT_USERPICTURE 5001
+#define TMT_DEFAULTPANESIZE 5002
+#define TMT_BLENDCOLOR 5003
+#define TMT_CUSTOMSPLITRECT 5004
+#define TMT_ANIMATIONBUTTONRECT 5005
+#define TMT_ANIMATIONDURATION 5006
+#define TMT_TRANSITIONDURATIONS 6000
+#define TMT_SCALEDBACKGROUND 7001
+#define TMT_ATLASIMAGE 8000
+#define TMT_ATLASINPUTIMAGE 8001
+#define TMT_ATLASRECT 8002
+
+
+//
+// LINK class parts and states
+//
+#define VSCLASS_LINK L"LINK"
+
+enum LINKPARTS {
+ LP_HYPERLINK = 1,
+};
+
+enum HYPERLINKSTATES {
+ HLS_NORMALTEXT = 1,
+ HLS_LINKTEXT = 2,
+};
+
+
+//
+// EMPTYMARKUP class parts and states
+//
+#define VSCLASS_EMPTYMARKUP L"EMPTYMARKUP"
+
+enum EMPTYMARKUPPARTS {
+ EMP_MARKUPTEXT = 1,
+};
+
+enum MARKUPTEXTSTATES {
+ EMT_NORMALTEXT = 1,
+ EMT_LINKTEXT = 2,
+};
+
+
+//
+// STATIC class parts and states
+//
+#define VSCLASS_STATIC L"STATIC"
+
+enum STATICPARTS {
+ STAT_TEXT = 1,
+};
+
+
+//
+// PAGE class parts and states
+//
+#define VSCLASS_PAGE L"PAGE"
+
+enum PAGEPARTS {
+ PGRP_UP = 1,
+ PGRP_DOWN = 2,
+ PGRP_UPHORZ = 3,
+ PGRP_DOWNHORZ = 4,
+};
+
+
+//
+// MONTHCAL class parts and states
+//
+#define VSCLASS_MONTHCAL L"MONTHCAL"
+
+enum MONTHCALPARTS {
+ MC_BACKGROUND = 1,
+ MC_BORDERS = 2,
+ MC_GRIDBACKGROUND = 3,
+ MC_COLHEADERSPLITTER = 4,
+ MC_GRIDCELLBACKGROUND = 5,
+ MC_GRIDCELL = 6,
+ MC_GRIDCELLUPPER = 7,
+ MC_TRAILINGGRIDCELL = 8,
+ MC_TRAILINGGRIDCELLUPPER = 9,
+ MC_NAVNEXT = 10,
+ MC_NAVPREV = 11,
+};
+
+enum GRIDCELLBACKGROUNDSTATES {
+ MCGCB_SELECTED = 1,
+ MCGCB_HOT = 2,
+ MCGCB_SELECTEDHOT = 3,
+ MCGCB_SELECTEDNOTFOCUSED = 4,
+ MCGCB_TODAY = 5,
+};
+
+enum GRIDCELLSTATES {
+ MCGC_HOT = 1,
+ MCGC_HASSTATE = 2,
+ MCGC_HASSTATEHOT = 3,
+ MCGC_TODAY = 4,
+};
+
+enum GRIDCELLUPPERSTATES {
+ MCGCU_HOT = 1,
+ MCGCU_HASSTATE = 2,
+ MCGCU_HASSTATEHOT = 3,
+};
+
+enum TRAILINGGRIDCELLSTATES {
+ MCTGC_HOT = 1,
+ MCTGC_HASSTATE = 2,
+ MCTGC_HASSTATEHOT = 3,
+ MCTGC_TODAY = 4,
+};
+
+enum TRAILINGGRIDCELLUPPERSTATES {
+ MCTGCU_HOT = 1,
+ MCTGCU_HASSTATE = 2,
+ MCTGCU_HASSTATEHOT = 3,
+};
+
+enum NAVNEXTSTATES {
+ MCNN_NORMAL = 1,
+ MCNN_HOT = 2,
+ MCNN_PRESSED = 3,
+ MCNN_DISABLED = 4,
+};
+
+enum NAVPREVSTATES {
+ MCNP_NORMAL = 1,
+ MCNP_HOT = 2,
+ MCNP_PRESSED = 3,
+ MCNP_DISABLED = 4,
+};
+
+
+//
+// CLOCK class parts and states
+//
+#define VSCLASS_CLOCK L"CLOCK"
+
+enum CLOCKPARTS {
+ CLP_TIME = 1,
+};
+
+enum CLOCKSTATES {
+ CLS_NORMAL = 1,
+ CLS_HOT = 2,
+ CLS_PRESSED = 3,
+};
+
+
+//
+// TRAYNOTIFY class parts and states
+//
+#define VSCLASS_TRAYNOTIFY L"TRAYNOTIFY"
+
+enum TRAYNOTIFYPARTS {
+ TNP_BACKGROUND = 1,
+ TNP_ANIMBACKGROUND = 2,
+};
+
+
+//
+// TASKBAR class parts and states
+//
+#define VSCLASS_TASKBAR L"TASKBAR"
+
+enum TASKBARPARTS {
+ TBP_BACKGROUNDBOTTOM = 1,
+ TBP_BACKGROUNDRIGHT = 2,
+ TBP_BACKGROUNDTOP = 3,
+ TBP_BACKGROUNDLEFT = 4,
+ TBP_SIZINGBARBOTTOM = 5,
+ TBP_SIZINGBARRIGHT = 6,
+ TBP_SIZINGBARTOP = 7,
+ TBP_SIZINGBARLEFT = 8,
+};
+
+
+//
+// TASKBAND class parts and states
+//
+#define VSCLASS_TASKBAND L"TASKBAND"
+
+enum TASKBANDPARTS {
+ TDP_GROUPCOUNT = 1,
+ TDP_FLASHBUTTON = 2,
+ TDP_FLASHBUTTONGROUPMENU = 3,
+};
+
+
+//
+// STARTPANEL class parts and states
+//
+#define VSCLASS_STARTPANEL L"STARTPANEL"
+
+enum STARTPANELPARTS {
+ SPP_USERPANE = 1,
+ SPP_MOREPROGRAMS = 2,
+ SPP_MOREPROGRAMSARROW = 3,
+ SPP_PROGLIST = 4,
+ SPP_PROGLISTSEPARATOR = 5,
+ SPP_PLACESLIST = 6,
+ SPP_PLACESLISTSEPARATOR = 7,
+ SPP_LOGOFF = 8,
+ SPP_LOGOFFBUTTONS = 9,
+ SPP_USERPICTURE = 10,
+ SPP_PREVIEW = 11,
+ SPP_MOREPROGRAMSTAB = 12,
+ SPP_NSCHOST = 13,
+ SPP_SOFTWAREEXPLORER = 14,
+ SPP_OPENBOX = 15,
+ SPP_SEARCHVIEW = 16,
+ SPP_MOREPROGRAMSARROWBACK = 17,
+ SPP_TOPMATCH = 18,
+ SPP_LOGOFFSPLITBUTTONDROPDOWN = 19,
+};
+
+enum MOREPROGRAMSTABSTATES {
+ SPMPT_NORMAL = 1,
+ SPMPT_HOT = 2,
+ SPMPT_SELECTED = 3,
+ SPMPT_DISABLED = 4,
+ SPMPT_FOCUSED = 5,
+};
+
+enum SOFTWAREEXPLORERSTATES {
+ SPSE_NORMAL = 1,
+ SPSE_HOT = 2,
+ SPSE_SELECTED = 3,
+ SPSE_DISABLED = 4,
+ SPSE_FOCUSED = 5,
+};
+
+enum OPENBOXSTATES {
+ SPOB_NORMAL = 1,
+ SPOB_HOT = 2,
+ SPOB_SELECTED = 3,
+ SPOB_DISABLED = 4,
+ SPOB_FOCUSED = 5,
+};
+
+enum MOREPROGRAMSARROWSTATES {
+ SPS_NORMAL = 1,
+ SPS_HOT = 2,
+ SPS_PRESSED = 3,
+};
+
+enum MOREPROGRAMSARROWBACKSTATES {
+ SPSB_NORMAL = 1,
+ SPSB_HOT = 2,
+ SPSB_PRESSED = 3,
+};
+
+enum LOGOFFBUTTONSSTATES {
+ SPLS_NORMAL = 1,
+ SPLS_HOT = 2,
+ SPLS_PRESSED = 3,
+};
+
+
+//
+// MENUBAND class parts and states
+//
+#define VSCLASS_MENUBAND L"MENUBAND"
+
+enum MENUBANDPARTS {
+ MDP_NEWAPPBUTTON = 1,
+ MDP_SEPERATOR = 2,
+};
+
+enum MENUBANDSTATES {
+ MDS_NORMAL = 1,
+ MDS_HOT = 2,
+ MDS_PRESSED = 3,
+ MDS_DISABLED = 4,
+ MDS_CHECKED = 5,
+ MDS_HOTCHECKED = 6,
+};
+
+
+#endif //__VSSYM32_H__
+
diff --git a/plugins/Clist_ng/SRC/CLCButton.cpp b/plugins/Clist_ng/SRC/CLCButton.cpp new file mode 100644 index 0000000000..e470b58e19 --- /dev/null +++ b/plugins/Clist_ng/SRC/CLCButton.cpp @@ -0,0 +1,705 @@ +/*
+ * 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: CLCButton.cpp 135 2010-10-06 13:13:51Z silvercircle $
+ *
+ * skinable button control for clist NG. Based on the original MButtonCtrl
+ * for Miranda by Robert Rainwater
+ *
+ */
+
+#include <commonheaders.h>
+
+static LRESULT CALLBACK TSButtonWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+struct MButtonCtrl {
+ HWND hwnd;
+ int stateId; // button state
+ int focus; // has focus (1 or 0)
+ HFONT hFont; // font
+ HICON arrow; // uses down arrow
+ int defbutton; // default button
+ HICON hIcon, hIconPrivate;
+ HBITMAP hBitmap;
+ int pushBtn;
+ int pbState;
+ HANDLE hThemeButton;
+ HANDLE hThemeToolbar;
+ BOOL bThemed;
+ DWORD bSkinned;
+ char cHot;
+ int flatBtn;
+ wchar_t szText[128];
+ SIZE sLabel;
+ HIMAGELIST hIml;
+ int iIcon;
+ BOOL bSendOnDown;
+ TButtonItem *buttonItem;
+ LONG lastGlyphMetrics[4];
+};
+
+static HWND hwndToolTips = NULL;
+
+int LoadCLCButtonModule(void)
+{
+ WNDCLASSEXW wc = {0};
+
+ wc.cbSize = sizeof(wc);
+ wc.lpszClassName = L"CLCButtonClass";
+ wc.lpfnWndProc = TSButtonWndProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.cbWndExtra = sizeof(MButtonCtrl *);
+ wc.hbrBackground = 0;
+ wc.style = CS_GLOBALCLASS;
+ RegisterClassEx(&wc);
+ return 0;
+}
+
+// Used for our own cheap TrackMouseEvent
+#define BUTTON_POLLID 100
+#define BUTTON_POLLDELAY 50
+
+#define MGPROC(x) GetProcAddress(themeAPIHandle,x)
+
+static void DestroyTheme(MButtonCtrl *ctl)
+{
+ if(Api::pfnCloseThemeData) {
+ if(ctl->hThemeButton) {
+ Api::pfnCloseThemeData(ctl->hThemeButton);
+ ctl->hThemeButton = 0;
+ }
+ if(ctl->hThemeToolbar) {
+ Api::pfnCloseThemeData(ctl->hThemeToolbar);
+ ctl->hThemeToolbar = 0;
+ }
+ ctl->bThemed = 0;
+ }
+}
+
+static void LoadTheme(MButtonCtrl *ctl)
+{
+ DestroyTheme(ctl);
+ if(IS_THEMED) {
+ ctl->hThemeButton = Api::pfnOpenThemeData(ctl->hwnd, L"BUTTON");
+ ctl->hThemeToolbar = Api::pfnOpenThemeData(ctl->hwnd, L"TOOLBAR");
+ ctl->bThemed = TRUE;
+ }
+}
+
+static int TBStateConvert2Flat(int state)
+{
+ switch(state) {
+ case PBS_NORMAL:
+ return TS_NORMAL;
+ case PBS_HOT:
+ return TS_HOT;
+ case PBS_PRESSED:
+ return TS_PRESSED;
+ case PBS_DISABLED:
+ return TS_DISABLED;
+ case PBS_DEFAULTED:
+ return TS_NORMAL;
+ }
+ return TS_NORMAL;
+}
+
+static void PaintWorker(MButtonCtrl *ctl, HDC hdcPaint)
+{
+ if(hdcPaint) {
+ HDC hdcMem;
+ RECT rcClient, rcBp;
+ HFONT hOldFont = 0;
+ int xOffset = 0;
+ HANDLE hbp = 0;
+ GetClientRect(ctl->hwnd, &rcClient);
+#ifndef _USE_D2D
+ rcBp = rcClient;
+ INIT_PAINT(hdcPaint, rcBp, hdcMem);
+#else
+ hdcMem = cfg::dat.hdcBg;
+ MapWindowPoints(ctl->hwnd, pcli->hwndContactList, reinterpret_cast<POINT *>(&rcClient), 2);
+#endif
+
+ hOldFont = reinterpret_cast<HFONT>(SelectObject(hdcMem, ctl->hFont));
+ // If its a push button, check to see if it should stay pressed
+ if(ctl->pushBtn && ctl->pbState)
+ ctl->stateId = PBS_PRESSED;
+
+ // Draw the flat button
+ if(ctl->flatBtn) {
+ if(ctl->hThemeToolbar && ctl->bThemed) {
+ RECT rc = rcClient;
+ int state = IsWindowEnabled(ctl->hwnd) ? (ctl->stateId == PBS_NORMAL && ctl->defbutton ? PBS_DEFAULTED : ctl->stateId) : PBS_DISABLED;
+ Gfx::drawBGFromSurface(ctl->hwnd, rc, hdcMem);
+ if(Api::pfnIsThemeBackgroundPartiallyTransparent(ctl->hThemeToolbar, TP_BUTTON, TBStateConvert2Flat(state))) {
+ Api::pfnDrawThemeParentBackground(ctl->hwnd, hdcMem, &rc);
+ }
+ Api::pfnDrawThemeBackground(ctl->hThemeToolbar, hdcMem, TP_BUTTON, TBStateConvert2Flat(state), &rc, &rc);
+ } else {
+ HBRUSH hbr;
+ RECT rc = rcClient;
+
+ if(ctl->buttonItem) {
+ RECT rcParent;
+ POINT pt;
+ TImageItem *imgItem = ctl->stateId == PBS_HOT ? ctl->buttonItem->imgHover : (ctl->stateId == PBS_PRESSED ? ctl->buttonItem->imgPressed : ctl->buttonItem->imgNormal);
+ LONG *glyphMetrics = ctl->stateId == PBS_HOT ? ctl->buttonItem->hoverGlyphMetrics : (ctl->stateId == PBS_PRESSED ? ctl->buttonItem->pressedGlyphMetrics : ctl->buttonItem->normalGlyphMetrics);
+#ifndef _USE_D2D
+ GetWindowRect(ctl->hwnd, &rcParent);
+ pt.x = rcParent.left;
+ pt.y = rcParent.top;
+ ScreenToClient(pcli->hwndContactList, &pt);
+ Gfx::drawBGFromSurface(ctl->hwnd, rc, hdcMem);
+#endif
+ if(imgItem)
+ Gfx::renderSkinItem(hdcMem, &rc, imgItem);
+ if(Skin::glyphItem) {
+ Api::pfnAlphaBlend(hdcMem, (rc.right - glyphMetrics[2]) / 2, (rc.bottom - glyphMetrics[3]) / 2,
+ glyphMetrics[2], glyphMetrics[3], Skin::glyphItem->hdc,
+ glyphMetrics[0], glyphMetrics[1], glyphMetrics[2],
+ glyphMetrics[3], Skin::glyphItem->bf);
+ }
+ } else if(ctl->bSkinned) { // skinned
+ RECT rcParent;
+ TStatusItem *item;
+ int item_id;
+
+ GetWindowRect(ctl->hwnd, &rcParent);
+
+ Gfx::drawBGFromSurface(ctl->hwnd, rc, hdcMem);
+ item_id = ctl->stateId == PBS_HOT ? ID_EXTBKBUTTONSMOUSEOVER : (ctl->stateId == PBS_PRESSED ? ID_EXTBKBUTTONSPRESSED : ID_EXTBKBUTTONSNPRESSED);
+ item = &Skin::statusItems[item_id];
+ Gfx::setTextColor(item->TEXTCOLOR);
+ if(item->IGNORED)
+ FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_3DFACE));
+ else {
+ rc.top += item->MARGIN_TOP;
+ rc.bottom -= item->MARGIN_BOTTOM;
+ rc.left += item->MARGIN_LEFT;
+ rc.right -= item->MARGIN_RIGHT;
+ Gfx::renderSkinItem(hdcMem, &rc, item->imageItem);
+ }
+ } else {
+ if(ctl->stateId == PBS_PRESSED || ctl->stateId == PBS_HOT)
+ hbr = GetSysColorBrush(COLOR_3DFACE);
+ else {
+ HDC dc;
+ HWND hwndParent;
+
+ hwndParent = GetParent(ctl->hwnd);
+ dc = GetDC(hwndParent);
+ hbr = (HBRUSH) SendMessage(hwndParent, WM_CTLCOLORDLG, (WPARAM) dc, (LPARAM) hwndParent);
+ ReleaseDC(hwndParent, dc);
+ }
+ if(hbr) {
+ FillRect(hdcMem, &rc, hbr);
+ DeleteObject(hbr);
+ }
+ }
+ if(!ctl->bSkinned && ctl->buttonItem == 0) {
+ if(ctl->stateId == PBS_HOT || ctl->focus) {
+ if(ctl->pbState)
+ DrawEdge(hdcMem, &rc, EDGE_ETCHED, BF_RECT | BF_SOFT);
+ else
+ DrawEdge(hdcMem, &rc, BDR_RAISEDOUTER, BF_RECT | BF_SOFT);
+ } else if(ctl->stateId == PBS_PRESSED)
+ DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT | BF_SOFT);
+ }
+ }
+ } else {
+ // Draw background/border
+ if(ctl->hThemeButton && ctl->bThemed) {
+ int state = IsWindowEnabled(ctl->hwnd) ? (ctl->stateId == PBS_NORMAL && ctl->defbutton ? PBS_DEFAULTED : ctl->stateId) : PBS_DISABLED;
+ POINT pt;
+ RECT rcParent;
+
+ GetWindowRect(ctl->hwnd, &rcParent);
+ pt.x = rcParent.left;
+ pt.y = rcParent.top;
+ ScreenToClient(pcli->hwndContactList, &pt);
+ BitBlt(hdcMem, 0, 0, rcClient.right, rcClient.bottom, cfg::dat.hdcBg, pt.x, pt.y, SRCCOPY);
+
+ if(Api::pfnIsThemeBackgroundPartiallyTransparent(ctl->hThemeButton, BP_PUSHBUTTON, state)) {
+ Api::pfnDrawThemeParentBackground(ctl->hwnd, hdcMem, &rcClient);
+ }
+ Api::pfnDrawThemeBackground(ctl->hThemeButton, hdcMem, BP_PUSHBUTTON, state, &rcClient, &rcClient);
+ } else {
+ UINT uState = DFCS_BUTTONPUSH | ((ctl->stateId == PBS_HOT) ? DFCS_HOT : 0) | ((ctl->stateId == PBS_PRESSED) ? DFCS_PUSHED : 0);
+ if(ctl->defbutton && ctl->stateId == PBS_NORMAL)
+ uState |= DLGC_DEFPUSHBUTTON;
+ DrawFrameControl(hdcMem, &rcClient, DFC_BUTTON, uState);
+ }
+
+ // Draw focus rectangle if button has focus
+ if(ctl->focus) {
+ RECT focusRect = rcClient;
+ InflateRect(&focusRect, -3, -3);
+ DrawFocusRect(hdcMem, &focusRect);
+ }
+ }
+
+ // If we have an icon or a bitmap, ignore text and only draw the image on the button
+ if(ctl->hIcon || ctl->hIconPrivate || ctl->iIcon) {
+ int ix = (rcClient.right - rcClient.left) / 2 - (CXSMICON / 2);
+ int iy = (rcClient.bottom - rcClient.top) / 2 - (CXSMICON / 2);
+ HICON hIconNew = ctl->hIconPrivate != 0 ? ctl->hIconPrivate : ctl->hIcon;
+ if(lstrlen(ctl->szText) == 0) {
+ if(ctl->iIcon)
+ ImageList_DrawEx(ctl->hIml, ctl->iIcon, hdcMem, ix, iy, CXSMICON, CYSMICON, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ else
+ DrawState(hdcMem, NULL, NULL, (LPARAM) hIconNew, 0, ix, iy, CXSMICON, CYSMICON, IsWindowEnabled(ctl->hwnd) ? DST_ICON | DSS_NORMAL : DST_ICON | DSS_DISABLED);
+ ctl->sLabel.cx = ctl->sLabel.cy = 0;
+ } else {
+ GetTextExtentPoint32(hdcMem, ctl->szText, lstrlen(ctl->szText), &ctl->sLabel);
+
+ if(CXSMICON + ctl->sLabel.cx + 8 > rcClient.right - rcClient.left)
+ ctl->sLabel.cx = (rcClient.right - rcClient.left) - CXSMICON - 8;
+ else
+ ctl->sLabel.cx += 4;
+
+ ix = (rcClient.right - rcClient.left) / 2 - ((CXSMICON + ctl->sLabel.cx) / 2);
+ if(ctl->iIcon)
+ ImageList_DrawEx(ctl->hIml, ctl->iIcon, hdcMem, ix, iy, CXSMICON, CYSMICON, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ else
+ DrawState(hdcMem, NULL, NULL, (LPARAM) hIconNew, 0, ix, iy, CXSMICON, CYSMICON, IsWindowEnabled(ctl->hwnd) ? DST_ICON | DSS_NORMAL : DST_ICON | DSS_DISABLED);
+ xOffset = ix + CXSMICON + 4;
+ }
+ } else if(ctl->hBitmap) {
+ BITMAP bminfo;
+ int ix, iy;
+
+ GetObject(ctl->hBitmap, sizeof(bminfo), &bminfo);
+ ix = (rcClient.right - rcClient.left) / 2 - (bminfo.bmWidth / 2);
+ iy = (rcClient.bottom - rcClient.top) / 2 - (bminfo.bmHeight / 2);
+ if(ctl->stateId == PBS_PRESSED) {
+ ix++;
+ iy++;
+ }
+ DrawState(hdcMem, NULL, NULL, (LPARAM) ctl->hBitmap, 0, ix, iy, bminfo.bmWidth, bminfo.bmHeight, IsWindowEnabled(ctl->hwnd) ? DST_BITMAP : DST_BITMAP | DSS_DISABLED);
+ }
+ if(GetWindowTextLength(ctl->hwnd)) {
+ // Draw the text and optinally the arrow
+ RECT rcText;
+
+ CopyRect(&rcText, &rcClient);
+ SetBkMode(hdcMem, TRANSPARENT);
+ if(!ctl->bSkinned)
+ Gfx::setTextColor(IsWindowEnabled(ctl->hwnd) || !ctl->hThemeButton ? GetSysColor(COLOR_BTNTEXT) : GetSysColor(COLOR_GRAYTEXT));
+ if(ctl->arrow) {
+ DrawState(hdcMem, NULL, NULL, (LPARAM) ctl->arrow, 0, rcClient.right - rcClient.left - 5 - CXSMICON + (!ctl->hThemeButton && ctl->stateId == PBS_PRESSED ? 1 : 0), (rcClient.bottom - rcClient.top) / 2 - CYSMICON / 2 + (!ctl->hThemeButton && ctl->stateId == PBS_PRESSED ? 1 : 0), CXSMICON, CYSMICON, IsWindowEnabled(ctl->hwnd) ? DST_ICON : DST_ICON | DSS_DISABLED);
+ rcText.left += (4 + CXSMICON);
+ }
+ if(xOffset)
+ rcText.left += (4 + CXSMICON);
+ Gfx::renderText(hdcMem, ctl->hThemeButton, ctl->szText, &rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE, 0);
+ }
+ if(hOldFont)
+ SelectObject(hdcMem, hOldFont);
+#ifndef _USE_D2D
+ FINALIZE_PAINT(hbp, &rcBp, 0);
+#endif
+ }
+}
+
+static LRESULT CALLBACK TSButtonWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ MButtonCtrl *bct = (MButtonCtrl *) GetWindowLongPtr(hwndDlg, 0);
+ switch(msg) {
+ case WM_NCCREATE: {
+ SetWindowLong(hwndDlg, GWL_STYLE, GetWindowLong(hwndDlg, GWL_STYLE) | BS_OWNERDRAW);
+ bct = reinterpret_cast<MButtonCtrl *>(malloc(sizeof(MButtonCtrl)));
+ if(bct == NULL)
+ return FALSE;
+ bct->hwnd = hwndDlg;
+ bct->stateId = PBS_NORMAL;
+ bct->focus = 0;
+ bct->hFont = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
+ bct->arrow = NULL;
+ bct->defbutton = 0;
+ bct->hIcon = bct->hIconPrivate = 0;
+ bct->iIcon = 0;
+ bct->hIml = 0;
+ bct->hBitmap = NULL;
+ bct->pushBtn = 0;
+ bct->pbState = 0;
+ bct->hThemeButton = NULL;
+ bct->hThemeToolbar = NULL;
+ bct->cHot = 0;
+ bct->flatBtn = 0;
+ bct->bThemed = FALSE;
+ bct->bSkinned = bct->bSendOnDown = 0;
+ bct->buttonItem = NULL;
+ LoadTheme(bct);
+ SetWindowLongPtr(hwndDlg, 0, (LONG_PTR) bct);
+ if(((CREATESTRUCTA *) lParam)->lpszName)
+ SetWindowText(hwndDlg, ((CREATESTRUCT *) lParam)->lpszName);
+ return TRUE;
+ }
+
+ case WM_DESTROY: {
+ if(bct) {
+ if(hwndToolTips) {
+ TOOLINFO ti;
+
+ ZeroMemory(&ti, sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.uFlags = TTF_IDISHWND;
+ ti.hwnd = bct->hwnd;
+ ti.uId = (UINT_PTR) bct->hwnd;
+ if(SendMessage(hwndToolTips, TTM_GETTOOLINFO, 0, (LPARAM) &ti)) {
+ SendMessage(hwndToolTips, TTM_DELTOOL, 0, (LPARAM) &ti);
+ }
+ if(SendMessage(hwndToolTips, TTM_GETTOOLCOUNT, 0, (LPARAM) &ti) == 0) {
+ DestroyWindow(hwndToolTips);
+ hwndToolTips = NULL;
+ }
+ }
+ if(bct->hIconPrivate)
+ DestroyIcon(bct->hIconPrivate);
+ DestroyTheme(bct);
+ free(bct);
+ }
+ SetWindowLongPtr(hwndDlg, 0, 0);
+ break; // DONT! fall thru
+ }
+
+ case WM_SETTEXT: {
+ bct->cHot = 0;
+ if((char*) lParam) {
+ char *tmp = (char *) lParam;
+ while(*tmp) {
+ if(*tmp == '&' && *(tmp + 1)) {
+ bct->cHot = tolower(*(tmp + 1));
+ break;
+ }
+ tmp++;
+ }
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ lstrcpyn(bct->szText, (wchar_t *)lParam, 127);
+ bct->szText[127] = 0;
+ }
+ break;
+ }
+
+ case WM_SYSKEYUP:
+ if(bct->stateId != PBS_DISABLED && bct->cHot && bct->cHot == tolower((int) wParam)) {
+ if(bct->pushBtn) {
+ if(bct->pbState)
+ bct->pbState = 0;
+ else
+ bct->pbState = 1;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ }
+ if(!bct->bSendOnDown)
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndDlg), BN_CLICKED), (LPARAM) hwndDlg);
+ return 0;
+ }
+ break;
+
+ case WM_THEMECHANGED: {
+ if(bct->bThemed)
+ LoadTheme(bct);
+ InvalidateRect(bct->hwnd, NULL, TRUE); // repaint it
+ break;
+ }
+
+ case WM_SETFONT: {
+ bct->hFont = (HFONT) wParam; // maybe we should redraw?
+ break;
+ }
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hdcPaint;
+
+ hdcPaint = BeginPaint(hwndDlg, &ps);
+ if(hdcPaint) {
+ PaintWorker(bct, hdcPaint);
+ EndPaint(hwndDlg, &ps);
+ }
+ break;
+ }
+
+ case BM_GETIMAGE:
+ if(wParam == IMAGE_ICON)
+ return (LRESULT)(bct->hIconPrivate ? bct->hIconPrivate : bct->hIcon);
+ break;
+
+ case BM_SETIMAGE:
+ if(!lParam)
+ break;
+ bct->hIml = 0;
+ bct->iIcon = 0;
+ if(wParam == IMAGE_ICON) {
+ ICONINFO ii = {0};
+ BITMAP bm = {0};
+
+ if(bct->hIconPrivate) {
+ DestroyIcon(bct->hIconPrivate);
+ bct->hIconPrivate = 0;
+ }
+
+ GetIconInfo((HICON) lParam, &ii);
+ GetObject(ii.hbmColor, sizeof(bm), &bm);
+ if(bm.bmWidth > CXSMICON || bm.bmHeight > CYSMICON) {
+ HIMAGELIST hImageList;
+ hImageList = ImageList_Create(CXSMICON, CYSMICON, ILC_COLOR32 | ILC_MASK, 1, 0);
+ ImageList_AddIcon(hImageList, (HICON) lParam);
+ bct->hIconPrivate = ImageList_GetIcon(hImageList, 0, ILD_NORMAL);
+ ImageList_RemoveAll(hImageList);
+ ImageList_Destroy(hImageList);
+ bct->hIcon = 0;
+ } else {
+ bct->hIcon = (HICON) lParam;
+ bct->hIconPrivate = 0;
+ }
+
+ DeleteObject(ii.hbmMask);
+ DeleteObject(ii.hbmColor);
+ bct->hBitmap = NULL;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ } else if(wParam == IMAGE_BITMAP) {
+ bct->hBitmap = (HBITMAP) lParam;
+ if(bct->hIconPrivate)
+ DestroyIcon(bct->hIconPrivate);
+ bct->hIcon = bct->hIconPrivate = NULL;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ }
+ break;
+
+ case BM_SETPRIVATEICON:
+ bct->hIml = 0;
+ bct->iIcon = 0;
+ {
+ if(bct->hIconPrivate)
+ DestroyIcon(bct->hIconPrivate);
+ bct->hIconPrivate = DuplicateIcon(g_hInst, (HICON) lParam);
+ bct->hIcon = 0;
+ break;
+ }
+
+ case BM_SETIMLICON: {
+ if(bct->hIconPrivate)
+ DestroyIcon(bct->hIconPrivate);
+ bct->hIml = (HIMAGELIST) wParam;
+ bct->iIcon = (int) lParam;
+ bct->hIcon = bct->hIconPrivate = 0;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+ }
+
+ case BM_SETSKINNED:
+ bct->bSkinned = (DWORD)lParam;
+ bct->bThemed = bct->bSkinned ? FALSE : bct->bThemed;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case BM_SETBTNITEM:
+ bct->buttonItem = (TButtonItem *)lParam;
+ break;
+
+ case BM_SETASMENUACTION:
+ bct->bSendOnDown = wParam ? TRUE : FALSE;
+ return 0;
+
+ case BM_SETCHECK:
+ if(!bct->pushBtn)
+ break;
+ if(wParam == BST_CHECKED) {
+ bct->pbState = 1;
+ bct->stateId = PBS_PRESSED;
+ } else if(wParam == BST_UNCHECKED) {
+ bct->pbState = 0;
+ bct->stateId = PBS_NORMAL;
+ }
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case BM_GETCHECK:
+ if(bct->pushBtn) {
+ return bct->pbState ? BST_CHECKED : BST_UNCHECKED;
+ }
+ return 0;
+
+ case BUTTONSETARROW:
+ // turn arrow on/off
+ if(wParam) {
+ if(!bct->arrow)
+ bct->arrow = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_MINIMIZE), IMAGE_ICON, CXSMICON, CYSMICON, 0);
+ } else {
+ if(bct->arrow) {
+ DestroyIcon(bct->arrow);
+ bct->arrow = NULL;
+ }
+ }
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case BUTTONSETDEFAULT:
+ bct->defbutton = wParam ? 1 : 0;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case BUTTONSETASPUSHBTN:
+ bct->pushBtn = 1;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case BUTTONSETASFLATBTN:
+ bct->flatBtn = lParam == 0 ? 1 : 0;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case BUTTONSETASFLATBTN + 10:
+ bct->bThemed = lParam ? TRUE : FALSE;
+ bct->bSkinned = bct->bThemed ? 0 : bct->bSkinned;
+ break;
+
+ case BUTTONADDTOOLTIP: {
+ TOOLINFO ti;
+
+ if(!(char*) wParam)
+ break;
+ if(!hwndToolTips) {
+ hwndToolTips = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, _T(""), WS_POPUP, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
+ SetWindowPos(hwndToolTips, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ }
+ ZeroMemory(&ti, sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.uFlags = TTF_IDISHWND;
+ ti.hwnd = bct->hwnd;
+ ti.uId = (UINT_PTR) bct->hwnd;
+ if(SendMessage(hwndToolTips, TTM_GETTOOLINFO, 0, (LPARAM) &ti)) {
+ SendMessage(hwndToolTips, TTM_DELTOOL, 0, (LPARAM) &ti);
+ }
+ ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
+ ti.uId = (UINT_PTR) bct->hwnd;
+ ti.lpszText = (wchar_t *) wParam;
+ SendMessage(hwndToolTips, TTM_ADDTOOL, 0, (LPARAM) &ti);
+ break;
+ }
+ case WM_SETFOCUS:
+ // set keybord focus and redraw
+ bct->focus = 1;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case WM_KILLFOCUS:
+ // kill focus and redraw
+ bct->focus = 0;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+
+ case WM_ENABLE: {
+ bct->stateId = wParam ? PBS_NORMAL : PBS_DISABLED;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ break;
+ }
+
+ case WM_MOUSELEAVE: {
+ if(bct->stateId != PBS_DISABLED) {
+ // don't change states if disabled
+ bct->stateId = PBS_NORMAL;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ }
+ break;
+ }
+
+ case WM_LBUTTONDOWN: {
+ if(bct->stateId != PBS_DISABLED && bct->stateId != PBS_PRESSED) {
+ bct->stateId = PBS_PRESSED;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ if(bct->bSendOnDown) {
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndDlg), BN_CLICKED), (LPARAM) hwndDlg);
+ bct->stateId = PBS_NORMAL;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ }
+ }
+ break;
+ }
+
+ case WM_LBUTTONUP: {
+ if(bct->pushBtn) {
+ if(bct->pbState)
+ bct->pbState = 0;
+ else
+ bct->pbState = 1;
+ }
+ if(bct->stateId != PBS_DISABLED) {
+ // don't change states if disabled
+ if(msg == WM_LBUTTONUP)
+ bct->stateId = PBS_HOT;
+ else
+ bct->stateId = PBS_NORMAL;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ }
+ if(!bct->bSendOnDown)
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndDlg), BN_CLICKED), (LPARAM) hwndDlg);
+ break;
+ }
+
+ case WM_MOUSEMOVE:
+ if(bct->stateId == PBS_NORMAL) {
+ bct->stateId = PBS_HOT;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ }
+ // Call timer, used to start cheesy TrackMouseEvent faker
+ SetTimer(hwndDlg, BUTTON_POLLID, BUTTON_POLLDELAY, NULL);
+ break;
+
+ case WM_NCHITTEST: {
+ LRESULT lr = SendMessage(GetParent(hwndDlg), WM_NCHITTEST, wParam, lParam);
+ if(lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT
+ || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT)
+ return HTTRANSPARENT;
+ break;
+ }
+ case WM_TIMER: {
+ if(wParam == BUTTON_POLLID) {
+ RECT rc;
+ POINT pt;
+ GetWindowRect(hwndDlg, &rc);
+ GetCursorPos(&pt);
+ if(!PtInRect(&rc, pt)) {
+ // mouse must be gone, trigger mouse leave
+ PostMessage(hwndDlg, WM_MOUSELEAVE, 0, 0L);
+ KillTimer(hwndDlg, BUTTON_POLLID);
+ }
+ }
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ return 1;
+ }
+ return DefWindowProc(hwndDlg, msg, wParam, lParam);
+}
diff --git a/plugins/Clist_ng/SRC/Docking.cpp b/plugins/Clist_ng/SRC/Docking.cpp new file mode 100644 index 0000000000..a26bf0089f --- /dev/null +++ b/plugins/Clist_ng/SRC/Docking.cpp @@ -0,0 +1,292 @@ +/*
+ * 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: Docking.cpp 102 2010-08-31 02:48:29Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+
+#define WM_DOCKCALLBACK (WM_USER+121)
+#define WM_CREATEDOCKED (WM_USER+122)
+#define EDGESENSITIVITY 3
+
+#define DOCKED_NONE 0
+#define DOCKED_LEFT 1
+#define DOCKED_RIGHT 2
+static int docked;
+
+extern RECT cluiPos;
+
+static void Docking_GetMonitorRectFromPoint(POINT pt, RECT *rc)
+{
+ MONITORINFO monitorInfo;
+ HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); // always returns a valid value
+ monitorInfo.cbSize = sizeof(MONITORINFO);
+
+ if (GetMonitorInfo( hMonitor, &monitorInfo)) {
+ CopyMemory(rc, &monitorInfo.rcMonitor, sizeof(RECT));
+ return;
+ }
+
+ // "generic" win95/NT support, also serves as failsafe
+ rc->left = 0;
+ rc->top = 0;
+ rc->bottom = GetSystemMetrics(SM_CYSCREEN);
+ rc->right = GetSystemMetrics(SM_CXSCREEN);
+}
+
+static void Docking_GetMonitorRectFromWindow(HWND hWnd, RECT *rc)
+{
+ POINT ptWindow;
+ GetWindowRect(hWnd, rc);
+ ptWindow.x = rc->left;
+ ptWindow.y = rc->top;
+ Docking_GetMonitorRectFromPoint(ptWindow, rc);
+}
+
+static void Docking_AdjustPosition(HWND hwnd, RECT *rcDisplay, RECT *rc)
+{
+ APPBARDATA abd;
+
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = hwnd;
+ abd.uEdge = docked == DOCKED_LEFT ? ABE_LEFT : ABE_RIGHT;
+ abd.rc = *rc;
+ abd.rc.top = rcDisplay->top;
+ abd.rc.bottom = rcDisplay->bottom;
+ if (docked == DOCKED_LEFT) {
+ abd.rc.right = rcDisplay->left + (abd.rc.right - abd.rc.left);
+ abd.rc.left = rcDisplay->left;
+ } else {
+ abd.rc.left = rcDisplay->right - (abd.rc.right - abd.rc.left);
+ abd.rc.right = rcDisplay->right;
+ }
+ SHAppBarMessage(ABM_SETPOS, &abd);
+ *rc = abd.rc;
+}
+
+int Docking_IsDocked(WPARAM wParam, LPARAM lParam)
+{
+ return docked;
+}
+
+int Docking_ProcessWindowMessage(WPARAM wParam, LPARAM lParam)
+{
+ APPBARDATA abd;
+ static int draggingTitle;
+ MSG *msg = (MSG *) wParam;
+
+ if (msg->message == WM_DESTROY)
+ cfg::writeByte("CList", "Docked", (BYTE) docked);
+ if (!docked && msg->message != WM_CREATE && msg->message != WM_MOVING && msg->message != WM_CREATEDOCKED && msg->message != WM_MOVE)
+ return 0;
+ switch (msg->message) {
+ case WM_CREATE:
+ //if(GetSystemMetrics(SM_CMONITORS)>1) return 0;
+ if (cfg::getByte("CList", "Docked", 0))
+ PostMessage(msg->hwnd, WM_CREATEDOCKED, 0, 0);
+ draggingTitle = 0;
+ return 0;
+ case WM_CREATEDOCKED:
+ //we need to post a message just after creation to let main message function do some work
+ docked = (int) (char) cfg::getByte("CList", "Docked", 0);
+ if (IsWindowVisible(msg->hwnd) && !IsIconic(msg->hwnd)) {
+ RECT rc, rcMonitor;
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW, &abd);
+ GetWindowRect(msg->hwnd, &rc);
+ Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
+ Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc);
+ MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
+ }
+ break;
+ case WM_ACTIVATE:
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_ACTIVATE, &abd);
+ return 0;
+ case WM_WINDOWPOSCHANGED:
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
+ return 0;
+ case WM_MOVING:
+ {
+ RECT rcMonitor;
+ POINT ptCursor;
+
+ // stop early
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ return 0;
+
+ // GetMessagePos() is no good, position is always unsigned
+ GetCursorPos(&ptCursor);
+ Docking_GetMonitorRectFromPoint(ptCursor, &rcMonitor);
+
+ if ((ptCursor.x < rcMonitor.left + EDGESENSITIVITY) || (ptCursor.x >= rcMonitor.right - EDGESENSITIVITY)) {
+ if(!(GetWindowLong(msg->hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) {
+ SendMessage(msg->hwnd, CLUIINTM_REDRAW, 0, 0);
+ MessageBox(0, TranslateT("The clist cannot be docked when using the default title bar and border. Use a toolwindow or borderless style instead."),
+ TranslateT("Clist docking"), MB_OK);
+ return 0;
+ }
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW, &abd);
+ if (ptCursor.x < rcMonitor.left + EDGESENSITIVITY)
+ docked = DOCKED_LEFT;
+ else
+ docked = DOCKED_RIGHT;
+ SendMessage(msg->hwnd, WM_LBUTTONUP, 0, MAKELPARAM(ptCursor.x, ptCursor.y));
+ GetWindowRect(msg->hwnd, (LPRECT) msg->lParam);
+ Docking_AdjustPosition(msg->hwnd, (LPRECT) &rcMonitor, (LPRECT) msg->lParam);
+ PostMessage(msg->hwnd, CLUIINTM_REDRAW, 0, 0);
+ return TRUE;
+ }
+ return 0;
+ }
+ case WM_MOVE:
+ {
+ if (docked) {
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
+ GetWindowRect(msg->hwnd, &rc);
+ Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc);
+ MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
+ return 1;
+ }
+ return 0;
+ }
+ case WM_SIZING:
+ {
+ RECT rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
+ Docking_AdjustPosition(msg->hwnd, &rcMonitor, (LPRECT) msg->lParam);
+ *((LRESULT *) lParam) = TRUE;
+ return TRUE;
+ }
+ case WM_SHOWWINDOW:
+ if (msg->lParam)
+ return 0;
+ if ((msg->wParam && docked < 0) || (!msg->wParam && docked > 0))
+ docked = -docked;
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ if (msg->wParam) {
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor);
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW, &abd);
+ GetWindowRect(msg->hwnd, &rc);
+ Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc);
+ MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
+ } else {
+ SHAppBarMessage(ABM_REMOVE, &abd);
+ }
+ return 0;
+ case WM_NCHITTEST:
+ {
+ LONG result;
+ result = DefWindowProc(msg->hwnd, WM_NCHITTEST, msg->wParam, msg->lParam);
+ if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT || result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT) {
+ *((LRESULT *) lParam) = HTCLIENT; return TRUE;
+ }
+ if (docked == DOCKED_LEFT && result == HTLEFT) {
+ *((LRESULT *) lParam) = HTCLIENT; return TRUE;
+ }
+ if (docked == DOCKED_RIGHT && result == HTRIGHT) {
+ *((LRESULT *) lParam) = HTCLIENT; return TRUE;
+ }
+ return 0;
+ }
+ case WM_SYSCOMMAND:
+ if ((msg->wParam & 0xFFF0) != SC_MOVE)
+ return 0;
+ SetActiveWindow(msg->hwnd);
+ SetCapture(msg->hwnd);
+ draggingTitle = 1;
+ *((LRESULT *) lParam) = 0;
+ return TRUE;
+ case WM_MOUSEMOVE:
+ if (!draggingTitle)
+ return 0; {
+ RECT rc;
+ POINT pt;
+ GetClientRect(msg->hwnd, &rc);
+ if (((docked == DOCKED_LEFT || docked == -DOCKED_LEFT) && (short) LOWORD(msg->lParam) > rc.right) || ((docked == DOCKED_RIGHT || docked == -DOCKED_RIGHT) && (short) LOWORD(msg->lParam) < 0)) {
+ ReleaseCapture();
+ draggingTitle = 0;
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_REMOVE, &abd);
+ docked = 0;
+ GetCursorPos(&pt);
+ PostMessage(msg->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pt.x, pt.y));
+ SetWindowPos(msg->hwnd, 0, pt.x - rc.right / 2, pt.y - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYSMCAPTION) / 2,
+ CLUI::cluiPos.right, CLUI::cluiPos.bottom, SWP_NOZORDER);
+ }
+ return 1;
+ }
+ case WM_LBUTTONUP:
+ if (draggingTitle) {
+ ReleaseCapture();
+ draggingTitle = 0;
+ }
+ return 0;
+ case WM_DOCKCALLBACK:
+ switch (msg->wParam) {
+ case ABN_WINDOWARRANGE:
+ ShowWindow(msg->hwnd, msg->lParam ? SW_HIDE : SW_SHOW);
+ break;
+ }
+ return TRUE;
+ case WM_DESTROY:
+ if (docked > 0) {
+ ZeroMemory(&abd, sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_REMOVE, &abd);
+ }
+ return 0;
+ }
+ return 0;
+}
diff --git a/plugins/Clist_ng/SRC/clc.cpp b/plugins/Clist_ng/SRC/clc.cpp new file mode 100644 index 0000000000..1ec6eb5bb8 --- /dev/null +++ b/plugins/Clist_ng/SRC/clc.cpp @@ -0,0 +1,934 @@ +/*
+ * 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_nicer plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: clc.cpp 138 2010-11-01 10:51:15Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include <resource.h>
+#include <m_userinfo.h>
+#include "../coolsb/coolscroll.h"
+
+/*
+ * static function pointers for Clist interface
+ */
+LRESULT (CALLBACK* CLC::saveContactListControlWndProc) (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) = 0;
+
+bool CLC::fHottrackDone = false, CLC::fInPaint = false;
+int CLC::iHottrackItem = 0;
+HANDLE CLC::hSettingsChanged = 0, CLC::hDBEvent = 0;
+HIMAGELIST CLC::hClistImages = 0;
+unsigned CLC::uNrAvatars = 0;
+
+TDisplayProfile CLC::dsp_default = {0};
+
+int CLC::_status2onlineness[] = {
+ 100, // ID_STATUS_ONLINE
+ 30, // ID_STATUS_AWAY
+ 40, // ID_STATUS_DND
+ 10, // ID_STATUS_NA
+ 60, // ID_STATUS_OCCUPIED
+ 110, // ID_STATUS_FREECHAT
+ 5, // ID_STATUS_INVISIBLE
+ 50, // ID_STATUS_ONTHEPHONE
+ 20 // ID_STATUS_OUTTOLUNCH
+};
+
+extern HANDLE hExtraImageApplying;
+extern FRAMEWND *wndFrameCLC;
+
+extern int during_sizing;
+
+HANDLE hSoundHook = 0, hIcoLibChanged = 0, hSvc_GetContactStatusMsg = 0;
+
+HMENU BuildGroupPopupMenu(struct ClcGroup* group)
+{
+ return Menu_BuildSubGroupMenu(group);
+}
+
+int AvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ pcli->pfnClcBroadcast(INTM_AVATARCHANGED, wParam, lParam);
+ return 0;
+}
+
+int __forceinline __strcmp(const char * src, const char * dst)
+{
+ int ret = 0 ;
+
+ while (!(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
+ ++src, ++dst;
+ return(ret);
+}
+
+static int ClcEventAdded(WPARAM hContact, LPARAM lParam)
+{
+ DWORD new_freq = 0;
+ cfg::dat.t_now = time(NULL);
+
+ if (hContact && lParam) {
+ DBEVENTINFO dbei = { sizeof(dbei) };
+ db_event_get((MEVENT)lParam, &dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) {
+ DWORD firstTime = cfg::getDword(hContact, "CList", "mf_firstEvent", 0);
+ DWORD count = cfg::getDword(hContact, "CList", "mf_count", 0);
+ count++;
+ new_freq = count ? (dbei.timestamp - firstTime) / count : 0x7fffffff;
+ cfg::writeDword(hContact, "CList", "mf_freq", new_freq);
+ cfg::writeDword(hContact, "CList", "mf_count", count);
+ int iEntry = cfg::getCache(hContact, NULL);
+ if (iEntry >= 0 && iEntry < cfg::nextCacheEntry) {
+ cfg::eCache[iEntry].dwLastMsgTime = dbei.timestamp;
+ if (new_freq)
+ cfg::eCache[iEntry].msgFrequency = new_freq;
+ pcli->pfnClcBroadcast(INTM_FORCESORT, 0, 1);
+ }
+ }
+ }
+ return 0;
+}
+
+int ClcSoundHook(WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+int CLC::SettingChanged(WPARAM hContact, LPARAM lParam)
+{
+ char *szProto = NULL;
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam;
+
+ if (hContact) {
+ if (!__strcmp(cws->szModule, "CList")) {
+ if (!__strcmp(cws->szSetting, "StatusMsg"))
+ SendMessage(pcli->hwndContactTree, INTM_STATUSMSGCHANGED, hContact, lParam);
+ }
+ else if (!__strcmp(cws->szModule, "UserInfo")) {
+ if (!__strcmp(cws->szSetting, "Timezone") || !__strcmp(cws->szSetting, "TzName"))
+ ReloadExtraInfo(hContact);
+ }
+ else if (hContact != 0 && (szProto = GetContactProto(hContact)) != NULL) {
+ if (!__strcmp(cws->szModule, "Protocol") && !__strcmp(cws->szSetting, "p")) {
+ char *szProto_s;
+ pcli->pfnClcBroadcast(INTM_PROTOCHANGED, hContact, lParam);
+ if (cws->value.type == DBVT_DELETED)
+ szProto_s = NULL;
+ else
+ szProto_s = cws->value.pszVal;
+ pcli->pfnChangeContactIcon(hContact, IconFromStatusMode(szProto_s, szProto_s == NULL ? ID_STATUS_OFFLINE : cfg::getWord(hContact, szProto_s, "Status", ID_STATUS_OFFLINE), hContact, NULL), 0);
+ }
+ // something is being written to a protocol module
+ if (!__strcmp(szProto, cws->szModule)) {
+ // was a unique setting key written?
+ pcli->pfnInvalidateDisplayNameCacheEntry(hContact);
+ if (!__strcmp(cws->szSetting, "Status")) {
+ if (!cfg::getByte(hContact, "CList", "Hidden", 0)) {
+ if (cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT)) {
+ // User's state is changing, and we are hideOffline-ing
+ if (cws->value.wVal == ID_STATUS_OFFLINE) {
+ pcli->pfnChangeContactIcon(hContact, IconFromStatusMode(cws->szModule, cws->value.wVal, hContact, NULL), 0);
+ CallService(MS_CLUI_CONTACTDELETED, hContact, 0);
+ return 0;
+ }
+ pcli->pfnChangeContactIcon(hContact, IconFromStatusMode(cws->szModule, cws->value.wVal, hContact, NULL), 1);
+ }
+ pcli->pfnChangeContactIcon(hContact, IconFromStatusMode(cws->szModule, cws->value.wVal, hContact, NULL), 0);
+ }
+ SendMessage(pcli->hwndContactTree, INTM_STATUSCHANGED, hContact, lParam);
+ return 0;
+ } else if (strstr("YMsg|StatusDescr|XStatusMsg", cws->szSetting))
+ SendMessage(pcli->hwndContactTree, INTM_STATUSMSGCHANGED, hContact, lParam);
+ else if (strstr(cws->szSetting, "XStatus"))
+ SendMessage(pcli->hwndContactTree, INTM_XSTATUSCHANGED, hContact, lParam);
+ else if (!__strcmp(cws->szSetting, "Timezone") || !__strcmp(cws->szSetting, "TzName"))
+ ReloadExtraInfo(hContact);
+ else if (!__strcmp(cws->szSetting, "MirVer"))
+ NotifyEventHooks(hExtraImageApplying, hContact, 0);
+
+ if (cfg::dat.bMetaAvail && !__strcmp(szProto, cfg::dat.szMetaName)) {
+ if ((lstrlenA(cws->szSetting) > 6 && !strncmp(cws->szSetting, "Status", 6)) || strstr("Default,ForceSend,Nick", cws->szSetting))
+ pcli->pfnClcBroadcast(INTM_NAMEORDERCHANGED, hContact, lParam);
+ }
+ }
+ if (cfg::dat.bMetaAvail && cfg::dat.bMetaEnabled && !__strcmp(cws->szModule, cfg::dat.szMetaName) && !__strcmp(cws->szSetting, "IsSubcontact"))
+ pcli->pfnClcBroadcast(INTM_HIDDENCHANGED, hContact, lParam);
+ }
+ } else if (hContact == 0 && !__strcmp(cws->szModule, cfg::dat.szMetaName)) {
+ BYTE bMetaEnabled = cfg::getByte(cfg::dat.szMetaName, "Enabled", 1);
+ if (bMetaEnabled != (BYTE)cfg::dat.bMetaEnabled) {
+ cfg::dat.bMetaEnabled = bMetaEnabled;
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ }
+ } else if (hContact == 0 && !__strcmp(cws->szModule, "Skin")) {
+ if (!__strcmp(cws->szSetting, "UseSound")) {
+ if (hSoundHook) {
+ UnhookEvent(hSoundHook);
+ hSoundHook = 0;
+ }
+ cfg::dat.soundsOff = cfg::getByte(cws->szModule, cws->szSetting, 0) ? 0 : 1;
+ if (cfg::dat.soundsOff && hSoundHook == 0)
+ hSoundHook = HookEvent(ME_SKIN_PLAYINGSOUND, ClcSoundHook);
+ CheckDlgButton(pcli->hwndContactList, IDC_TBSOUND, cfg::dat.soundsOff ? BST_UNCHECKED : BST_CHECKED);
+ CLUI::setButtonStates(pcli->hwndContactList);
+ }
+ } else if (szProto == NULL && hContact == 0) {
+ if (!__strcmp(cws->szSetting, "XStatusId"))
+ CluiProtocolStatusChanged(0, cws->szModule);
+ return 0;
+ }
+ return 0;
+}
+
+static int ClcModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+int CLC::preshutdown(WPARAM wParam, LPARAM lParam)
+{
+ SFL_Destroy();
+ cfg::shutDown = TRUE;
+ if (hSvc_GetContactStatusMsg)
+ DestroyServiceFunction(hSvc_GetContactStatusMsg);
+ UnhookEvent(hSettingsChanged);
+ UnhookEvent(hDBEvent);
+ if (hIcoLibChanged)
+ UnhookEvent(hIcoLibChanged);
+ return 0;
+}
+
+int CLC::shutDown(WPARAM wParam, LPARAM lParam)
+{
+ if (cfg::dat.hIconInvisible)
+ DestroyIcon(cfg::dat.hIconInvisible);
+ if (cfg::dat.hIconVisible)
+ DestroyIcon(cfg::dat.hIconVisible);
+ if (cfg::dat.hIconChatactive)
+ DestroyIcon(cfg::dat.hIconChatactive);
+
+ DeleteObject(cfg::dat.hBrushCLCBk);
+ DeleteObject(cfg::dat.hBrushCLCGroupsBk);
+ DeleteObject(cfg::dat.hBrushAvatarBorder);
+ DestroyMenu(cfg::dat.hMenuNotify);
+ ClearIcons(1);
+ SFL_UnregisterWindowClass();
+ if (cfg::eCache) {
+ int i;
+
+ for (i = 0; i < cfg::nextCacheEntry; i++) {
+ if (cfg::eCache[i].statusMsg)
+ free(cfg::eCache[i].statusMsg);
+ if (cfg::eCache[i].status_item) {
+ TStatusItem *item = cfg::eCache[i].status_item;
+ int j;
+
+ free(cfg::eCache[i].status_item);
+ cfg::eCache[i].status_item = 0;
+ for (j = i; j < cfg::nextCacheEntry; j++) { // avoid duplicate free()'ing status item pointers (there are references from sub to master contacts, so compare the pointers...
+ if (cfg::eCache[j].status_item == item)
+ cfg::eCache[j].status_item = 0;
+ }
+ }
+ }
+ free(cfg::eCache);
+ cfg::eCache = NULL;
+ }
+ Skin::Unload();
+ DeleteCriticalSection(&cfg::cachecs);
+ return 0;
+}
+
+int CLC::loadModule(void)
+{
+ CLC::hClistImages = (HIMAGELIST) CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, ClcModulesLoaded);
+ hSettingsChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, CLC::SettingChanged);
+ hDBEvent = HookEvent(ME_DB_EVENT_ADDED, ClcEventAdded);
+ HookEvent(ME_OPT_INITIALISE, ClcOptInit);
+ HookEvent(ME_SYSTEM_SHUTDOWN, preshutdown);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// clist_nicer+ control window procedure
+
+LRESULT CALLBACK CLC::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ClcData *dat;
+ BOOL frameHasTitlebar = FALSE;
+
+ if (wndFrameCLC)
+ frameHasTitlebar = wndFrameCLC->TitleBar.ShowTitleBar;
+
+ dat = (struct ClcData *) GetWindowLongPtr(hwnd, 0);
+ if (msg >= CLM_FIRST && msg < CLM_LAST)
+ return ProcessExternalMessages(hwnd, dat, msg, wParam, lParam);
+
+ switch (msg) {
+ case WM_NCCREATE:
+ dat = (struct ClcData *)mir_alloc(sizeof(struct ClcData));
+ memset(dat, 0, sizeof(struct ClcData));
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat);
+ dat->ph = new CLCPaintHelper(hwnd, dat, 0, 0, 0, 0, 0);
+ RowHeight::Init(dat);
+ break;
+ case WM_CREATE:
+ dat->forceScroll = 0;
+ dat->lastRepaint = 0;
+ dat->needsResort = false;
+ dat->himlExtraColumns = CLUI::hExtraImages;
+ dat->hwndParent = GetParent(hwnd);
+ dat->lastSort = GetTickCount();
+ dat->ph = new CLCPaintHelper(hwnd, dat, 0, 0, 0, 0, 0);
+ {
+ CREATESTRUCT *cs = (CREATESTRUCT *)lParam;
+ if (cs->lpCreateParams == (LPVOID)0xff00ff00) {
+ dat->bisEmbedded = FALSE;
+ dat->bHideSubcontacts = TRUE;
+ cfg::clcdat = dat;
+ if (cfg::dat.bShowLocalTime)
+ SetTimer(hwnd, TIMERID_REFRESH, 65000, NULL);
+ } else
+ dat->bisEmbedded = TRUE;
+ }
+ break;
+ case WM_SIZE:
+ pcli->pfnEndRename(hwnd, dat, 1);
+ KillTimer(hwnd, TIMERID_INFOTIP);
+ KillTimer(hwnd, TIMERID_RENAME);
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+LBL_Def:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_NCCALCSIZE: {
+ return FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam, frameHasTitlebar);
+ }
+
+ /*
+ * scroll bar handling
+ */
+ case WM_NCPAINT:
+ return FrameNCPaint(hwnd, DefWindowProc, wParam, lParam, frameHasTitlebar);
+ case INTM_SCROLLBARCHANGED:
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_CONTACTLIST) {
+ if (!cfg::getByte("CLC", "NoVScrollBar", 0)) {
+ CoolSB_SetupScrollBar(hwnd);
+ ShowScrollBar(hwnd, SB_VERT, FALSE);
+ }
+ else
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+ }
+ break;
+ case INTM_GROUPCHANGED: {
+ ClcContact *contact;
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ BYTE flags = 0;
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ memset(iExtraImage, 0xFF, sizeof(iExtraImage));
+ else {
+ CopyMemory(iExtraImage, contact->iExtraImage, sizeof(iExtraImage));
+ flags = contact->flags;
+ }
+ pcli->pfnDeleteItemFromTree(hwnd, (MCONTACT)wParam);
+ if (GetWindowLong(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !CLVM_GetContactHiddenStatus(wParam, NULL, dat)) {
+ NMCLISTCONTROL nm;
+ pcli->pfnAddContactToTree(hwnd, dat, wParam, 1, 1);
+ if (findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) {
+ CopyMemory(contact->iExtraImage, iExtraImage, sizeof(iExtraImage));
+ if (flags & CONTACTF_CHECKED)
+ contact->flags |= CONTACTF_CHECKED;
+ }
+ nm.hdr.code = CLN_CONTACTMOVED;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = (HANDLE) wParam;
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) &nm);
+ }
+ dat->needsResort = true;
+ PostMessage(hwnd, INTM_SORTCLC, 0, 1);
+ goto LBL_Def;
+ }
+
+ case INTM_ICONCHANGED: {
+ struct ClcContact *contact = NULL;
+ struct ClcGroup *group = NULL;
+ int recalcScrollBar = 0, shouldShow;
+ WORD status = ID_STATUS_OFFLINE;
+ char *szProto;
+ int contactRemoved = 0;
+ DWORD hSelItem = 0;
+ struct ClcContact *selcontact = NULL;
+
+ szProto = GetContactProto(wParam);
+ if (szProto == NULL)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = cfg::getWord(wParam, szProto, "Status", ID_STATUS_OFFLINE);
+
+ shouldShow = (GetWindowLong(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !CLVM_GetContactHiddenStatus(wParam, szProto, dat)) && ((cfg::dat.bFilterEffective ? TRUE : !pcli->pfnIsHiddenMode(dat, status)) || CallService(MS_CLIST_GETCONTACTICON, wParam, 0) != lParam);// XXX CLVM changed - this means an offline msg is flashing, so the contact should be shown
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL)) {
+ if (shouldShow && CallService(MS_DB_CONTACT_IS, wParam, 0)) {
+ if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1)
+ hSelItem = (MCONTACT)pcli->pfnContactToHItem(selcontact);
+ pcli->pfnAddContactToTree(hwnd, dat, wParam, 0, 0);
+ recalcScrollBar = 1;
+ findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL);
+ if (contact) {
+ contact->iImage = (WORD) lParam;
+ pcli->pfnNotifyNewContact(hwnd, wParam);
+ }
+ }
+ } else {
+ //item in list already
+ DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+ if (contact->iImage == (WORD) lParam)
+ break;
+ if (!shouldShow && !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline || cfg::dat.bFilterEffective)) { // CLVM changed
+ if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1)
+ hSelItem = (MCONTACT)pcli->pfnContactToHItem(selcontact);
+ pcli->pfnRemoveItemFromGroup(hwnd, group, contact, 0);
+ contactRemoved = TRUE;
+ recalcScrollBar = 1;
+ } else {
+ contact->iImage = (WORD) lParam;
+ if (!pcli->pfnIsHiddenMode(dat, status))
+ contact->flags |= CONTACTF_ONLINE;
+ else
+ contact->flags &= ~CONTACTF_ONLINE;
+ }
+ }
+ if (hSelItem) {
+ struct ClcGroup *selgroup;
+ if (pcli->pfnFindItem(hwnd, dat, hSelItem, &selcontact, &selgroup, NULL))
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, List_IndexOf((SortedList*) & selgroup->cl, selcontact));
+ else
+ dat->selection = -1;
+ }
+ dat->needsResort = true;
+ PostMessage(hwnd, INTM_SORTCLC, 0, recalcScrollBar);
+ PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contactRemoved ? 0 : wParam));
+ if (recalcScrollBar)
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+ goto LBL_Def;
+ }
+ case INTM_METACHANGED: {
+ struct ClcContact *contact;
+ if (!pcli->pfnFindItem(hwnd, dat, wParam, &contact, NULL, NULL))
+ break;
+ if (contact->bIsMeta && cfg::dat.bMetaAvail) {
+ contact->hSubContact = (MCONTACT) CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM) contact->hContact, 0);
+ contact->metaProto = GetContactProto(contact->hSubContact);
+ contact->iImage = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) contact->hSubContact, 0);
+ if (contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) {
+ int subIndex = cfg::getCache(contact->hSubContact, contact->metaProto);
+ cfg::eCache[contact->extraCacheEntry].proto_status_item = GetProtocolStatusItem(contact->metaProto);
+ if (subIndex >= 0 && subIndex <= cfg::nextCacheEntry) {
+ cfg::eCache[contact->extraCacheEntry].status_item = cfg::eCache[subIndex].status_item;
+ CopyMemory(cfg::eCache[contact->extraCacheEntry].iExtraImage, cfg::eCache[subIndex].iExtraImage, MAXEXTRACOLUMNS);
+ cfg::eCache[contact->extraCacheEntry].iExtraValid = cfg::eCache[subIndex].iExtraValid;
+ }
+ }
+ }
+ SendMessage(hwnd, INTM_NAMEORDERCHANGED, wParam, lParam);
+ goto LBL_Def;
+ }
+ case INTM_METACHANGEDEVENT: {
+ struct ClcContact *contact;
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ break;
+ if (lParam == 0)
+ pcli->pfnInitAutoRebuild(hwnd);
+ goto LBL_Def;
+ }
+ case INTM_NAMECHANGED: {
+ struct ClcContact *contact;
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ break;
+ lstrcpyn(contact->szText, pcli->pfnGetContactDisplayName(wParam, 0), safe_sizeof(contact->szText));
+ RTL_DetectAndSet(contact, 0);
+ dat->needsResort = true;
+ PostMessage(hwnd, INTM_SORTCLC, 0, 0);
+ goto LBL_Def;
+ }
+
+ case INTM_AVATARCHANGED: {
+ struct avatarCacheEntry *cEntry = (struct avatarCacheEntry *)lParam;
+ struct ClcContact *contact = NULL;
+
+ if (wParam == 0) {
+ cfg::dat.bForceRefetchOnPaint = TRUE;
+ RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
+ cfg::dat.bForceRefetchOnPaint = FALSE;
+ goto LBL_Def;
+ }
+
+ if (!findItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL))
+ return 0;
+ contact->ace = cEntry;
+ if (cEntry == NULL)
+ contact->cFlags &= ~ECF_AVATAR;
+ else {
+ if (cfg::dat.dwFlags & CLUI_FRAME_AVATARS)
+ contact->cFlags = (contact->dwDFlags & ECF_HIDEAVATAR ? contact->cFlags & ~ECF_AVATAR : contact->cFlags | ECF_AVATAR);
+ else
+ contact->cFlags = (contact->dwDFlags & ECF_FORCEAVATAR ? contact->cFlags | ECF_AVATAR : contact->cFlags & ~ECF_AVATAR);
+ }
+ PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)contact->hContact);
+
+ goto LBL_Def;
+ }
+ case INTM_STATUSMSGCHANGED: {
+ struct ClcContact *contact = NULL;
+ int index = -1;
+ char *szProto = NULL;
+
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ index = cfg::getCache(wParam, NULL);
+ else {
+ index = contact->extraCacheEntry;
+ szProto = contact->proto;
+ }
+ GetCachedStatusMsg(index, szProto);
+ PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contact ? contact->hContact : 0));
+ goto LBL_Def;
+ }
+ case INTM_STATUSCHANGED: {
+ struct ClcContact *contact = NULL;
+ WORD wStatus;
+
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ break;
+
+ wStatus = cfg::getWord(wParam, contact->proto, "Status", ID_STATUS_OFFLINE);
+ if (cfg::dat.bNoOfflineAvatars && wStatus != ID_STATUS_OFFLINE && contact->wStatus == ID_STATUS_OFFLINE) {
+ contact->wStatus = wStatus;
+ if (contact->ace == 0)
+ LoadAvatarForContact(contact);
+ }
+ contact->wStatus = wStatus;
+ goto LBL_Def;
+ }
+ case INTM_PROTOCHANGED: {
+ struct ClcContact *contact = NULL;
+
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ break;
+ contact->proto = GetContactProto(wParam);
+ CallService(MS_CLIST_INVALIDATEDISPLAYNAME, wParam, 0);
+ lstrcpyn(contact->szText, pcli->pfnGetContactDisplayName(wParam, 0), safe_sizeof(contact->szText));
+ RTL_DetectAndSet(contact, 0);
+ dat->needsResort = TRUE;
+ PostMessage(hwnd, INTM_SORTCLC, 0, 0);
+ goto LBL_Def;
+ }
+
+ case INTM_INVALIDATE:
+ if (!dat->bNeedPaint) {
+ KillTimer(hwnd, TIMERID_PAINT);
+ SetTimer(hwnd, TIMERID_PAINT, 100, NULL);
+ dat->bNeedPaint = TRUE;
+ }
+
+ if (lParam && !dat->bisEmbedded) {
+ struct ClcContact *contact = NULL;
+
+ if (findItem(hwnd, dat, (HANDLE)lParam, &contact, NULL, 0)) {
+ if (contact && contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry && cfg::eCache[contact->extraCacheEntry].floater)
+ FLT_Update(dat, contact);
+ }
+ }
+ goto LBL_Def;
+
+ case INTM_INVALIDATECONTACT: {
+ struct ClcContact *contact = 0;
+ struct ClcGroup *group = 0;
+ int iItem;
+
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL))
+ break;
+
+ if (contact == 0 || group == 0)
+ break;
+
+ iItem = pcli->pfnGetRowsPriorTo(&dat->list, group, List_IndexOf((SortedList*) & group->cl, contact));
+ pcli->pfnInvalidateItem(hwnd, dat, iItem);
+ goto LBL_Def;
+ }
+ case INTM_FORCESORT:
+ dat->needsResort = TRUE;
+ return SendMessage(hwnd, INTM_SORTCLC, wParam, lParam);
+ case INTM_SORTCLC:
+ if (dat->needsResort) {
+ pcli->pfnSortCLC(hwnd, dat, TRUE);
+ dat->needsResort = FALSE;
+ }
+ if (lParam)
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+ goto LBL_Def;
+
+ case INTM_IDLECHANGED: {
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam;
+ char *szProto;
+ struct ClcContact *contact = NULL;
+
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ break;
+ szProto = (char*)cws->szModule;
+ if (szProto == NULL)
+ break;
+ contact->flags &= ~CONTACTF_IDLE;
+ if (cfg::getDword(wParam, szProto, "IdleTS", 0)) {
+ contact->flags |= CONTACTF_IDLE;
+ }
+ PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)contact->hContact);
+ goto LBL_Def;
+ }
+ case INTM_XSTATUSCHANGED: {
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam;
+ char *szProto;
+ struct ClcContact *contact = NULL;
+ int index;
+
+ szProto = (char *)cws->szModule;
+
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) {
+ index = cfg::getCache(wParam, szProto);
+ if (!dat->bisEmbedded && cfg::dat.bMetaAvail && szProto) { // may be a subcontact, forward the xstatus
+ if (cfg::getByte(wParam, cfg::dat.szMetaName, "IsSubcontact", 0)) {
+ MCONTACT hMasterContact = cfg::getDword(wParam, cfg::dat.szMetaName, "Handle", 0);
+ if (hMasterContact && hMasterContact != wParam) // avoid recursive call of settings handler
+ cfg::writeByte(hMasterContact, cfg::dat.szMetaName, "XStatusId", (BYTE)cfg::getByte(wParam, szProto, "XStatusId", 0));
+ break;
+ }
+ }
+ } else {
+ contact->xStatus = cfg::getByte(wParam, szProto, "XStatusId", 0);
+ index = contact->extraCacheEntry;
+ }
+ if (szProto == NULL)
+ break;
+ GetCachedStatusMsg(index, szProto);
+ PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contact ? contact->hContact : 0));
+ goto LBL_Def;
+ }
+ case WM_PAINT: {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ ULONGLONG ulTick;
+ hdc = BeginPaint(hwnd, &ps);
+ if (IsWindowVisible(hwnd) && !CLUI::fInSizing && !cfg::shutDown && dat->ph) {
+ ulTick = Api::pfnGetTickCount64();
+ if(ulTick - dat->lastRepaint > 2000) {
+ countAvatars(dat);
+ dat->lastRepaint = ulTick;
+ }
+ Paint(hwnd, dat, hdc, &ps.rcPaint);
+ dat->bNeedPaint = FALSE;
+ }
+ EndPaint(hwnd, &ps);
+ if (dat->selection != dat->oldSelection && !dat->bisEmbedded && CLUI::buttonItems != NULL) {
+ CLUI::setFrameButtonStates(0);
+ dat->oldSelection = dat->selection;
+ }
+ goto LBL_Def;
+ }
+
+ case WM_MOUSEWHEEL:
+ dat->forceScroll = TRUE;
+ break;
+
+ case WM_TIMER:
+ if (wParam == TIMERID_PAINT) {
+ KillTimer(hwnd, TIMERID_PAINT);
+ InvalidateRect(hwnd, NULL, FALSE);
+ goto LBL_Def;
+ }
+
+ if (wParam == TIMERID_REFRESH) {
+ InvalidateRect(hwnd, NULL, FALSE);
+ goto LBL_Def;
+ }
+ break;
+
+ case WM_LBUTTONDBLCLK: {
+ struct ClcContact *contact;
+ DWORD hitFlags;
+ ReleaseCapture();
+ dat->iHotTrack = -1;
+ pcli->pfnHideInfoTip(hwnd, dat);
+ KillTimer(hwnd, TIMERID_RENAME);
+ KillTimer(hwnd, TIMERID_INFOTIP);
+ dat->szQuickSearch[0] = 0;
+ dat->selection = HitTest(hwnd, dat, (short) LOWORD(lParam), (short) HIWORD(lParam), &contact, NULL, &hitFlags);
+ if (hitFlags & CLCHT_ONITEMEXTRAEX && hwnd == pcli->hwndContactTree && contact != 0) {
+ int column = hitFlags >> 24;
+ if (column-- > 0) {
+ if (contact->type == CLCIT_CONTACT) {
+ CONTACTINFO ci;
+ ZeroMemory(&ci,sizeof(CONTACTINFO));
+ ci.cbSize = sizeof(CONTACTINFO);
+ ci.hContact = contact->hContact;
+ ci.szProto = contact->proto;
+
+ if (column == 0) {
+ ci.dwFlag = CNF_EMAIL;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) {
+ char buf[4096];
+ mir_snprintf(buf, sizeof(buf), "mailto:%s", (LPCSTR)ci.pszVal);
+ mir_free(ci.pszVal);
+ ShellExecuteA(hwnd, "open", buf, NULL, NULL, SW_SHOW);
+ }
+ return TRUE;
+ }
+ if (column == 1) {
+ ci.dwFlag = CNF_HOMEPAGE;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) {
+ ShellExecuteA(hwnd, "open", (LPCSTR)ci.pszVal, NULL, NULL, SW_SHOW);
+ mir_free(ci.pszVal);
+ }
+ return TRUE;
+ }
+ }
+ }
+ }
+ InvalidateRect(hwnd, NULL, FALSE);
+ if (dat->selection != -1)
+ pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0);
+ if (hitFlags & CLCHT_ONAVATAR && cfg::dat.bDblClkAvatars) {
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)contact->hContact, 0);
+ return TRUE;
+ }
+ if (hitFlags & (CLCHT_ONITEMICON | CLCHT_ONITEMLABEL | CLCHT_ONITEMSPACE)) {
+ UpdateWindow(hwnd);
+ pcli->pfnDoSelectionDefaultAction(hwnd, dat);
+ }
+ return TRUE;
+ }
+ case WM_CONTEXTMENU: {
+ struct ClcContact *contact;
+ HMENU hMenu = NULL;
+ POINT pt;
+ DWORD hitFlags;
+
+ pcli->pfnEndRename(hwnd, dat, 1);
+ pcli->pfnHideInfoTip(hwnd, dat);
+ KillTimer(hwnd, TIMERID_RENAME);
+ KillTimer(hwnd, TIMERID_INFOTIP);
+ if (GetFocus() != hwnd)
+ SetFocus(hwnd);
+ dat->iHotTrack = -1;
+ dat->szQuickSearch[0] = 0;
+ pt.x = (short) LOWORD(lParam);
+ pt.y = (short) HIWORD(lParam);
+ if (pt.x == -1 && pt.y == -1) {
+ dat->selection = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, NULL);
+ if (dat->selection != -1)
+ pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0);
+ pt.x = dat->iconXSpace + 15;
+ pt.y = RowHeight::getItemTopY(dat, dat->selection) - dat->yScroll + (int)(dat->row_heights[dat->selection] * .7);
+ hitFlags = dat->selection == -1 ? CLCHT_NOWHERE : CLCHT_ONITEMLABEL;
+ } else {
+ ScreenToClient(hwnd, &pt);
+ dat->selection = HitTest(hwnd, dat, pt.x, pt.y, &contact, NULL, &hitFlags);
+ }
+ InvalidateRect(hwnd, NULL, FALSE);
+ if (dat->selection != -1)
+ pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0);
+ UpdateWindow(hwnd);
+
+ if (dat->selection != -1 && hitFlags & (CLCHT_ONITEMICON | CLCHT_ONITEMCHECK | CLCHT_ONITEMLABEL)) {
+ if (contact->type == CLCIT_GROUP) {
+ HMENU hMenu = Menu_BuildSubGroupMenu(contact->group);
+ ClientToScreen(hwnd, &pt);
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, pcli->hwndContactList, NULL);
+ CheckMenuItem(hMenu, POPUP_GROUPHIDEOFFLINE, contact->group->hideOffline ? MF_CHECKED : MF_UNCHECKED);
+ DestroyMenu(hMenu);
+ return 0;
+ }
+ else if (contact->type == CLCIT_CONTACT)
+ hMenu = Menu_BuildContactMenu(contact->hContact);
+ } else {
+ //call parent for new group/hide offline menu
+ PostMessage(GetParent(hwnd), WM_CONTEXTMENU, wParam, lParam);
+ return 0;
+ }
+ if (hMenu != NULL) {
+ ClientToScreen(hwnd, &pt);
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL);
+ DestroyMenu(hMenu);
+ }
+ return 0;
+ }
+ case WM_COMMAND:
+ if (LOWORD(wParam) == POPUP_NEWGROUP)
+ SendMessage(GetParent(hwnd), msg, wParam, lParam);
+ break;
+
+ case WM_MOUSEMOVE: {
+ int iOldHT = dat->iHotTrack;
+ LRESULT result = saveContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if(dat->iHotTrack != iOldHT)
+ InvalidateRect(hwnd, 0, FALSE);
+ return(result);
+ }
+
+ case WM_NCHITTEST: {
+ LRESULT lr = SendMessage(GetParent(hwnd), WM_NCHITTEST, wParam, lParam);
+ if (lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT
+ || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT)
+ return HTTRANSPARENT;
+ break;
+ }
+ case WM_DESTROY: {
+ int i;
+
+ if (!dat->bisEmbedded) {
+ for (i = 0; i < cfg::nextCacheEntry; i++) {
+ if (cfg::eCache[i].floater && cfg::eCache[i].floater->hwnd)
+ DestroyWindow(cfg::eCache[i].floater->hwnd);
+ }
+ }
+ RowHeight::Free(dat);
+ if(dat->ph) {
+ delete dat->ph;
+ dat->ph = 0;
+ }
+ break;
+ }
+ }
+
+ {
+ LRESULT result = coreCli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ return result;
+ }
+}
+
+int CLC::findItem(HWND hwnd, ClcData *dat, HANDLE hItem, ClcContact **contact, ClcGroup **subgroup, int *isVisible)
+{
+ int index = 0;
+ int nowVisible = 1;
+ ClcGroup *group = &dat->list;
+
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ ClcGroup *tgroup;
+ group = group->parent;
+ if (group == NULL)
+ break;
+ nowVisible = 1;
+ for (tgroup = group; tgroup; tgroup = tgroup->parent) {
+ if (!(group->expanded)) {
+ nowVisible = 0; break;
+ }
+ }
+ group->scanIndex++;
+ continue;
+ }
+ if (nowVisible)
+ index++;
+ if ((IsHContactGroup(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_GROUP && ((UINT_PTR)hItem & ~HCONTACT_ISGROUP) == group->cl.items[group->scanIndex]->groupId) ||
+ (IsHContactContact(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->hContact == (MCONTACT)hItem) ||
+ (IsHContactInfo(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->hContact == (MCONTACT)((UINT_PTR)hItem & ~HCONTACT_ISINFO)))
+ {
+ if (isVisible) {
+ if (!nowVisible)
+ *isVisible = 0;
+ else {
+ int posy = RowHeight::getItemTopY(dat, index + 1);
+ if (posy < dat->yScroll)
+ *isVisible = 0;
+ //if ((index + 1) * dat->rowHeight< dat->yScroll)
+ // *isVisible = 0;
+ else {
+ RECT clRect;
+ GetClientRect(hwnd, &clRect);
+ //if (index * dat->rowHeight >= dat->yScroll + clRect.bottom)
+ if (posy >= dat->yScroll + clRect.bottom)
+ *isVisible = 0;
+ else
+ *isVisible = 1;
+ }
+ }
+ }
+ if (contact)
+ *contact = group->cl.items[group->scanIndex];
+ if (subgroup)
+ *subgroup = group;
+ return 1;
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ nowVisible &= (group->expanded);
+ continue;
+ }
+ group->scanIndex++;
+ }
+
+ if (isVisible) *isVisible = FALSE;
+ if (contact) *contact = NULL;
+ if (subgroup) *subgroup = NULL;
+ return 0;
+}
+
+void CLC::countAvatars(ClcData *dat)
+{
+ if(dat->bisEmbedded)
+ return;
+
+ CLC::uNrAvatars = 0;
+ ClcGroup* group;
+
+ group = &dat->list;
+ group->scanIndex = 0;
+
+ while(TRUE) {
+ if (group->scanIndex==group->cl.count)
+ {
+ group=group->parent;
+ if(group==NULL)
+ break; // Finished list
+ group->scanIndex++;
+ continue;
+ }
+
+ if(group->cl.items[group->scanIndex]->cFlags & ECF_AVATAR)
+ CLC::uNrAvatars++;
+
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) {
+ group=group->cl.items[group->scanIndex]->group;
+ group->scanIndex=0;
+ continue;
+ }
+ group->scanIndex++;
+ }
+}
diff --git a/plugins/Clist_ng/SRC/clcitems.cpp b/plugins/Clist_ng/SRC/clcitems.cpp new file mode 100644 index 0000000000..99aadd11c7 --- /dev/null +++ b/plugins/Clist_ng/SRC/clcitems.cpp @@ -0,0 +1,543 @@ +/*
+ * 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: clcitems.cpp 138 2010-11-01 10:51:15Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include <m_icq.h>
+
+extern HANDLE hExtraImageListRebuilding, hExtraImageApplying;
+
+static void TZ_LoadTimeZone(MCONTACT hContact, struct TExtraCache *c, const char *szProto);
+
+//routines for managing adding/removal of items in the list, including sorting
+
+ClcContact* CLC::CreateClcContact()
+{
+ struct ClcContact* p = (struct ClcContact*)mir_alloc( sizeof( struct ClcContact ) );
+ if ( p != NULL ) {
+ ZeroMemory(p, sizeof(struct ClcContact));
+ //p->clientId = -1;
+ p->extraCacheEntry = -1;
+ p->avatarLeft = p->extraIconRightBegin = -1;
+ p->isRtl = 0;
+ p->ace = 0;
+ }
+ return p;
+}
+
+int CLC::AddInfoItemToGroup(ClcGroup *group, int flags, const wchar_t *pszText)
+{
+ int i = coreCli.pfnAddInfoItemToGroup(group, flags, pszText);
+ ClcContact* p = group->cl.items[i];
+ p->bIsMeta = 0;
+ p->xStatus = 0;
+ p->ace = NULL;
+ p->extraCacheEntry = -1;
+ p->avatarLeft = p->extraIconRightBegin = -1;
+ return i;
+}
+
+ClcGroup* CLC::AddGroup(HWND hwnd, struct ClcData *dat, const wchar_t *szName, DWORD flags, int groupId, int calcTotalMembers)
+{
+ struct ClcGroup *p = coreCli.pfnAddGroup( hwnd, dat, szName, flags, groupId, calcTotalMembers);
+
+ if ( p && p->parent )
+ RTL_DetectGroupName( p->parent->cl.items[ p->parent->cl.count-1] );
+ return p;
+}
+
+ClcGroup* CLC::RemoveItemFromGroup(HWND hwnd, ClcGroup *group, ClcContact *contact, int updateTotalCount)
+{
+ if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) {
+ if(cfg::eCache[contact->extraCacheEntry].floater && cfg::eCache[contact->extraCacheEntry].floater->hwnd)
+ ShowWindow(cfg::eCache[contact->extraCacheEntry].floater->hwnd, SW_HIDE);
+ }
+ return(coreCli.pfnRemoveItemFromGroup(hwnd, group, contact, updateTotalCount));
+}
+
+void LoadAvatarForContact(struct ClcContact *p)
+{
+ if(cfg::dat.dwFlags & CLUI_FRAME_AVATARS)
+ p->cFlags = (p->dwDFlags & ECF_HIDEAVATAR ? p->cFlags & ~ECF_AVATAR : p->cFlags | ECF_AVATAR);
+ else
+ p->cFlags = (p->dwDFlags & ECF_FORCEAVATAR ? p->cFlags | ECF_AVATAR : p->cFlags & ~ECF_AVATAR);
+
+ p->ace = NULL;
+ if(/*(p->cFlags & ECF_AVATAR) && */(!cfg::dat.bNoOfflineAvatars || p->wStatus != ID_STATUS_OFFLINE)) {
+ p->ace = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)p->hContact, 0);
+ if(CALLSERVICE_NOTFOUND == (INT_PTR)p->ace)
+ p->ace = 0;
+ if (p->ace != NULL && p->ace->cbSize != sizeof(struct avatarCacheEntry))
+ p->ace = NULL;
+ if (p->ace != NULL)
+ p->ace->t_lastAccess = cfg::dat.t_now;
+ }
+ if(p->ace == NULL)
+ p->cFlags &= ~ECF_AVATAR;
+}
+
+int CLC::AddContactToGroup(struct ClcData *dat, struct ClcGroup *group, MCONTACT hContact)
+{
+ int i = coreCli.pfnAddContactToGroup( dat, group, hContact );
+ struct ClcContact* p = group->cl.items[i];
+
+ p->wStatus = cfg::getWord(hContact, p->proto, "Status", ID_STATUS_OFFLINE);
+ p->xStatus = cfg::getByte(hContact, p->proto, "XStatusId", 0);
+ //p->iRowHeight = -1;
+
+ if (p->proto)
+ p->bIsMeta = !strcmp(p->proto, cfg::dat.szMetaName);
+ else
+ p->bIsMeta = FALSE;
+ if (p->bIsMeta && cfg::dat.bMetaAvail) {
+ p->hSubContact = db_mc_getMostOnline(hContact);
+ p->metaProto = GetContactProto(p->hSubContact);
+ p->iImage = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) p->hSubContact, 0);
+ } else {
+ p->iImage = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) hContact, 0);
+ p->metaProto = NULL;
+ }
+ p->bSecondLine = cfg::dat.dualRowMode;
+ p->bSecondLineLocal = cfg::getByte(hContact, "CList", "CLN_2ndline", -1);
+
+ p->dwDFlags = cfg::getDword(hContact, "CList", "CLN_Flags", 0);
+
+ if(dat->bisEmbedded)
+ p->extraCacheEntry = -1;
+ else {
+ p->extraCacheEntry = cfg::getCache(p->hContact, p->proto);
+ GetExtendedInfo( p, dat);
+ if(p->extraCacheEntry >= 0 && p->extraCacheEntry < cfg::nextCacheEntry) {
+ cfg::eCache[p->extraCacheEntry].proto_status_item = GetProtocolStatusItem(p->bIsMeta ? p->metaProto : p->proto);
+ if(cfg::getByte(p->hContact, "CList", "floating", 0) && g_floatoptions.enabled) {
+ if(cfg::eCache[p->extraCacheEntry].floater == NULL)
+ FLT_Create(p->extraCacheEntry);
+ else {
+ ShowWindow(cfg::eCache[p->extraCacheEntry].floater->hwnd, SW_SHOWNOACTIVATE);
+ FLT_Update(dat, p);
+ }
+ }
+ }
+ LoadAvatarForContact(p);
+ // notify other plugins to re-supply their extra images (icq for xstatus, mBirthday etc...)
+ pcli->pfnSetAllExtraIcons(hContact);
+ }
+ RTL_DetectAndSet( p, p->hContact);
+ p->avatarLeft = p->extraIconRightBegin = -1;
+ p->flags |= cfg::getByte(p->hContact, "CList", "Priority", 0) ? CONTACTF_PRIORITY : 0;
+
+ return i;
+}
+
+void CLC::RebuildEntireList(HWND hwnd, ClcData *dat)
+{
+ char *szProto;
+ DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+ MCONTACT hContact;
+ ClcGroup *group;
+ DBVARIANT dbv = {0};
+
+ RowHeight::Clear(dat);
+ RowHeight::getMaxRowHeight(dat, hwnd);
+
+ dat->list.expanded = 1;
+ dat->list.hideOffline = cfg::getByte("CLC", "HideOfflineRoot", 0);
+ dat->list.cl.count = 0;
+ dat->list.totalMembers = 0;
+ dat->selection = -1;
+ dat->SelectMode = cfg::getByte("CLC", "SelectMode", 0); {
+ int i;
+ wchar_t *szGroupName;
+ DWORD groupFlags;
+
+ for (i = 1; ; i++) {
+ szGroupName = pcli->pfnGetGroupName(i, &groupFlags);
+ if (szGroupName == NULL)
+ break;
+ pcli->pfnAddGroup(hwnd, dat, szGroupName, groupFlags, i, 0);
+ }
+ }
+
+ hContact = db_find_first();
+ while (hContact) {
+ if (style & CLS_SHOWHIDDEN || !CLVM_GetContactHiddenStatus(hContact, NULL, dat)) {
+ ZeroMemory((void *)&dbv, sizeof(dbv));
+ if (cfg::getTString(hContact, "CList", "Group", &dbv))
+ group = &dat->list;
+ else {
+ group = pcli->pfnAddGroup(hwnd, dat, dbv.ptszVal, (DWORD) - 1, 0, 0);
+ mir_free(dbv.ptszVal);
+ }
+
+ if (group != NULL) {
+ group->totalMembers++;
+ if (!(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline)) {
+ szProto = GetContactProto(hContact);
+ if (szProto == NULL) {
+ if (!pcli->pfnIsHiddenMode(dat, ID_STATUS_OFFLINE))
+ AddContactToGroup(dat, group, hContact);
+ } else if (!pcli->pfnIsHiddenMode(dat, (WORD) cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE)))
+ AddContactToGroup(dat, group, hContact);
+ } else
+ AddContactToGroup(dat, group, hContact);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+
+ if (style & CLS_HIDEEMPTYGROUPS) {
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (; ;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ } else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ if (group->cl.items[group->scanIndex]->group->cl.count == 0) {
+ group = pcli->pfnRemoveItemFromGroup(hwnd, group, group->cl.items[group->scanIndex], 0);
+ } else {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ }
+ continue;
+ }
+ group->scanIndex++;
+ }
+ }
+ pcli->pfnSortCLC(hwnd, dat, 0);
+ pcli->pfnSetAllExtraIcons(NULL);
+ if(!dat->bisEmbedded)
+ FLT_SyncWithClist();
+}
+
+/*
+ * status msg in the database has changed.
+ * get it and store it properly formatted in the extra data cache
+ */
+
+BYTE GetCachedStatusMsg(int iExtraCacheEntry, char *szProto)
+{
+ DBVARIANT dbv = {0};
+ MCONTACT hContact;
+ TExtraCache *cEntry;
+ int result;
+
+ if(iExtraCacheEntry < 0 || iExtraCacheEntry > cfg::nextCacheEntry)
+ return 0;
+
+ cEntry = &cfg::eCache[iExtraCacheEntry];
+
+ cEntry->bStatusMsgValid = STATUSMSG_NOTFOUND;
+ hContact = cEntry->hContact;
+
+ result = cfg::getTString(hContact, "CList", "StatusMsg", &dbv);
+ if ( !result && lstrlen(dbv.ptszVal) > 1)
+ cEntry->bStatusMsgValid = STATUSMSG_CLIST;
+ else {
+ if (!szProto)
+ szProto = GetContactProto(hContact);
+ if(szProto) {
+ if ( !result )
+ db_free(&dbv);
+ if( !( result = cfg::getTString(hContact, szProto, "YMsg", &dbv)) && lstrlen(dbv.ptszVal) > 1)
+ cEntry->bStatusMsgValid = STATUSMSG_YIM;
+ else if ( !(result = cfg::getTString(hContact, szProto, "StatusDescr", &dbv)) && lstrlen(dbv.ptszVal) > 1)
+ cEntry->bStatusMsgValid = STATUSMSG_GG;
+ else if( !(result = cfg::getTString(hContact, szProto, "XStatusMsg", &dbv)) && lstrlen(dbv.ptszVal) > 1)
+ cEntry->bStatusMsgValid = STATUSMSG_XSTATUS;
+ } }
+
+ if(cEntry->bStatusMsgValid == STATUSMSG_NOTFOUND) { // no status msg, consider xstatus name (if available)
+ if ( !result )
+ db_free( &dbv );
+ result = cfg::getTString(hContact, szProto, "XStatusName", &dbv);
+ if ( !result && lstrlen(dbv.ptszVal) > 1) {
+ int iLen = lstrlen(dbv.ptszVal);
+ cEntry->bStatusMsgValid = STATUSMSG_XSTATUSNAME;
+ cEntry->statusMsg = (wchar_t *)realloc(cEntry->statusMsg, (iLen + 2) * sizeof(wchar_t));
+ _tcsncpy(cEntry->statusMsg, dbv.ptszVal, iLen + 1);
+ }
+ else {
+ int xStatus;
+ WPARAM xStatus2;
+ wchar_t xStatusName[128];
+
+ CUSTOM_STATUS cst = { sizeof(cst) };
+ cst.flags = CSSF_MASK_STATUS;
+ cst.status = &xStatus;
+ if (ProtoServiceExists(szProto, PS_GETCUSTOMSTATUSEX) && !CallProtoService(szProto, PS_GETCUSTOMSTATUSEX, hContact, (LPARAM)&cst) && xStatus > 0) {
+ cst.flags = CSSF_MASK_NAME | CSSF_DEFAULT_NAME | CSSF_TCHAR;
+ cst.wParam = &xStatus2;
+ cst.ptszName = xStatusName;
+ if (!CallProtoService(szProto, PS_GETCUSTOMSTATUSEX, hContact, (LPARAM)&cst)) {
+ wchar_t *szwXstatusName = TranslateTS(xStatusName);
+ cEntry->statusMsg = (wchar_t *)realloc(cEntry->statusMsg, (lstrlen(szwXstatusName) + 2) * sizeof(wchar_t));
+ _tcsncpy(cEntry->statusMsg, szwXstatusName, lstrlen(szwXstatusName) + 1);
+ cEntry->bStatusMsgValid = STATUSMSG_XSTATUSNAME;
+ }
+ }
+ }
+ }
+ if(cEntry->bStatusMsgValid > STATUSMSG_XSTATUSNAME) {
+ int j = 0, i;
+ cEntry->statusMsg = (wchar_t *)realloc(cEntry->statusMsg, (lstrlen(dbv.ptszVal) + 2) * sizeof(wchar_t));
+ for(i = 0; dbv.ptszVal[i]; i++) {
+ if(dbv.ptszVal[i] == (wchar_t)0x0d)
+ continue;
+ cEntry->statusMsg[j] = dbv.ptszVal[i] == (wchar_t)0x0a ? (wchar_t)' ' : dbv.ptszVal[i];
+ j++;
+ }
+ cEntry->statusMsg[j] = (wchar_t)0;
+ }
+ if ( !result )
+ db_free( &dbv );
+
+ if(cEntry->bStatusMsgValid != STATUSMSG_NOTFOUND) {
+ WORD infoTypeC2[12];
+ int iLen, i
+ ;
+ ZeroMemory(infoTypeC2, sizeof(WORD) * 12);
+ iLen = min(lstrlenW(cEntry->statusMsg), 10);
+ GetStringTypeW(CT_CTYPE2, cEntry->statusMsg, iLen, infoTypeC2);
+ cEntry->dwCFlags &= ~ECF_RTLSTATUSMSG;
+ for(i = 0; i < 10; i++) {
+ if(infoTypeC2[i] == C2_RIGHTTOLEFT) {
+ cEntry->dwCFlags |= ECF_RTLSTATUSMSG;
+ break;
+ }
+ }
+ }
+ if(cEntry->hTimeZone == 0)
+ TZ_LoadTimeZone(hContact, cEntry, szProto);
+ return cEntry->bStatusMsgValid;;
+}
+
+/*
+ * load time zone information for the contact
+ * if TzName is set, use it. It has to be a standard windows time zone name
+ * Currently, it can only be set by using UserInfoEx plugin
+ *
+ * Fallback: use ordinary GMT offsets (incorrect, in some cases due to DST
+ * differences.
+ */
+
+static void TZ_LoadTimeZone(MCONTACT hContact, TExtraCache *c, const char *szProto)
+{
+ DWORD flags = 0;
+ if (cfg::dat.bShowLocalTimeSelective) flags |= TZF_DIFONLY;
+ c->hTimeZone = TimeZone_CreateByContact(hContact, 0, flags);
+}
+
+void ReloadExtraInfo(MCONTACT hContact)
+{
+ if(hContact && pcli->hwndContactTree) {
+ int index = cfg::getCache(hContact, NULL);
+ if(index >= 0 && index < cfg::nextCacheEntry) {
+ char *szProto = GetContactProto(hContact);
+
+ TZ_LoadTimeZone(hContact, &cfg::eCache[index], szProto);
+ InvalidateRect(pcli->hwndContactTree, NULL, FALSE);
+ }
+ }
+}
+
+/*
+ * autodetect RTL property of the nickname, evaluates the first 10 characters of the nickname only
+ */
+
+void RTL_DetectAndSet(struct ClcContact *contact, MCONTACT hContact)
+{
+ WORD infoTypeC2[12];
+ int i, index;
+ wchar_t *szText = NULL;
+ DWORD iLen;
+
+ ZeroMemory(infoTypeC2, sizeof(WORD) * 12);
+
+ if(contact == NULL) {
+ szText = pcli->pfnGetContactDisplayName(hContact, 0);
+ index = cfg::getCache(hContact, NULL);
+ }
+ else {
+ szText = contact->szText;
+ index = contact->extraCacheEntry;
+ }
+ if(index >= 0 && index < cfg::nextCacheEntry) {
+ iLen = min(lstrlenW(szText), 10);
+ GetStringTypeW(CT_CTYPE2, szText, iLen, infoTypeC2);
+ cfg::eCache[index].dwCFlags &= ~ECF_RTLNICK;
+ for(i = 0; i < 10; i++) {
+ if(infoTypeC2[i] == C2_RIGHTTOLEFT) {
+ cfg::eCache[index].dwCFlags |= ECF_RTLNICK;
+ return;
+ }
+ }
+ }
+}
+
+void RTL_DetectGroupName(struct ClcContact *group)
+{
+ WORD infoTypeC2[12];
+ int i;
+ DWORD iLen;
+
+ group->isRtl = 0;
+
+ if(group->szText) {
+ iLen = min(lstrlenW(group->szText), 10);
+ GetStringTypeW(CT_CTYPE2, group->szText, iLen, infoTypeC2);
+ for(i = 0; i < 10; i++) {
+ if(infoTypeC2[i] == C2_RIGHTTOLEFT) {
+ group->isRtl = 1;
+ return;
+ }
+ }
+ }
+}
+/*
+ * check for exteneded user information - email, phone numbers, homepage
+ * set extra icons accordingly
+ */
+
+void GetExtendedInfo(struct ClcContact *contact, struct ClcData *dat)
+{
+ int index;
+
+ if(dat->bisEmbedded || contact == NULL)
+ return;
+
+ if(contact->proto == NULL || contact->hContact == 0)
+ return;
+
+ index = contact->extraCacheEntry;
+
+ if(index >= 0 && index < cfg::nextCacheEntry) {
+ if(cfg::eCache[index].valid)
+ return;
+ cfg::eCache[index].valid = TRUE;
+ }
+ else
+ return;
+ cfg::eCache[index].isChatRoom = cfg::getByte(contact->hContact, contact->proto, "ChatRoom", 0);
+ cfg::eCache[index].msgFrequency = cfg::getDword(contact->hContact, "CList", "mf_freq", 0x7fffffff);
+
+}
+
+DWORD CalcXMask(MCONTACT hContact)
+{
+ DWORD dwXMask = cfg::getDword(hContact, "CList", "CLN_xmask", 0);
+ int i;
+ DWORD dwResult = cfg::dat.dwExtraImageMask, bForced, bHidden;
+
+ for(i = 0; i <= 10; i++) {
+ bForced = (dwXMask & (1 << (2 * i)));
+ bHidden = (dwXMask & (1 << (2 * i + 1)));
+ if(bForced == 0 && bHidden == 0)
+ continue;
+ else if(bForced)
+ dwResult |= (1 << i);
+ else if(bHidden)
+ dwResult &= ~(1 << i);
+ }
+ return(dwResult);
+}
+
+/*
+ * checks the currently active view mode filter and returns true, if the contact should be hidden
+ * if no view mode is active, it returns the CList/Hidden setting
+ * also cares about sub contacts (if meta is active)
+ */
+
+int __fastcall CLVM_GetContactHiddenStatus(MCONTACT hContact, char *szProto, struct ClcData *dat)
+{
+ int dbHidden = cfg::getByte(hContact, "CList", "Hidden", 0); // default hidden state, always respect it.
+ int filterResult = 1;
+ DBVARIANT dbv = {0};
+ char szTemp[64];
+ wchar_t szGroupMask[256];
+ DWORD dwLocalMask;
+
+ // always hide subcontacts (but show them on embedded contact lists)
+
+ if(cfg::dat.bMetaAvail && dat != NULL && dat->bHideSubcontacts && cfg::dat.bMetaEnabled && cfg::getByte(hContact, cfg::dat.szMetaName, "IsSubcontact", 0))
+ return 1;
+
+ if(cfg::dat.bFilterEffective) {
+ if (szProto == NULL)
+ szProto = GetContactProto(hContact);
+ // check stickies first (priority), only if we really have stickies defined (CLVM_STICKY_CONTACTS is set).
+ if(cfg::dat.bFilterEffective & CLVM_STICKY_CONTACTS) {
+ if((dwLocalMask = cfg::getDword(hContact, "CLVM", cfg::dat.current_viewmode, 0)) != 0) {
+ if(cfg::dat.bFilterEffective & CLVM_FILTER_STICKYSTATUS) {
+ WORD wStatus = cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ return !((1 << (wStatus - ID_STATUS_OFFLINE)) & HIWORD(dwLocalMask));
+ }
+ return 0;
+ }
+ }
+ // check the proto, use it as a base filter result for all further checks
+ if(cfg::dat.bFilterEffective & CLVM_FILTER_PROTOS) {
+ mir_snprintf(szTemp, sizeof(szTemp), "%s|", szProto);
+ filterResult = strstr(cfg::dat.protoFilter, szTemp) ? 1 : 0;
+ }
+ if(cfg::dat.bFilterEffective & CLVM_FILTER_GROUPS) {
+ if(!cfg::getTString(hContact, "CList", "Group", &dbv)) {
+ _sntprintf(szGroupMask, safe_sizeof(szGroupMask), _T("%s|"), &dbv.ptszVal[1]);
+ filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? (filterResult | (_tcsstr(cfg::dat.groupFilter, szGroupMask) ? 1 : 0)) : (filterResult & (_tcsstr(cfg::dat.groupFilter, szGroupMask) ? 1 : 0));
+ mir_free(dbv.ptszVal);
+ }
+ else if(cfg::dat.filterFlags & CLVM_INCLUDED_UNGROUPED)
+ filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 1;
+ else
+ filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 0;
+ }
+ if(cfg::dat.bFilterEffective & CLVM_FILTER_STATUS) {
+ WORD wStatus = cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ filterResult = (cfg::dat.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & cfg::dat.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & cfg::dat.statusMaskFilter ? 1 : 0));
+ }
+ if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG) {
+ DWORD now;
+ int iEntry = cfg::getCache(hContact, szProto);
+ if(iEntry >= 0 && iEntry <= cfg::nextCacheEntry) {
+ now = cfg::dat.t_now;
+ now -= cfg::dat.lastMsgFilter;
+ if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG_OLDERTHAN)
+ filterResult = filterResult & (cfg::eCache[iEntry].dwLastMsgTime < now);
+ else if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG_NEWERTHAN)
+ filterResult = filterResult & (cfg::eCache[iEntry].dwLastMsgTime > now);
+ }
+ }
+ return (dbHidden | !filterResult);
+ }
+ else
+ return dbHidden;
+}
diff --git a/plugins/Clist_ng/SRC/clcmsgs.cpp b/plugins/Clist_ng/SRC/clcmsgs.cpp new file mode 100644 index 0000000000..f8b52b27f2 --- /dev/null +++ b/plugins/Clist_ng/SRC/clcmsgs.cpp @@ -0,0 +1,211 @@ +/*
+ * 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_nicer plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: clcmsgs.cpp 132 2010-09-29 07:49:20Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+
+//processing of all the CLM_ messages incoming
+
+LRESULT CLC::ProcessExternalMessages(HWND hwnd, ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case CLM_SETSTICKY:
+ {
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+
+ if (wParam == 0 || !findItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL))
+ return 0;
+ if (lParam)
+ contact->flags |= CONTACTF_STICKY;
+ else
+ contact->flags &= ~CONTACTF_STICKY;
+ break;
+ }
+
+ case CLM_SETEXTRAIMAGEINT:
+ {
+ struct ClcContact *contact = NULL;
+ int index = -1;
+
+ if (LOWORD(lParam) >= MAXEXTRACOLUMNS || wParam == 0)
+ return 0;
+
+ if (!findItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ return 0;
+
+ index = contact->extraCacheEntry;
+
+ if(contact->type != CLCIT_CONTACT) // || contact->bIsMeta)
+ return 0;
+
+ if(index >= 0 && index < cfg::nextCacheEntry) {
+ cfg::eCache[index].iExtraImage[LOWORD(lParam)] = (BYTE)HIWORD(lParam);
+ cfg::eCache[index].iExtraValid = cfg::eCache[index].iExtraImage[LOWORD(lParam)] != (BYTE)0xff ? (cfg::eCache[index].iExtraValid | (1 << LOWORD(lParam))) : (cfg::eCache[index].iExtraValid & ~(1 << LOWORD(lParam)));
+ PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contact ? contact->hContact : 0));
+ }
+ }
+ return 0;
+ case CLM_SETEXTRAIMAGEINTMETA:
+ {
+ MCONTACT hMasterContact = 0;
+ int index = -1;
+
+ if (LOWORD(lParam) >= MAXEXTRACOLUMNS)
+ return 0;
+
+ index = cfg::getCache(wParam, NULL);
+ if(index >= 0 && index < cfg::nextCacheEntry) {
+ cfg::eCache[index].iExtraImage[LOWORD(lParam)] = (BYTE)HIWORD(lParam);
+ cfg::eCache[index].iExtraValid = cfg::eCache[index].iExtraImage[LOWORD(lParam)] != (BYTE)0xff ? (cfg::eCache[index].iExtraValid | (1 << LOWORD(lParam))) : (cfg::eCache[index].iExtraValid & ~(1 << LOWORD(lParam)));
+ }
+
+ hMasterContact = cfg::getDword(wParam, cfg::dat.szMetaName, "Handle", 0);
+
+ index = cfg::getCache(hMasterContact, NULL);
+ if(index >= 0 && index < cfg::nextCacheEntry) {
+ cfg::eCache[index].iExtraImage[LOWORD(lParam)] = (BYTE)HIWORD(lParam);
+ cfg::eCache[index].iExtraValid = cfg::eCache[index].iExtraImage[LOWORD(lParam)] != (BYTE)0xff ? (cfg::eCache[index].iExtraValid | (1 << LOWORD(lParam))) : (cfg::eCache[index].iExtraValid & ~(1 << LOWORD(lParam)));
+ PostMessage(hwnd, INTM_INVALIDATE, 0, 0);
+ }
+ }
+ return 0;
+
+ case CLM_GETSTATUSMSG:
+ {
+ ClcContact *contact = NULL;
+
+ if (wParam == 0)
+ return 0;
+
+ if (!findItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL))
+ return 0;
+ if(contact->type != CLCIT_CONTACT)
+ return 0;
+ if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry <= cfg::nextCacheEntry) {
+ if(cfg::eCache[contact->extraCacheEntry].bStatusMsgValid != STATUSMSG_NOTFOUND)
+ return((INT_PTR)cfg::eCache[contact->extraCacheEntry].statusMsg);
+ } }
+ return 0;
+
+ case CLM_SETHIDESUBCONTACTS:
+ dat->bHideSubcontacts = (BOOL)lParam;
+ return 0;
+
+ case CLM_TOGGLEPRIORITYCONTACT:
+ {
+ struct ClcContact *contact = NULL;
+
+ if (wParam == 0)
+ return 0;
+
+ if (!findItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL))
+ return 0;
+ if(contact->type != CLCIT_CONTACT)
+ return 0;
+ contact->flags ^= CONTACTF_PRIORITY;
+ cfg::writeByte(contact->hContact, "CList", "Priority", (BYTE)(contact->flags & CONTACTF_PRIORITY ? 1 : 0));
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ return 0;
+ }
+ case CLM_QUERYPRIORITYCONTACT:
+ {
+ struct ClcContact *contact = NULL;
+
+ if (wParam == 0)
+ return 0;
+
+ if (!findItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL))
+ return 0;
+ if(contact->type != CLCIT_CONTACT)
+ return 0;
+ return(contact->flags & CONTACTF_PRIORITY ? 1 : 0);
+ }
+ case CLM_TOGGLEFLOATINGCONTACT:
+ {
+ struct ClcContact *contact = NULL;
+ BYTE state;
+ int iEntry;
+
+ if (wParam == 0)
+ return 0;
+
+ if (!findItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL))
+ return 0;
+ if(contact->type != CLCIT_CONTACT)
+ return 0;
+
+ iEntry = contact->extraCacheEntry;
+
+ if(iEntry >= 0 && iEntry <= cfg::nextCacheEntry) {
+ state = !cfg::getByte(contact->hContact, "CList", "floating", 0);
+ if(state) {
+ if(cfg::eCache[iEntry].floater == NULL)
+ FLT_Create(iEntry);
+ ShowWindow(cfg::eCache[contact->extraCacheEntry].floater->hwnd, SW_SHOW);
+ }
+ else {
+ if(cfg::eCache[iEntry].floater && cfg::eCache[iEntry].floater->hwnd) {
+ DestroyWindow(cfg::eCache[iEntry].floater->hwnd);
+ cfg::eCache[iEntry].floater = 0;
+ }
+ }
+ cfg::writeByte(contact->hContact, "CList", "floating", state);
+ }
+ return 0;
+ }
+ case CLM_QUERYFLOATINGCONTACT:
+ {
+ return(cfg::getByte(wParam, "CList", "floating", 0));
+ }
+ case CLM_SETEXTRAIMAGELIST:
+ dat->himlExtraColumns = (HIMAGELIST) lParam;
+ InvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case CLM_SETFONT:
+ if(HIWORD(lParam)<0 || HIWORD(lParam)>FONTID_LAST)
+ return 0;
+ dat->fontInfo[HIWORD(lParam)].hFont = (HFONT)wParam;
+ dat->fontInfo[HIWORD(lParam)].changed = 1;
+
+ RowHeight::getMaxRowHeight(dat, hwnd);
+
+ if(LOWORD(lParam))
+ InvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+
+ case CLM_ISMULTISELECT:
+ return dat->isMultiSelect;
+ }
+
+ return coreCli.pfnProcessExternalMessages(hwnd, dat, msg, wParam, lParam);
+}
diff --git a/plugins/Clist_ng/SRC/clcopts.cpp b/plugins/Clist_ng/SRC/clcopts.cpp new file mode 100644 index 0000000000..2c4e81ae39 --- /dev/null +++ b/plugins/Clist_ng/SRC/clcopts.cpp @@ -0,0 +1,1408 @@ +/*
+ * 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_n plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: clcopts.cpp 136 2010-10-12 18:55:36Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include "../coolsb/coolscroll.h"
+
+#define DBFONTF_BOLD 1
+#define DBFONTF_ITALIC 2
+#define DBFONTF_UNDERLINE 4
+
+struct CheckBoxToStyleEx_t {
+ int id;
+ DWORD flag;
+ int not_t;
+} static const checkBoxToStyleEx[] = {
+ {IDC_DISABLEDRAGDROP, CLS_EX_DISABLEDRAGDROP, 0}, {IDC_NOTEDITLABELS, CLS_EX_EDITLABELS, 1},
+ {IDC_SHOWSELALWAYS, CLS_EX_SHOWSELALWAYS, 0}, {IDC_TRACKSELECT, CLS_EX_TRACKSELECT, 0},
+ {IDC_DIVIDERONOFF, CLS_EX_DIVIDERONOFF, 0}, {IDC_NOTNOTRANSLUCENTSEL, CLS_EX_NOTRANSLUCENTSEL, 1},
+ {IDC_NOTNOSMOOTHSCROLLING, CLS_EX_NOSMOOTHSCROLLING, 1}
+};
+
+struct CheckBoxToGroupStyleEx_t {
+ int id;
+ DWORD flag;
+ int not_t;
+} static const checkBoxToGroupStyleEx[] = {
+ {IDC_SHOWGROUPCOUNTS, CLS_EX_SHOWGROUPCOUNTS, 0}, {IDC_HIDECOUNTSWHENEMPTY, CLS_EX_HIDECOUNTSWHENEMPTY, 0},
+ {IDC_LINEWITHGROUPS, CLS_EX_LINEWITHGROUPS, 0}, {IDC_QUICKSEARCHVISONLY, CLS_EX_QUICKSEARCHVISONLY, 0},
+ {IDC_SORTGROUPSALPHA, CLS_EX_SORTGROUPSALPHA, 0}
+};
+
+struct CheckBoxValues_t {
+ DWORD style;
+ wchar_t *szDescr;
+};
+
+static const struct CheckBoxValues_t greyoutValues[] = {
+ { GREYF_UNFOCUS, LPGENT("Not focused")},
+ { MODEF_OFFLINE, LPGENT("Offline")},
+ { PF2_ONLINE, LPGENT("Online")},
+ { PF2_SHORTAWAY, LPGENT("Away")},
+ { PF2_LONGAWAY, LPGENT("NA")},
+ { PF2_LIGHTDND, LPGENT("Occupied")},
+ { PF2_HEAVYDND, LPGENT("DND")},
+ { PF2_FREECHAT, LPGENT("Free for chat")},
+ { PF2_INVISIBLE, LPGENT("Invisible")},
+ { PF2_OUTTOLUNCH, LPGENT("Out to lunch")},
+ { PF2_ONTHEPHONE, LPGENT("On the phone")}
+};
+
+static const struct CheckBoxValues_t offlineValues[] = {
+ { MODEF_OFFLINE, LPGENT("Offline")},
+ { PF2_ONLINE, LPGENT("Online")},
+ { PF2_SHORTAWAY, LPGENT("Away")},
+ { PF2_LONGAWAY, LPGENT("NA")},
+ { PF2_LIGHTDND, LPGENT("Occupied")},
+ { PF2_HEAVYDND, LPGENT("DND")},
+ { PF2_FREECHAT, LPGENT("Free for chat")},
+ { PF2_INVISIBLE, LPGENT("Invisible")},
+ { PF2_OUTTOLUNCH, LPGENT("Out to lunch")},
+ { PF2_ONTHEPHONE, LPGENT("On the phone")}
+};
+
+static HIMAGELIST himlCheckBoxes = 0;
+
+static HIMAGELIST CreateStateImageList()
+{
+ if(0 == himlCheckBoxes) {
+ HICON hIconNoTick = Skin_LoadIcon(SKINICON_OTHER_NOTICK);
+ HICON hIconTick = Skin_LoadIcon(SKINICON_OTHER_TICK);
+
+ himlCheckBoxes = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 2, 2);
+ ImageList_AddIcon(himlCheckBoxes, hIconNoTick);
+ ImageList_AddIcon(himlCheckBoxes, hIconTick);
+ ImageList_AddIcon(himlCheckBoxes, hIconNoTick);
+ }
+ return(himlCheckBoxes);
+}
+
+
+static UINT sortCtrlIDs[] = {IDC_SORTPRIMARY, IDC_SORTTHEN, IDC_SORTFINALLY, 0};
+
+static void FillCheckBoxTree(HWND hwndTree, const struct CheckBoxValues_t *values, int nValues, DWORD style)
+{
+ TVINSERTSTRUCT tvis;
+ int i;
+
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE;
+ for(i = 0; i < nValues; i++) {
+ tvis.item.lParam = values[i].style;
+ tvis.item.pszText = TranslateTS(values[i].szDescr);
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK((style & tvis.item.lParam) != 0 ? 2 : 1);
+ TreeView_InsertItem(hwndTree, &tvis);
+ }
+}
+
+static DWORD MakeCheckBoxTreeFlags(HWND hwndTree)
+{
+ DWORD flags = 0;
+ TVITEM tvi;
+
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
+ tvi.hItem = TreeView_GetRoot(hwndTree);
+ while(tvi.hItem) {
+ TreeView_GetItem(hwndTree, &tvi);
+ if(((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2))
+ flags |= tvi.lParam;
+ tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem);
+ }
+ return(flags);
+}
+
+/*
+ * load current values into the given profile
+ */
+
+void DSP_LoadFromDefaults(TDisplayProfile *p)
+{
+ int i;
+ DBVARIANT dbv = {0};
+ char szKey[5];
+
+ if (0 == p)
+ return;
+
+ p->dwExtraImageMask = cfg::dat.dwExtraImageMask;
+ p->exIconScale = cfg::dat.exIconScale;
+ p->bCenterStatusIcons = cfg::dat.bCenterStatusIcons;
+ p->dwFlags = cfg::dat.dwFlags;
+ p->bDimIdle = cfg::getByte("CLC", "ShowIdle", CLCDEFAULT_SHOWIDLE);
+ p->avatarBorder = cfg::dat.avatarBorder;
+ p->avatarSize = cfg::dat.avatarSize;
+ p->dualRowMode = cfg::dat.dualRowMode;
+ p->bNoOfflineAvatars = cfg::dat.bNoOfflineAvatars;
+ p->bShowLocalTime = cfg::dat.bShowLocalTime;
+ p->bShowLocalTimeSelective = cfg::dat.bShowLocalTimeSelective;
+ p->clcExStyle = cfg::getDword("CLC", "ExStyle", pcli->pfnGetDefaultExStyle());
+ p->clcOfflineModes = cfg::getDword("CLC", "OfflineModes", CLCDEFAULT_OFFLINEMODES);
+ p->bDontSeparateOffline = cfg::dat.bDontSeparateOffline;
+ p->sortOrder[0] = cfg::dat.sortOrder[0];
+ p->sortOrder[1] = cfg::dat.sortOrder[1];
+ p->sortOrder[2] = cfg::dat.sortOrder[2];
+ p->bUseDCMirroring = cfg::dat.bUseDCMirroring;
+ p->bCenterGroupNames = cfg::getByte("CLCExt", "EXBK_CenterGroupnames", 0);
+ p->bGroupAlign = cfg::dat.bGroupAlign;
+ p->avatarPadding = cfg::dat.avatarPadding;
+
+ p->bLeftMargin = cfg::getByte("CLC", "LeftMargin", CLCDEFAULT_LEFTMARGIN);
+ p->bRightMargin = cfg::getByte("CLC", "RightMargin", CLCDEFAULT_LEFTMARGIN);
+ p->bRowSpacing = cfg::dat.bRowSpacing;
+ p->bGroupIndent = cfg::getByte("CLC", "GroupIndent", CLCDEFAULT_GROUPINDENT);
+ p->bRowHeight = cfg::getByte("CLC", "RowHeight", CLCDEFAULT_ROWHEIGHT);
+ p->bGroupRowHeight = cfg::getByte("CLC", "GRowHeight", CLCDEFAULT_ROWHEIGHT);
+ CopyMemory(p->exIconOrder, cfg::dat.exIconOrder, EXICON_COUNT);
+
+ for(i = 0; i < NR_DSPOVERRIDES; i++) {
+ mir_snprintf(szKey, 3, "%d", i);
+ ZeroMemory(&p->dspOverride[i], sizeof(TDspOverride));
+ if(0 == db_get(0, DSP_PROFILES_MODULE, szKey, &dbv)) {
+ if(dbv.type == DBVT_BLOB && dbv.cpbVal > 0 && dbv.cpbVal <= sizeof(TDspOverride))
+ CopyMemory((void *)&p->dspOverride[i], (void *)dbv.pbVal, dbv.cpbVal);
+ db_free(&dbv);
+ }
+ }
+}
+
+/*
+ * apply a display profile
+ */
+
+void DSP_Apply(TDisplayProfile *p)
+{
+ int oldexIconScale = cfg::dat.exIconScale;
+ int i;
+ DWORD exStyle;
+ char temp[EXICON_COUNT + 1], szKey[5];
+ /*
+ * icons page
+ */
+ cfg::dat.dwFlags &= ~(CLUI_FRAME_STATUSICONS | CLUI_SHOWVISI | CLUI_FRAME_OVERLAYICONS | CLUI_FRAME_SELECTIVEICONS);
+ cfg::dat.dwExtraImageMask = p->dwExtraImageMask;
+ cfg::dat.exIconScale = p->exIconScale;
+ cfg::dat.bCenterStatusIcons = p->bCenterStatusIcons;
+
+ cfg::writeDword("CLUI", "ximgmask", cfg::dat.dwExtraImageMask);
+ cfg::writeByte("CLC", "ExIconScale", (BYTE)cfg::dat.exIconScale);
+ cfg::writeByte("CLC", "si_centered", (BYTE)cfg::dat.bCenterStatusIcons);
+ cfg::writeByte("CLC", "ShowIdle", (BYTE)p->bDimIdle);
+
+ CopyMemory(cfg::dat.exIconOrder, p->exIconOrder, EXICON_COUNT);
+ CopyMemory(temp, p->exIconOrder, EXICON_COUNT);
+ temp[EXICON_COUNT] = 0;
+ cfg::writeString(NULL, "CLUI", "exIconOrder", temp);
+
+ /*
+ * advanced (avatars & 2nd row)
+ */
+
+ cfg::dat.dwFlags &= ~(CLUI_FRAME_AVATARSLEFT | CLUI_FRAME_AVATARSRIGHT | CLUI_FRAME_AVATARSRIGHTWITHNICK |
+ CLUI_FRAME_AVATARS |
+ CLUI_FRAME_ALWAYSALIGNNICK | CLUI_FRAME_SHOWSTATUSMSG | CLUI_FRAME_AVATARBORDER);
+
+ cfg::dat.avatarSize = p->avatarSize;
+ cfg::dat.avatarBorder = p->avatarBorder;
+ cfg::dat.dualRowMode = p->dualRowMode;
+ cfg::dat.bNoOfflineAvatars = p->bNoOfflineAvatars;
+ cfg::dat.bShowLocalTime = p->bShowLocalTime;
+ cfg::dat.bShowLocalTimeSelective = p->bShowLocalTimeSelective;
+
+ if(cfg::dat.hBrushAvatarBorder)
+ DeleteObject(cfg::dat.hBrushAvatarBorder);
+ cfg::dat.hBrushAvatarBorder = CreateSolidBrush(cfg::dat.avatarBorder);
+
+ /*
+ * items page
+ */
+
+ cfg::dat.dwFlags &= ~CLUI_STICKYEVENTS;
+
+ cfg::dat.sortOrder[0] = p->sortOrder[0];
+ cfg::dat.sortOrder[1] = p->sortOrder[1];
+ cfg::dat.sortOrder[2] = p->sortOrder[2];
+ cfg::dat.bDontSeparateOffline = p->bDontSeparateOffline;
+ cfg::writeByte("CList", "DontSeparateOffline", (BYTE)cfg::dat.bDontSeparateOffline);
+ cfg::writeDword("CLC", "OfflineModes", p->clcOfflineModes);
+
+ cfg::writeDword("CList", "SortOrder",
+ MAKELONG(MAKEWORD(cfg::dat.sortOrder[0], cfg::dat.sortOrder[1]),
+ MAKEWORD(cfg::dat.sortOrder[2], 0)));
+
+ cfg::dat.bUseDCMirroring = p->bUseDCMirroring;
+ cfg::writeByte("CLC", "MirrorDC", cfg::dat.bUseDCMirroring);
+
+ /*
+ * groups page
+ */
+
+ cfg::dat.dwFlags &= ~CLUI_FRAME_NOGROUPICON;
+ cfg::dat.bGroupAlign = p->bGroupAlign;
+ cfg::writeByte("CLC", "GroupAlign", cfg::dat.bGroupAlign);
+ cfg::writeByte("CLCExt", "EXBK_CenterGroupnames", (BYTE)p->bCenterGroupNames);
+
+ exStyle = cfg::getDword("CLC", "ExStyle", pcli->pfnGetDefaultExStyle());
+ for(i = 0; i < sizeof(checkBoxToGroupStyleEx) / sizeof(checkBoxToGroupStyleEx[0]); i++)
+ exStyle &= ~(checkBoxToGroupStyleEx[i].flag);
+
+ exStyle |= p->clcExStyle;
+ cfg::writeDword("CLC", "ExStyle", exStyle);
+ cfg::dat.avatarPadding = p->avatarPadding;
+ cfg::writeByte("CList", "AvatarPadding", cfg::dat.avatarPadding);
+
+ cfg::dat.bRowSpacing = p->bRowSpacing;
+ cfg::writeByte("CLC", "RowGap", cfg::dat.bRowSpacing);
+
+ cfg::writeByte("CLC", "LeftMargin", (BYTE)p->bLeftMargin);
+ cfg::writeByte("CLC", "RightMargin", (BYTE)p->bRightMargin);
+ cfg::writeByte("CLC", "GroupIndent", (BYTE)p->bGroupIndent);
+ cfg::writeByte("CLC", "RowHeight", (BYTE)p->bRowHeight);
+ cfg::writeByte("CLC", "GRowHeight", (BYTE)p->bGroupRowHeight);
+
+ if(cfg::dat.sortOrder[0] == SORTBY_LASTMSG || cfg::dat.sortOrder[1] == SORTBY_LASTMSG || cfg::dat.sortOrder[2] == SORTBY_LASTMSG) {
+ int i;
+
+ for(i = 0; i < cfg::nextCacheEntry; i++)
+ cfg::eCache[i].dwLastMsgTime = INTSORT_GetLastMsgTime(cfg::eCache[i].hContact);
+ }
+
+ cfg::writeByte("CLC", "ShowLocalTime", (BYTE)cfg::dat.bShowLocalTime);
+ cfg::writeByte("CLC", "SelectiveLocalTime", (BYTE)cfg::dat.bShowLocalTimeSelective);
+ cfg::writeDword("CLC", "avatarborder", cfg::dat.avatarBorder);
+ cfg::writeWord(NULL, "CList", "AvatarSize", (WORD)cfg::dat.avatarSize);
+ cfg::writeByte("CLC", "DualRowMode", cfg::dat.dualRowMode);
+ cfg::writeByte("CList", "NoOfflineAV", (BYTE)cfg::dat.bNoOfflineAvatars);
+
+ KillTimer(pcli->hwndContactTree, TIMERID_REFRESH);
+ if(cfg::dat.bShowLocalTime)
+ SetTimer(pcli->hwndContactTree, TIMERID_REFRESH, 65000, NULL);
+
+ cfg::dat.dwFlags |= p->dwFlags;
+ cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags);
+
+ for(i = 0; i < cfg::nextCacheEntry; i++)
+ cfg::eCache[i].dwXMask = CalcXMask(cfg::eCache[i].hContact);
+
+ if(oldexIconScale != cfg::dat.exIconScale) {
+ ImageList_RemoveAll(CLUI::hExtraImages);
+ ImageList_SetIconSize(CLUI::hExtraImages, cfg::dat.exIconScale, cfg::dat.exIconScale);
+ IcoLibReloadIcons();
+ }
+ pcli->pfnClcOptionsChanged();
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+
+ for(i = 0; i < NR_DSPOVERRIDES; i++) {
+ mir_snprintf(szKey, 3, "%d", i);
+ db_set_blob(0, DSP_PROFILES_MODULE, szKey, (void *)&p->dspOverride[i], sizeof(TDspOverride));
+ }
+
+ CopyMemory(&CLC::dsp_default, p, sizeof(TDisplayProfile));
+}
+
+void GetDefaultFontSetting(int i, LOGFONTW *lf, COLORREF *colour)
+{
+ SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), lf, FALSE);
+ *colour = GetSysColor(COLOR_WINDOWTEXT);
+ switch(i) {
+ case FONTID_GROUPS:
+ lf->lfWeight = FW_BOLD;
+ break;
+ case FONTID_GROUPCOUNTS:
+ lf->lfHeight = (int)(lf->lfHeight * .75);
+ *colour = GetSysColor(COLOR_3DSHADOW);
+ break;
+ case FONTID_OFFINVIS:
+ case FONTID_INVIS:
+ lf->lfItalic = !lf->lfItalic;
+ break;
+ case FONTID_DIVIDERS:
+ lf->lfHeight = (int)(lf->lfHeight * .75);
+ break;
+ case FONTID_NOTONLIST:
+ *colour = GetSysColor(COLOR_3DSHADOW);
+ break;
+ }
+}
+
+INT_PTR CALLBACK cfg::DlgProcDspGroups(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ TranslateDialogDefault(hwndDlg);
+ SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always Left"));
+ SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always Right"));
+ SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Automatic (RTL)"));
+ return(TRUE);
+ }
+ case WM_COMMAND:
+ if((LOWORD(wParam) == IDC_ROWHEIGHT || LOWORD(wParam) == IDC_AVATARPADDING || LOWORD(wParam) == IDC_ROWGAP || LOWORD(wParam) == IDC_RIGHTMARGIN || LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_SMOOTHTIME || LOWORD(wParam) == IDC_GROUPINDENT || LOWORD(wParam) == IDC_GROUPROWHEIGHT)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()))
+ return(0);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_USER + 100: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ DWORD exStyle = p->clcExStyle;
+ int i;
+ for(i = 0; i < sizeof(checkBoxToGroupStyleEx) / sizeof(checkBoxToGroupStyleEx[0]); i++)
+ CheckDlgButton(hwndDlg, checkBoxToGroupStyleEx[i].id, (exStyle & checkBoxToGroupStyleEx[i].flag) ^(checkBoxToGroupStyleEx[i].flag * checkBoxToGroupStyleEx[i].not_t) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_NOGROUPICON, (p->dwFlags & CLUI_FRAME_NOGROUPICON) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CENTERGROUPNAMES, p->bCenterGroupNames);
+ SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_SETCURSEL, p->bGroupAlign, 0);
+ SendDlgItemMessage(hwndDlg, IDC_AVATARPADDINGSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0));
+ SendDlgItemMessage(hwndDlg, IDC_AVATARPADDINGSPIN, UDM_SETPOS, 0, p->avatarPadding);
+
+ SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETRANGE, 0, MAKELONG(64, 0));
+ SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, p->bLeftMargin);
+ SendDlgItemMessage(hwndDlg, IDC_RIGHTMARGINSPIN, UDM_SETRANGE, 0, MAKELONG(64, 0));
+ SendDlgItemMessage(hwndDlg, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, p->bRightMargin);
+ SendDlgItemMessage(hwndDlg, IDC_ROWGAPSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0));
+ SendDlgItemMessage(hwndDlg, IDC_ROWGAPSPIN, UDM_SETPOS, 0, p->bRowSpacing);
+ SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETRANGE, 0, MAKELONG(50, 0));
+ SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETPOS, 0, p->bGroupIndent);
+ SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, 8));
+ SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETPOS, 0, p->bRowHeight);
+ SendDlgItemMessage(hwndDlg, IDC_GROUPROWHEIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, 8));
+ SendDlgItemMessage(hwndDlg, IDC_GROUPROWHEIGHTSPIN, UDM_SETPOS, 0, p->bGroupRowHeight);
+ }
+ return(0);
+ }
+ case WM_USER + 200: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ int i;
+ DWORD exStyle = 0;
+ LRESULT curSel;
+ BOOL translated;
+
+ for(i = 0; i < sizeof(checkBoxToGroupStyleEx) / sizeof(checkBoxToGroupStyleEx[0]); i++) {
+ if((IsDlgButtonChecked(hwndDlg, checkBoxToGroupStyleEx[i].id) == 0) == checkBoxToGroupStyleEx[i].not_t)
+ exStyle |= checkBoxToGroupStyleEx[i].flag;
+ }
+ p->clcExStyle = exStyle;
+ p->dwFlags |= (IsDlgButtonChecked(hwndDlg, IDC_NOGROUPICON) ? CLUI_FRAME_NOGROUPICON : 0);
+ p->bCenterGroupNames = IsDlgButtonChecked(hwndDlg, IDC_CENTERGROUPNAMES) ? 1 : 0;
+ curSel = SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_GETCURSEL, 0, 0);
+ if(curSel != CB_ERR)
+ p->bGroupAlign = (BYTE)curSel;
+
+ p->avatarPadding = (BYTE)GetDlgItemInt(hwndDlg, IDC_AVATARPADDING, &translated, FALSE);
+ p->bLeftMargin = (BYTE)SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_GETPOS, 0, 0);
+ p->bRightMargin = (BYTE)SendDlgItemMessage(hwndDlg, IDC_RIGHTMARGINSPIN, UDM_GETPOS, 0, 0);
+ p->bRowSpacing = (BYTE)SendDlgItemMessage(hwndDlg, IDC_ROWGAPSPIN, UDM_GETPOS, 0, 0);
+ p->bGroupIndent = (BYTE)SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_GETPOS, 0, 0);
+ p->bRowHeight = (BYTE)SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_GETPOS, 0, 0);
+ p->bGroupRowHeight = (BYTE)SendDlgItemMessage(hwndDlg, IDC_GROUPROWHEIGHTSPIN, UDM_GETPOS, 0, 0);
+ }
+ return(0);
+ }
+ case WM_NOTIFY:
+ switch(((LPNMHDR) lParam)->idFrom) {
+ case 0:
+ switch(((LPNMHDR) lParam)->code) {
+ case PSN_APPLY: {
+ return(TRUE);
+ }
+ }
+ break;
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+INT_PTR CALLBACK cfg::DlgProcDspItems(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ int i = 0;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), GWL_STYLE,
+ GetWindowLong(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES);
+
+ for(i = 0; sortCtrlIDs[i] != 0; i++) {
+ SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Nothing"));
+ SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Name"));
+ SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Protocol"));
+ SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Status"));
+ SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Last Message"));
+ SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Message Frequency"));
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Never"));
+ SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always"));
+ SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("For RTL only"));
+ SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("RTL TEXT only"));
+ return(TRUE);
+ }
+ case WM_COMMAND:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_USER + 100: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ int i;
+ FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), offlineValues, sizeof(offlineValues) / sizeof(offlineValues[0]), p->clcOfflineModes);
+ CheckDlgButton(hwndDlg, IDC_EVENTSONTOP, (p->dwFlags & CLUI_STICKYEVENTS) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DONTSEPARATE, p->bDontSeparateOffline);
+ for(i = 0; sortCtrlIDs[i] != 0; i++)
+ SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_SETCURSEL, p->sortOrder[i], 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_SETCURSEL, p->bUseDCMirroring, 0);
+ }
+ return(0);
+ }
+ case WM_USER + 200: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ int i;
+ LRESULT curSel;
+
+ for(i = 0; sortCtrlIDs[i] != 0; i++) {
+ curSel = SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_GETCURSEL, 0, 0);
+ if(curSel == 0 || curSel == CB_ERR)
+ p->sortOrder[i] = 0;
+ else
+ p->sortOrder[i] = (BYTE)curSel;
+ }
+ p->bDontSeparateOffline = IsDlgButtonChecked(hwndDlg, IDC_DONTSEPARATE) ? 1 : 0;
+ p->dwFlags |= IsDlgButtonChecked(hwndDlg, IDC_EVENTSONTOP) ? CLUI_STICKYEVENTS : 0;
+ p->clcOfflineModes = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS));
+ p->bUseDCMirroring = (BYTE)SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_GETCURSEL, 0, 0);
+ }
+ return(0);
+ }
+ case WM_NOTIFY:
+ switch(((LPNMHDR) lParam)->idFrom) {
+ case IDC_HIDEOFFLINEOPTS:
+ if(((LPNMHDR) lParam)->code == NM_CLICK) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short) LOWORD(GetMessagePos());
+ hti.pt.y = (short) HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR) lParam)->hwndFrom, &hti.pt);
+ if(TreeView_HitTest(((LPNMHDR) lParam)->hwndFrom, &hti))
+ if(hti.flags & TVHT_ONITEMSTATEICON) {
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1;
+ TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ case 0:
+ switch(((LPNMHDR) lParam)->code) {
+ case PSN_APPLY: {
+ return(TRUE);
+ }
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY: {
+ ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), TVSIL_STATE));
+ break;
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+static UINT avatar_controls[] = { IDC_ALIGNMENT, IDC_AVATARSBORDER, IDC_AVATARBORDERCLR, IDC_ALWAYSALIGNNICK, IDC_AVATARHEIGHT, IDC_AVATARSIZESPIN, 0};
+
+INT_PTR CALLBACK cfg::DlgProcDspClasses(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_INSERTSTRING, -1, (LPARAM)TranslateW(L"Offline contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_INSERTSTRING, -1, (LPARAM)TranslateW(L"Online contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_INSERTSTRING, -1, (LPARAM)TranslateW(L"Selected contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_INSERTSTRING, -1, (LPARAM)TranslateW(L"Hovered contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_INSERTSTRING, -1, (LPARAM)TranslateW(L"Priority contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_SETCURSEL, 0, 0);
+ break;
+
+ /*
+ * sent from the tab parent to init settings
+ */
+ case WM_USER + 100: {
+ TDisplayProfile* p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, reinterpret_cast<INT_PTR>(p));
+ SendMessage(hwndDlg, WM_USER + 300, 0, 0);
+
+ CheckDlgButton(hwndDlg, IDC_DSPCLASS_ENABLE_SELECTED, p->dspOverride[DSP_OVR_SELECTED].fActive ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DSPCLASS_ENABLE_HOVERED, p->dspOverride[DSP_OVR_HOVERED].fActive ? BST_CHECKED : BST_UNCHECKED);
+ }
+ return(0);
+ }
+
+ /*
+ * sent from the tab parent to collect settings
+ */
+ case WM_USER + 200: {
+ TDisplayProfile* pNew = reinterpret_cast<TDisplayProfile *>(lParam);
+ TDisplayProfile* p = reinterpret_cast<TDisplayProfile *>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
+ CopyMemory(&pNew->dspOverride[0], &p->dspOverride[0], sizeof(TDspOverride) * NR_DSPOVERRIDES);
+ return(0);
+ }
+
+ /*
+ * internal - init settings based on the selected override identifier
+ * (stored in IDC_DSPCLASS)
+ */
+ case WM_USER + 300: {
+ TDisplayProfile* p = reinterpret_cast<TDisplayProfile *>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
+ if(p) {
+ LRESULT uIndex = SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_GETCURSEL, 0, 0);
+ if(uIndex >= 0 && uIndex < NR_DSPOVERRIDES) {
+ TDspOverride* o = &p->dspOverride[uIndex];
+ CheckDlgButton(hwndDlg, IDC_DSPCLASS_AVATAR, o->bAvatar == 0 ? BST_INDETERMINATE : (o->bAvatar == 1 ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_DSPCLASS_SECONDLINE, o->bSecondLine == 0 ? BST_INDETERMINATE : (o->bSecondLine == 1 ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_DSPCLASS_ICON, o->bIcon == 0 ? BST_INDETERMINATE : (o->bIcon == 1 ? BST_CHECKED : BST_UNCHECKED));
+ }
+ }
+ return(0);
+ }
+
+ case WM_COMMAND: {
+ if(IDC_DSPCLASS == LOWORD(wParam) && CBN_SELCHANGE == HIWORD(wParam)) {
+ SendMessage(hwndDlg, WM_USER + 300, 0, 0);
+ break;
+ }
+ switch(LOWORD(wParam)) {
+ case IDC_DSPCLASS_AVATAR:
+ case IDC_DSPCLASS_ICON:
+ case IDC_DSPCLASS_SECONDLINE:
+ case IDC_DSPCLASS_ENABLE_SELECTED:
+ case IDC_DSPCLASS_ENABLE_HOVERED: {
+ TDisplayProfile* p = reinterpret_cast<TDisplayProfile *>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
+ if(p) {
+ LRESULT uIndex = SendDlgItemMessage(hwndDlg, IDC_DSPCLASS, CB_GETCURSEL, 0, 0);
+ if(uIndex >= 0 && uIndex < NR_DSPOVERRIDES) {
+ LRESULT r;
+ TDspOverride* o = &p->dspOverride[uIndex];
+ r = IsDlgButtonChecked(hwndDlg, IDC_DSPCLASS_AVATAR);
+ o->bAvatar = (r == BST_INDETERMINATE ? 0 : (r == BST_CHECKED ? 1 : -1));
+ r = IsDlgButtonChecked(hwndDlg, IDC_DSPCLASS_ICON);
+ o->bIcon = (r == BST_INDETERMINATE ? 0 : (r == BST_CHECKED ? 1 : -1));
+ r = IsDlgButtonChecked(hwndDlg, IDC_DSPCLASS_SECONDLINE);
+ o->bSecondLine = (r == BST_INDETERMINATE ? 0 : (r == BST_CHECKED ? 1 : -1));
+ }
+ p->dspOverride[DSP_OVR_HOVERED].fActive = (IsDlgButtonChecked(hwndDlg, IDC_DSPCLASS_ENABLE_HOVERED) ? true : false);
+ p->dspOverride[DSP_OVR_SELECTED].fActive = (IsDlgButtonChecked(hwndDlg, IDC_DSPCLASS_ENABLE_SELECTED) ? true : false);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ default:
+ break;
+ }
+ return(FALSE);
+}
+
+INT_PTR CALLBACK cfg::DlgProcDspAdvanced(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ int i = 0;
+
+ TranslateDialogDefault(hwndDlg);
+ SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Never"));
+ SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always"));
+ SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("When needed"));
+
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("With Nickname - left"));
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Far left"));
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Far right"));
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("With Nickname - right"));
+
+ Utils::enableDlgControl(hwndDlg, IDC_CLISTAVATARS, TRUE);
+ while(avatar_controls[i] != 0)
+ Utils::enableDlgControl(hwndDlg, avatar_controls[i++], TRUE);
+ return(TRUE);
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_CLISTAVATARS:
+ if((HWND)lParam != GetFocus())
+ return(0);
+ break;
+ case IDC_SHOWLOCALTIME:
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT, IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIME));
+ break;
+ case IDC_AVATARSBORDER:
+ Utils::enableDlgControl(hwndDlg, IDC_AVATARBORDERCLR, IsDlgButtonChecked(hwndDlg, IDC_AVATARSBORDER) ? TRUE : FALSE);
+ break;
+ }
+ if((LOWORD(wParam) == IDC_AVATARHEIGHT) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()))
+ return(0);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_USER + 100: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ CheckDlgButton(hwndDlg, IDC_NOAVATARSOFFLINE, p->bNoOfflineAvatars);
+ SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_SETCURSEL, (WPARAM)p->dualRowMode, 0);
+ CheckDlgButton(hwndDlg, IDC_CLISTAVATARS, (p->dwFlags & CLUI_FRAME_AVATARS) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_AVATARSBORDER, (p->dwFlags & CLUI_FRAME_AVATARBORDER) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ALWAYSALIGNNICK, (p->dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWSTATUSMSG, (p->dwFlags & CLUI_FRAME_SHOWSTATUSMSG) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg, IDC_AVATARBORDERCLR, CPM_SETCOLOUR, 0, p->avatarBorder);
+
+ SendDlgItemMessage(hwndDlg, IDC_AVATARSIZESPIN, UDM_SETRANGE, 0, MAKELONG(100, 16));
+ SendDlgItemMessage(hwndDlg, IDC_AVATARSIZESPIN, UDM_SETPOS, 0, p->avatarSize);
+
+ Utils::enableDlgControl(hwndDlg, IDC_AVATARBORDERCLR, IsDlgButtonChecked(hwndDlg, IDC_AVATARSBORDER) ? TRUE : FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_SHOWLOCALTIME, p->bShowLocalTime ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT, p->bShowLocalTimeSelective ? 1 : 0);
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT, IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIME));
+
+ if(p->dwFlags & CLUI_FRAME_AVATARSLEFT)
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 1, 0);
+ else if(p->dwFlags & CLUI_FRAME_AVATARSRIGHT)
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 2, 0);
+ else if(p->dwFlags & CLUI_FRAME_AVATARSRIGHTWITHNICK)
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 3, 0);
+ else
+ SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 0, 0);
+ }
+ return(0);
+ }
+ case WM_USER + 200: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ LRESULT sel = SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_GETCURSEL, 0, 0);
+ BOOL translated;
+
+ if(sel != CB_ERR) {
+ if(sel == 1)
+ p->dwFlags |= CLUI_FRAME_AVATARSLEFT;
+ else if(sel == 2)
+ p->dwFlags |= CLUI_FRAME_AVATARSRIGHT;
+ else if(sel == 3)
+ p->dwFlags |= CLUI_FRAME_AVATARSRIGHTWITHNICK;
+ }
+
+ p->dwFlags |= ((IsDlgButtonChecked(hwndDlg, IDC_CLISTAVATARS) ? CLUI_FRAME_AVATARS : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_AVATARSBORDER) ? CLUI_FRAME_AVATARBORDER : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_ALWAYSALIGNNICK) ? CLUI_FRAME_ALWAYSALIGNNICK : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSMSG) ? CLUI_FRAME_SHOWSTATUSMSG : 0));
+
+ p->avatarBorder = SendDlgItemMessage(hwndDlg, IDC_AVATARBORDERCLR, CPM_GETCOLOUR, 0, 0);
+ p->avatarSize = GetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, &translated, FALSE);
+ p->bNoOfflineAvatars = IsDlgButtonChecked(hwndDlg, IDC_NOAVATARSOFFLINE) ? TRUE : FALSE;
+ p->bShowLocalTime = IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIME) ? 1 : 0;
+ p->bShowLocalTimeSelective = IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT) ? 1 : 0;
+
+ p->dualRowMode = (BYTE)SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_GETCURSEL, 0, 0);
+ if(p->dualRowMode == CB_ERR)
+ p->dualRowMode = 0;
+ }
+ return(0);
+ }
+ case WM_NOTIFY:
+ switch(((LPNMHDR) lParam)->code) {
+ case PSN_APPLY: {
+ return(TRUE);
+ }
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+ORDERTREEDATA OrderTreeData[] = {
+ {EXTRA_ICON_RES0, _T("Reserved, unused"), 9, TRUE, 0},
+ {EXTRA_ICON_EMAIL, _T("E-mail"), 0, TRUE, 0},
+ {EXTRA_ICON_RES1, _T("Reserved #1"), 7, TRUE, 0},
+ {EXTRA_ICON_SMS, _T("Telephone"), 2, TRUE, 0},
+ {EXTRA_ICON_ADV1, _T("Advanced #1 (X-Status)"), 3, TRUE, 0},
+ {EXTRA_ICON_ADV2, _T("Advanced #2"), 4, TRUE, 0},
+ {EXTRA_ICON_WEB, _T("Homepage"), 1, TRUE, 0},
+ {EXTRA_ICON_CLIENT, _T("Client (fingerprint required)"), 10, TRUE, 0},
+ {EXTRA_ICON_RES2, _T("Reserved #2"), 8, TRUE, 0},
+ {EXTRA_ICON_ADV3, _T("Advanced #3"), 5, TRUE, 0},
+ {EXTRA_ICON_ADV4, _T("Advanced #4"), 6, TRUE, 0},
+};
+
+static int dragging = 0;
+static HTREEITEM hDragItem = NULL;
+
+static int FillOrderTree(HWND hwndDlg, HWND hwndTree, TDisplayProfile *p)
+{
+ int i = 0;
+ TVINSERTSTRUCT tvis = {0};
+ TreeView_DeleteAllItems(hwndTree);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE;
+
+ for(i = 0; i < EXICON_COUNT; i++) {
+ int iIndex = (int)(p->exIconOrder[i] - 1);
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.lParam = (LPARAM)(&(OrderTreeData[iIndex]));
+ tvis.item.pszText = TranslateTS(OrderTreeData[iIndex].Name);
+ OrderTreeData[iIndex].Visible = (p->dwExtraImageMask & (1 << OrderTreeData[iIndex].ID)) ? TRUE : FALSE;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK(OrderTreeData[iIndex].Visible ? 1 : 2);
+ TreeView_InsertItem(hwndTree, &tvis);
+ }
+ return(0);
+}
+
+static int SaveOrderTree(HWND hwndDlg, HWND hwndTree, TDisplayProfile *p)
+{
+ HTREEITEM ht;
+ TVITEM tvi = {0};
+ int iIndex = 0;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM;
+ ht = TreeView_GetRoot(hwndTree);
+
+ p->dwExtraImageMask = 0;
+
+ do {
+ ORDERTREEDATA *it = NULL;
+ tvi.hItem = ht;
+ TreeView_GetItem(hwndTree, &tvi);
+ it = (ORDERTREEDATA *)(tvi.lParam);
+
+ p->exIconOrder[iIndex] = it->ID + 1;
+ p->dwExtraImageMask |= (it->Visible ? (1 << it->ID) : 0);
+ ht = TreeView_GetNextSibling(hwndTree, ht);
+ iIndex++;
+ } while(ht);
+ return(0);
+}
+
+INT_PTR CALLBACK cfg::DlgProcXIcons(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EXTRAORDER), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EXTRAORDER), GWL_STYLE) | (TVS_NOHSCROLL | TVS_CHECKBOXES));
+
+ HIMAGELIST himlOptions = (HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC_EXTRAORDER, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)CreateStateImageList());
+ ImageList_Destroy(himlOptions);
+ return(TRUE);
+ }
+ case WM_COMMAND:
+ if((LOWORD(wParam) == IDC_EXICONSCALE) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()))
+ return(0);
+
+ if(IDC_RESETXICONS == LOWORD(wParam)) {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
+ if(p) {
+ for(int i = 0; i < EXICON_COUNT; i++) {
+ OrderTreeData[i].Visible = TRUE;
+ p->exIconOrder[i] = i + 1;
+ }
+ p->dwExtraImageMask = 0xffffffff;
+ FillOrderTree(hwndDlg, GetDlgItem(hwndDlg, IDC_EXTRAORDER), p);
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_USER + 100: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (INT_PTR)p);
+ CheckDlgButton(hwndDlg, IDC_SHOWSTATUSICONS, (p->dwFlags & CLUI_FRAME_STATUSICONS) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWVISIBILITY, (p->dwFlags & CLUI_SHOWVISI) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_OVERLAYICONS, (p->dwFlags & CLUI_FRAME_OVERLAYICONS) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SELECTIVEICONS, (p->dwFlags & CLUI_FRAME_SELECTIVEICONS) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_STATUSICONSCENTERED, p->bCenterStatusIcons ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_IDLE, p->bDimIdle ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg, IDC_EXICONSCALESPIN, UDM_SETRANGE, 0, MAKELONG(20, 8));
+ SendDlgItemMessage(hwndDlg, IDC_EXICONSCALESPIN, UDM_SETPOS, 0, (LPARAM)p->exIconScale);
+ FillOrderTree(hwndDlg, GetDlgItem(hwndDlg, IDC_EXTRAORDER), p);
+ }
+ return(0);
+ }
+ case WM_USER + 200: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ if(p) {
+ SaveOrderTree(hwndDlg, GetDlgItem(hwndDlg, IDC_EXTRAORDER), p);
+
+ p->exIconScale = SendDlgItemMessage(hwndDlg, IDC_EXICONSCALESPIN, UDM_GETPOS, 0, 0);
+ p->exIconScale = (p->exIconScale < 8 || p->exIconScale > 20) ? 16 : p->exIconScale;
+
+ p->dwFlags |= ((IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSICONS) ? CLUI_FRAME_STATUSICONS : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_SHOWVISIBILITY) ? CLUI_SHOWVISI : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_OVERLAYICONS) ? CLUI_FRAME_OVERLAYICONS : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_SELECTIVEICONS) ? CLUI_FRAME_SELECTIVEICONS : 0));
+
+ p->bDimIdle = IsDlgButtonChecked(hwndDlg, IDC_IDLE) ? 1 : 0;
+ p->bCenterStatusIcons = IsDlgButtonChecked(hwndDlg, IDC_STATUSICONSCENTERED) ? 1 : 0;
+ }
+ return(0);
+ }
+ case WM_NOTIFY:
+ if(((LPNMHDR) lParam)->idFrom == IDC_EXTRAORDER) {
+ switch(((LPNMHDR)lParam)->code) {
+ case TVN_BEGINDRAGA:
+ case TVN_BEGINDRAGW:
+ SetCapture(hwndDlg);
+ dragging = 1;
+ hDragItem = ((LPNMTREEVIEWA)lParam)->itemNew.hItem;
+ TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_EXTRAORDER), hDragItem);
+ break;
+ case NM_CLICK: {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR)lParam)->hwndFrom, &hti.pt);
+ if(TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom, &hti))
+ if(hti.flags & TVHT_ONITEMSTATEICON) {
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1;
+ ((ORDERTREEDATA *)tvi.lParam)->Visible = (tvi.iImage == 2 ? FALSE : TRUE);
+ if(((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2))
+ ((ORDERTREEDATA *)tvi.lParam)->Visible = TRUE;
+ else
+ ((ORDERTREEDATA *)tvi.lParam)->Visible = FALSE;
+ TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+
+ }
+ }
+ break;
+ }
+ switch(((LPNMHDR) lParam)->code) {
+ case PSN_APPLY: {
+ return(TRUE);
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE: {
+ if(!dragging)
+ break;
+ {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwndDlg, &hti.pt);
+ ScreenToClient(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &hti.pt);
+ TreeView_HitTest(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &hti);
+ if(hti.flags&(TVHT_ONITEM | TVHT_ONITEMRIGHT)) {
+ HTREEITEM it = hti.hItem;
+ hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg, IDC_EXTRAORDER)) / 2;
+ TreeView_HitTest(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &hti);
+ if(!(hti.flags & TVHT_ABOVE))
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_EXTRAORDER), hti.hItem, 1);
+ else
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_EXTRAORDER), it, 0);
+ } else {
+ if(hti.flags & TVHT_ABOVE) SendDlgItemMessage(hwndDlg, IDC_EXTRAORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
+ if(hti.flags & TVHT_BELOW) SendDlgItemMessage(hwndDlg, IDC_EXTRAORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_EXTRAORDER), NULL, 0);
+ }
+ }
+ }
+ break;
+ case WM_LBUTTONUP: {
+ if(!dragging) break;
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_EXTRAORDER), NULL, 0);
+ dragging = 0;
+ ReleaseCapture();
+ {
+ TVHITTESTINFO hti;
+ TVITEM tvi;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwndDlg, &hti.pt);
+ ScreenToClient(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &hti.pt);
+ hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg, IDC_EXTRAORDER)) / 2;
+ TreeView_HitTest(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &hti);
+ if(hDragItem == hti.hItem) break;
+ if(hti.flags & TVHT_ABOVE) hti.hItem = TVI_FIRST;
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM;
+ tvi.hItem = hDragItem;
+ TreeView_GetItem(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &tvi);
+ if(hti.flags&(TVHT_ONITEM | TVHT_ONITEMRIGHT) || (hti.hItem == TVI_FIRST)) {
+ TVINSERTSTRUCT tvis;
+ wchar_t name[128];
+ tvis.item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvis.item.stateMask = 0xFFFFFFFF;
+ tvis.item.pszText = name;
+ tvis.item.cchTextMax = sizeof(name);
+ tvis.item.hItem = hDragItem;
+ tvis.item.iImage = tvis.item.iSelectedImage = ((ORDERTREEDATA *)tvi.lParam)->Visible;
+ TreeView_GetItem(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &tvis.item);
+ TreeView_DeleteItem(GetDlgItem(hwndDlg, IDC_EXTRAORDER), hDragItem);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = hti.hItem;
+ TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_EXTRAORDER), TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &tvis));
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ }
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+static TDisplayProfile dsp_current;
+
+INT_PTR CALLBACK cfg::DlgProcDspProfiles(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int iInit = TRUE;
+ static HWND hwndTab;
+ static int iTabCount;
+
+ switch(msg) {
+ case WM_INITDIALOG: {
+ TCITEM tci;
+ RECT rcClient;
+ int oPage = cfg::getByte("CLUI", "opage_d", 0);
+
+ TranslateDialogDefault(hwnd);
+
+ GetClientRect(hwnd, &rcClient);
+ hwndTab = GetDlgItem(hwnd, IDC_OPTIONSTAB);
+ iInit = TRUE;
+ tci.mask = TCIF_PARAM | TCIF_TEXT;
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_DSPITEMS), hwnd, DlgProcDspItems);
+ tci.pszText = TranslateT("Contacts");
+ TabCtrl_InsertItem(hwndTab, 0, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 0 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_DSPGROUPS), hwnd, DlgProcDspGroups);
+ tci.pszText = TranslateT("Groups and layout");
+ TabCtrl_InsertItem(hwndTab, 1, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 1 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_XICONS), hwnd, DlgProcXIcons);
+ tci.pszText = TranslateT("Icons");
+ TabCtrl_InsertItem(hwndTab, 2, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 2 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_DSPADVANCED), hwnd, DlgProcDspAdvanced);
+ tci.pszText = TranslateT("Advanced");
+ TabCtrl_InsertItem(hwndTab, 3, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 3 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_DSPCLASSES), hwnd, DlgProcDspClasses);
+ tci.pszText = TranslateT("Display classes");
+ TabCtrl_InsertItem(hwndTab, 4, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 4 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB), oPage);
+
+ DSP_LoadFromDefaults(&CLC::dsp_default);
+ CopyMemory(&dsp_current, &CLC::dsp_default, sizeof(TDisplayProfile));
+
+ iTabCount = TabCtrl_GetItemCount(hwndTab);
+
+ SendMessage(hwnd, WM_USER + 100, 0, (LPARAM)&CLC::dsp_default);
+
+ iInit = FALSE;
+ return(FALSE);
+ }
+
+ /*
+ * distribute a WM_USER message to all child windows so they can update their pages from the
+ * display profile structure
+ * LPARAM = DISPLAYPROFILE *
+ */
+
+ case WM_USER + 100: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+
+ if(p) {
+ int i;
+ TCITEM item = {0};
+ item.mask = TCIF_PARAM;
+
+ for(i = 0; i < iTabCount; i++) {
+ TabCtrl_GetItem(hwndTab, i, &item);
+ if(item.lParam && IsWindow((HWND)item.lParam))
+ SendMessage((HWND)item.lParam, WM_USER + 100, 0, (LPARAM)p);
+ }
+ }
+ return(0);
+ }
+
+ /*
+ * collect the settings from the pages into a DISPLAYPROFILE struct
+ */
+ case WM_USER + 200: {
+ TDisplayProfile *p = reinterpret_cast<TDisplayProfile *>(lParam);
+ int i;
+ TCITEM item = {0};
+ item.mask = TCIF_PARAM;
+
+ for(i = 0; i < iTabCount; i++) {
+ TabCtrl_GetItem(hwndTab, i, &item);
+ if(item.lParam && IsWindow((HWND)item.lParam))
+ SendMessage((HWND)item.lParam, WM_USER + 200, 0, (LPARAM)p);
+ }
+ return(0);
+ }
+
+ case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0);
+ if(!iInit)
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch(((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ TDisplayProfile p;
+
+ ZeroMemory(&p, sizeof(p));
+ SendMessage(hwnd, WM_USER + 200, 0, (LPARAM)&p);
+ DSP_Apply(&p);
+ }
+ break;
+ }
+ break;
+ case IDC_OPTIONSTAB:
+ switch(((LPNMHDR)lParam)->code) {
+ case TCN_SELCHANGING: {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+ }
+ break;
+ case TCN_SELCHANGE: {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)), &tci);
+ ShowWindow((HWND)tci.lParam, SW_SHOW);
+ cfg::writeByte("CLUI", "opage_d", (BYTE)TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)));
+ }
+ break;
+ }
+ break;
+
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+INT_PTR CALLBACK cfg::TabOptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int iInit = TRUE;
+
+ switch(msg) {
+ case WM_INITDIALOG: {
+ TCITEM tci;
+ RECT rcClient;
+ int oPage = cfg::getByte("CLUI", "opage_m", 0);
+
+ if(oPage > 3)
+ oPage = 0;
+
+ GetClientRect(hwnd, &rcClient);
+ iInit = TRUE;
+ tci.mask = TCIF_PARAM | TCIF_TEXT;
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_CLIST), hwnd, cfg::DlgProcGenOpts);
+ tci.pszText = TranslateT("General");
+ TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 0, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 0 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_CLC), hwnd, cfg::DlgProcClcMainOpts);
+ tci.pszText = TranslateT("List layout");
+ TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 1, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 1 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_CLUI), hwnd, cfg::DlgProcCluiOpts);
+ tci.pszText = TranslateT("Window");
+ TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 2, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 2 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ tci.lParam = (LPARAM)CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_OPT_SBAR), hwnd, cfg::DlgProcSBarOpts);
+ tci.pszText = TranslateT("Status Bar");
+ TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 3, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 30, 1);
+ ShowWindow((HWND)tci.lParam, oPage == 3 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB), oPage);
+ iInit = FALSE;
+ return(FALSE);
+ }
+
+ case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0);
+ if(!iInit)
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch(((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ TCITEM tci;
+ int i, count;
+ tci.mask = TCIF_PARAM;
+ count = TabCtrl_GetItemCount(GetDlgItem(hwnd, IDC_OPTIONSTAB));
+ for(i = 0; i < count; i++) {
+ TabCtrl_GetItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), i, &tci);
+ SendMessage((HWND)tci.lParam, WM_NOTIFY, 0, lParam);
+ }
+ }
+ break;
+ }
+ break;
+ case IDC_OPTIONSTAB:
+ switch(((LPNMHDR)lParam)->code) {
+ case TCN_SELCHANGING: {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+ }
+ break;
+ case TCN_SELCHANGE: {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)), &tci);
+ ShowWindow((HWND)tci.lParam, SW_SHOW);
+ cfg::writeByte("CLUI", "opage_m", (BYTE)TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)));
+ }
+ break;
+ }
+ break;
+
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+int ClcOptInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp, sizeof(odp));
+ //odp.cbSize = sizeof(odp);
+ odp.position = 0;
+ odp.hInstance = g_hInst;
+ odp.pszGroup = LPGEN("Contact List");
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_DSPPROFILES);
+ odp.pszTitle = LPGEN("Contact rows");
+ odp.pfnDlgProc = cfg::DlgProcDspProfiles;
+ odp.flags = ODPF_BOLDGROUPS;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FLOATING);
+ odp.pszTitle = LPGEN("Floating contacts");
+ odp.pfnDlgProc = cfg::DlgProcFloatingContacts;
+ odp.flags = ODPF_BOLDGROUPS;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT);
+ odp.pszGroup = LPGEN("Skins");
+ odp.pszTitle = LPGEN("Contact list skin");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = cfg::SkinOptionsDlgProc;
+ Options_AddPage(wParam, &odp);
+
+ odp.position = -1000000000;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONSDIALOG);
+ odp.pszGroup = NULL;
+ odp.pszTitle = LPGEN("Contact List");
+ odp.pfnDlgProc = cfg::TabOptionsDlgProc;
+ odp.flags = ODPF_BOLDGROUPS;
+ Options_AddPage(wParam, &odp);
+ return(0);
+}
+
+static int opt_clc_main_changed = 0;
+
+INT_PTR CALLBACK cfg::DlgProcClcMainOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ opt_clc_main_changed = 0;
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE, GetWindowLong(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES);
+
+ {
+ int i;
+ DWORD exStyle = cfg::getDword("CLC", "ExStyle", pcli->pfnGetDefaultExStyle());
+ UDACCEL accel[2] = {
+ {0, 10}, {2, 50}
+ };
+ SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETRANGE, 0, MAKELONG(999, 0));
+ SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETACCEL, sizeof(accel) / sizeof(accel[0]), (LPARAM) &accel);
+ SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CLC", "ScrollTime", CLCDEFAULT_SCROLLTIME), 0));
+
+ for(i = 0; i < sizeof(checkBoxToStyleEx) / sizeof(checkBoxToStyleEx[0]); i++)
+ CheckDlgButton(hwndDlg, checkBoxToStyleEx[i].id, (exStyle & checkBoxToStyleEx[i].flag) ^(checkBoxToStyleEx[i].flag * checkBoxToStyleEx[i].not_t) ? BST_CHECKED : BST_UNCHECKED);
+ }
+ CheckDlgButton(hwndDlg, IDC_FULLROWSELECT, (cfg::dat.dwFlags & CLUI_FULLROWSELECT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_DBLCLKAVATARS, cfg::dat.bDblClkAvatars);
+ CheckDlgButton(hwndDlg, IDC_GREYOUT, cfg::getDword("CLC", "GreyoutFlags", CLCDEFAULT_GREYOUTFLAGS) ? BST_CHECKED : BST_UNCHECKED);
+ Utils::enableDlgControl(hwndDlg, IDC_SMOOTHTIME, IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING));
+ Utils::enableDlgControl(hwndDlg, IDC_GREYOUTOPTS, IsDlgButtonChecked(hwndDlg, IDC_GREYOUT));
+ FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), greyoutValues, sizeof(greyoutValues) / sizeof(greyoutValues[0]), cfg::getDword("CLC", "FullGreyoutFlags", CLCDEFAULT_FULLGREYOUTFLAGS));
+ CheckDlgButton(hwndDlg, IDC_NOSCROLLBAR, cfg::getByte("CLC", "NoVScrollBar", 0) ? BST_CHECKED : BST_UNCHECKED);
+
+ return(TRUE);
+ case WM_VSCROLL:
+ opt_clc_main_changed = 1;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_COMMAND:
+ if(LOWORD(wParam) == IDC_NOTNOSMOOTHSCROLLING)
+ Utils::enableDlgControl(hwndDlg, IDC_SMOOTHTIME, IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING));
+ if(LOWORD(wParam) == IDC_GREYOUT)
+ Utils::enableDlgControl(hwndDlg, IDC_GREYOUTOPTS, IsDlgButtonChecked(hwndDlg, IDC_GREYOUT));
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ opt_clc_main_changed = 1;
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR) lParam)->idFrom) {
+ case IDC_GREYOUTOPTS:
+ if(((LPNMHDR) lParam)->code == NM_CLICK) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short) LOWORD(GetMessagePos());
+ hti.pt.y = (short) HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR) lParam)->hwndFrom, &hti.pt);
+ if(TreeView_HitTest(((LPNMHDR) lParam)->hwndFrom, &hti))
+ if(hti.flags & TVHT_ONITEMSTATEICON) {
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1;
+ TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ opt_clc_main_changed = 1;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ case 0:
+ switch(((LPNMHDR) lParam)->code) {
+ case PSN_APPLY: {
+ int i;
+ DWORD exStyle = cfg::getDword("CLC", "ExStyle", CLCDEFAULT_EXSTYLE);
+
+ if(!opt_clc_main_changed)
+ return(TRUE);
+
+ for(i = 0; i < sizeof(checkBoxToStyleEx) / sizeof(checkBoxToStyleEx[0]); i++)
+ exStyle &= ~(checkBoxToStyleEx[i].flag);
+
+ for(i = 0; i < sizeof(checkBoxToStyleEx) / sizeof(checkBoxToStyleEx[0]); i++) {
+ if((IsDlgButtonChecked(hwndDlg, checkBoxToStyleEx[i].id) == 0) == checkBoxToStyleEx[i].not_t)
+ exStyle |= checkBoxToStyleEx[i].flag;
+ }
+ cfg::writeDword("CLC", "ExStyle", exStyle);
+ } {
+ DWORD fullGreyoutFlags = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS));
+ cfg::writeDword("CLC", "FullGreyoutFlags", fullGreyoutFlags);
+ if(IsDlgButtonChecked(hwndDlg, IDC_GREYOUT))
+ cfg::writeDword("CLC", "GreyoutFlags", fullGreyoutFlags);
+ else
+ cfg::writeDword("CLC", "GreyoutFlags", 0);
+ }
+ cfg::writeWord("CLC", "ScrollTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_GETPOS, 0, 0));
+ cfg::writeByte("CLC", "NoVScrollBar", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_NOSCROLLBAR) ? 1 : 0));
+ cfg::dat.dwFlags = IsDlgButtonChecked(hwndDlg, IDC_FULLROWSELECT) ? cfg::dat.dwFlags | CLUI_FULLROWSELECT : cfg::dat.dwFlags & ~CLUI_FULLROWSELECT;
+ cfg::dat.bDblClkAvatars = IsDlgButtonChecked(hwndDlg, IDC_DBLCLKAVATARS) ? TRUE : FALSE;
+ cfg::writeByte("CLC", "dblclkav", (BYTE)cfg::dat.bDblClkAvatars);
+ cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags);
+
+ pcli->pfnClcOptionsChanged();
+ CoolSB_SetupScrollBar(pcli->hwndContactTree);
+ PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0);
+ opt_clc_main_changed = 0;
+ return(TRUE);
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY:
+ ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), TVSIL_STATE));
+ break;
+ }
+ return(FALSE);
+}
+
diff --git a/plugins/Clist_ng/SRC/clcpaint.cpp b/plugins/Clist_ng/SRC/clcpaint.cpp new file mode 100644 index 0000000000..3b7afc0ee4 --- /dev/null +++ b/plugins/Clist_ng/SRC/clcpaint.cpp @@ -0,0 +1,1372 @@ +/* + * 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: clcpaint.cpp 134 2010-10-01 10:23:10Z silvercircle $ + * + */ + +#include <commonheaders.h> + +HANDLE CLC::hTheme = 0; + +extern ORDERTREEDATA OrderTreeData[]; +extern HICON overlayicons[]; +extern FRAMEWND* wndFrameCLC; +extern wchar_t* statusNames[]; + +int g_center, g_ignoreselforgroups, g_selectiveIcon, g_exIconSpacing; +HWND g_focusWnd; +BYTE selBlend; +int my_status; + +//static Gdiplus::Graphics* _g; + +static wchar_t wszTimeFormat[] = L"%H:%M"; +static LONG dxBufferDiff, dBufferDiff; + +HFONT CLCPaintHelper::changeToFont(const unsigned int id) +{ + HFONT hOldFont = 0; + + hOldFont = reinterpret_cast<HFONT>(SelectObject(hdcMem, dat->fontInfo[id].hFont)); + Gfx::setTextColor(dat->fontInfo[id].colour); + m_fontHeight = dat->fontInfo[id].fontHeight; + + dat->currentFontID = id; + return hOldFont; +} + +void CLCPaintHelper::setHotTrackColour() +{ + if (dat->gammaCorrection) { + COLORREF oldCol, newCol; + int oldLum, newLum; + + oldCol = GetTextColor(hdcMem); + oldLum = (GetRValue(oldCol) * 30 + GetGValue(oldCol) * 59 + GetBValue(oldCol) * 11) / 100; + newLum = (GetRValue(dat->hotTextColour) * 30 + GetGValue(dat->hotTextColour) * 59 + GetBValue(dat->hotTextColour) * 11) / 100; + if (newLum == 0) { + Gfx::setTextColor(dat->hotTextColour); + return; + } + if (newLum >= oldLum + 20) { + oldLum += 20; + newCol = RGB(GetRValue(dat->hotTextColour) * oldLum / newLum, GetGValue(dat->hotTextColour) * oldLum / newLum, GetBValue(dat->hotTextColour) * oldLum / newLum); + } else if (newLum <= oldLum) { + int r, g, b; + r = GetRValue(dat->hotTextColour) * oldLum / newLum; + g = GetGValue(dat->hotTextColour) * oldLum / newLum; + b = GetBValue(dat->hotTextColour) * oldLum / newLum; + if (r > 255) { + g +=(r-255)*3 / 7; + b +=(r-255)*3 / 7; + r = 255; + } + if (g > 255) { + r +=(g-255)*59 / 41; + if (r > 255) + r = 255; + b +=(g-255)*59 / 41; + g = 255; + } + if (b > 255) { + r +=(b-255)*11 / 89; + if (r > 255) + r = 255; + g +=(b-255)*11 / 89; + if (g > 255) + g = 255; + b = 255; + } + newCol = RGB(r, g, b); + } else + newCol = dat->hotTextColour; + Gfx::setTextColor(newCol); + } else + Gfx::setTextColor(dat->hotTextColour); +} + +/** + * return "relative" onlineness value based on the status mode + * + * @param status status mode + * @param ignoreConnectingState ignore the special "in + * connection progress" status + * + * @return int "onlineness" value for the + * given status mode + */ +static int __fastcall GetRealStatus(struct ClcContact *contact, int status) +{ + int i; + char *szProto = contact->proto; + if (!szProto) + return status; + for (i = 0; i < pcli->hClcProtoCount; i++) { + if (!lstrcmpA(pcli->clcProto[i].szProto, szProto)) { + return pcli->clcProto[i].dwStatus; + } + } + return status; +} + +int GetBasicFontID(struct ClcContact * contact) +{ + switch (contact->type) { + case CLCIT_CONTACT: + if (contact->flags & CONTACTF_NOTONLIST) + return FONTID_NOTONLIST; + else if ((contact->flags&CONTACTF_INVISTO && GetRealStatus(contact, ID_STATUS_OFFLINE) != ID_STATUS_INVISIBLE) + || (contact->flags&CONTACTF_VISTO && GetRealStatus(contact, ID_STATUS_OFFLINE) == ID_STATUS_INVISIBLE)) + return contact->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS; + else + return contact->flags & CONTACTF_ONLINE ? FONTID_CONTACTS : FONTID_OFFLINE; + break; + case CLCIT_GROUP: + return FONTID_GROUPS; + case CLCIT_INFO: + if(contact->flags & CLCIIF_GROUPFONT) + return FONTID_GROUPS; + else + return FONTID_CONTACTS; + case CLCIT_DIVIDER: + return FONTID_DIVIDERS; + default: + return FONTID_CONTACTS; + } +} + +static BLENDFUNCTION bf = {0, 0, AC_SRC_OVER, 0}; +static BOOL avatar_done = FALSE; +HDC g_HDC; +static BOOL g_RTL; +HDC hdcTempAV; +HBITMAP hbmTempAV, hbmTempOldAV; + +LONG g_maxAV_X = 200, g_maxAV_Y = 200; + +int CLCPaintHelper::drawAvatar(RECT *rc, ClcContact *contact, int y, WORD cstatus, int rowHeight) +{ + float dScale = 0.; + float newHeight, newWidth, dAspect; + DWORD topoffset = 0, leftoffset = 0, dwFlags = contact->dwDFlags; + LONG bmWidth, bmHeight; + HBITMAP hbm; + HRGN rgn = 0; + int avatar_size = cfg::dat.avatarSize; + DWORD av_saved_left; + TStatusItem *item = contact->wStatus == ID_STATUS_OFFLINE ? &Skin::statusItems[ID_EXTBKAVATARFRAMEOFFLINE] : &Skin::statusItems[ID_EXTBKAVATARFRAME]; + int skinMarginX, skinMarginY; + BOOL fOverlay = (cfg::dat.dwFlags & CLUI_FRAME_OVERLAYICONS); + + contact->avatarLeft = -1; + if(dat->bisEmbedded) + return 0; + + if(contact->ace) { + if(contact->ace->dwFlags & AVS_HIDEONCLIST) { + if (cfg::dat.dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) + return avatar_size + 2; + else + return 0; + } + bmHeight = contact->ace->bmHeight; + bmWidth = contact->ace->bmWidth; + if(bmWidth != 0) + dAspect = (float)bmHeight / (float)bmWidth; + else + dAspect = 1.0; + hbm = contact->ace->hbmPic; + contact->ace->t_lastAccess = cfg::dat.t_now; + } + else if (cfg::dat.dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) + return avatar_size + 2; + else + return 0; + + if(bmHeight == 0 || bmWidth == 0 || hbm == 0) + return 0; + + g_maxAV_X = max(bmWidth, g_maxAV_X); + g_maxAV_Y = max(bmHeight, g_maxAV_Y); + + if(dAspect >= 1.0) { // height > width + skinMarginY = item->IGNORED ? 0 : (item->MARGIN_TOP + item->MARGIN_BOTTOM); + skinMarginX = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + + dScale = (float)(avatar_size - 2) / (float)bmHeight; + newHeight = (float)(avatar_size - skinMarginY - 2); + newWidth = (float)(bmWidth * dScale) - skinMarginX; + } + else { + skinMarginY = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + skinMarginX = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + + newWidth = (float)(avatar_size - 2) - skinMarginX; + dScale = (float)(avatar_size - 2) / (float)bmWidth; + newHeight = (float)(bmHeight * dScale) - skinMarginY; + } + topoffset = rowHeight > (int)newHeight ? (rowHeight - (int)newHeight) / 2 : 0; + if(!item->IGNORED) { + //topoffset += item->MARGIN_TOP; + leftoffset = item->MARGIN_LEFT; + } + // create the region for the avatar border - use the same region for clipping, if needed. + + av_saved_left = rc->left; + if(cfg::dat.bCenterStatusIcons && newWidth < newHeight) + rc->left += (((avatar_size - 2) - ((int)newWidth + skinMarginX)) / 2); + + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = contact->ace->dwFlags & AVS_PREMULTIPLIED ? AC_SRC_ALPHA : 0; + + + FIBITMAP *fib = cfg::fif->FI_CreateDIBFromHBITMAP(contact->ace->hbmPic); + FIBITMAP *fibnew = cfg::fif->FI_Rescale(fib, newWidth, newHeight, FILTER_LANCZOS3); + HBITMAP hbmNew = cfg::fif->FI_CreateHBITMAPFromDIB(fibnew); + HBITMAP hbmTempOld = (HBITMAP)SelectObject(hdcTempAV, hbmNew); + + Api::pfnAlphaBlend(hdcMem, leftoffset + rc->left - (g_RTL ? 1 : 0), y + topoffset, (int)newWidth, (int)newHeight, hdcTempAV, 0, 0, newWidth, newHeight, bf); + + SelectObject(hdcTempAV, hbmTempOld); + if(hbmNew != contact->ace->hbmPic) + DeleteObject(hbmNew); + cfg::fif->FI_Unload(fib); + cfg::fif->FI_Unload(fibnew); + + if(cfg::dat.dwFlags & CLUI_FRAME_AVATARBORDER) { + rgn = CreateRectRgn(leftoffset + rc->left, y + topoffset, leftoffset + rc->left + (int)newWidth, y + topoffset + (int)newHeight); + if(g_RTL) + OffsetRgn(rgn, -1 , 0); + FrameRgn(hdcMem, rgn, cfg::dat.hBrushAvatarBorder, 1, 1); + DeleteObject(rgn); + } + + if(fOverlay) + fOverlay = (dwFlags & ECF_HIDEOVERLAY) ? 0 : 1; + else + fOverlay = (dwFlags & ECF_FORCEOVERLAY) ? 1 : 0; + + if(fOverlay && cstatus && (int)newHeight >= CYSMICON) + DrawIconEx(hdcMem, rc->left + (int)newWidth - 15, y + topoffset + (int)newHeight - 15, overlayicons[cstatus - ID_STATUS_OFFLINE], CYSMICON, CXSMICON, 0, 0, DI_NORMAL | DI_COMPAT); + + if(!item->IGNORED) { + RECT rcFrame; + bool inClCPaint_save = CLC::fInPaint; + HDC hdcTemp = 0; + HBITMAP hbmOld, hbmTemp; + + CLC::fInPaint = false; + rcFrame.left = rc->left; + rcFrame.top = y + topoffset - item->MARGIN_TOP; + rcFrame.right = rcFrame.left + (int)newWidth + item->MARGIN_RIGHT + item->MARGIN_LEFT; + rcFrame.bottom = rcFrame.top + (int)newHeight + item->MARGIN_BOTTOM + item->MARGIN_TOP; + if(g_RTL) { + RECT rcTemp; + + OffsetRect(&rcFrame, 1, 0); + rcTemp.left = rcTemp.top = 0; + rcTemp.right = rcFrame.right - rcFrame.left; + rcTemp.bottom = rcFrame.bottom - rcFrame.top; + hdcTemp = CreateCompatibleDC(g_HDC); + hbmTemp = CreateCompatibleBitmap(g_HDC, rcTemp.right, rcTemp.bottom); + hbmOld = reinterpret_cast<HBITMAP>(SelectObject(hdcTemp, hbmTemp)); + SetLayout(hdcTemp, LAYOUT_RTL); + BitBlt(hdcTemp, 0, 0, rcTemp.right, rcTemp.bottom, + hdcMem, rcFrame.left, rcFrame.top, SRCCOPY); + SetLayout(hdcTemp, 0); + Gfx::renderSkinItem(hdcTemp, &rcTemp, item->imageItem); + BitBlt(hdcMem, rcFrame.left, rcFrame.top, rcFrame.right - rcFrame.left, rcFrame.bottom - rcFrame.top, + hdcTemp, 0, 0, SRCCOPY); + SelectObject(hdcTemp, hbmOld); + DeleteObject(hbmTemp); + DeleteDC(hdcTemp); + } else + Gfx::renderSkinItem(hdcMem, &rcFrame, item->imageItem); + CLC::fInPaint = inClCPaint_save; + } + contact->avatarLeft = rc->left; + avatar_done = TRUE; + rc->left = av_saved_left; + return avatar_size + 2; + +} + +static BOOL pi_avatar = FALSE; +static RECT rcContent; +static BOOL pi_selectiveIcon; + +static BOOL av_left, av_right, av_rightwithnick; +static BOOL mirror_rtl, mirror_always, mirror_rtltext; + +BYTE savedCORNER = -1; +int g_padding_y = 0; + +void CLCPaintHelper::Paint(ClcGroup *group, ClcContact *contact, int rowHeight) +{ + RECT rc; + int iImage = -1; + SIZE textSize = { 0 }, countsSize = { 0 }, spaceSize = { 0 }; + int width, checkboxWidth; + TCHAR* szCounts = 0; + wchar_t* wszCounts = 0; + BOOL twoRows = FALSE; + WORD cstatus; + DWORD leftOffset = 0, rightOffset = 0; + int iconXSpace = dat->iconXSpace; + HFONT hPreviousFont = 0; + BYTE type; + BYTE flags; + COLORREF oldGroupColor = -1; + DWORD qLeft = 0; + int leftX = dat->leftMargin + indent * dat->groupIndent; + int bg_indent_r = 0; + int bg_indent_l = 0; + int rightIcons = 0; + DWORD dt_nickflags = 0, dt_2ndrowflags = 0; + TExtraCache* cEntry = NULL; + DWORD dwFlags = cfg::dat.dwFlags; + int scanIndex; + BOOL av_local_wanted, fLocalTime; + + if(!isContactFloater) + current_shape = 0; + + rowHeight -= cfg::dat.bRowSpacing; + + if(group == NULL || contact == NULL) + return; + + g_RTL = FALSE; + scanIndex = group->scanIndex; + av_local_wanted = (CLC::uNrAvatars > 0); + + type = contact->type; + flags = contact->flags; + avatar_done = FALSE; + if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) + cEntry = &cfg::eCache[contact->extraCacheEntry]; + else + cEntry = cfg::eCache; + + if(dat->bisEmbedded) + goto set_bg_l; + + if(type == CLCIT_CONTACT && (cEntry->dwCFlags & ECF_RTLNICK || mirror_always)) { + if(mirror_rtl || mirror_always) { + g_RTL = TRUE; + bg_indent_r = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else if(mirror_rtltext) { + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + dt_nickflags = DT_RTLREADING | DT_RIGHT; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else if(type == CLCIT_GROUP) { + if((contact->isRtl && cfg::dat.bGroupAlign == CLC_GROUPALIGN_AUTO) || cfg::dat.bGroupAlign == CLC_GROUPALIGN_RIGHT) { + g_RTL = TRUE; + bg_indent_r = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + +set_bg_l: + //setup + if (type == CLCIT_GROUP) { + changeToFont(FONTID_GROUPS); + GetTextExtentPoint32(hdcMem, contact->szText, lstrlen(contact->szText), &textSize); + width = textSize.cx; + szCounts = pcli->pfnGetGroupCountsText(dat, contact); + if (szCounts[0]) { + GetTextExtentPoint32W(hdcMem, L" ", 1, &spaceSize); + changeToFont(FONTID_GROUPCOUNTS); + GetTextExtentPoint32W(hdcMem, szCounts, lstrlenW(szCounts), &countsSize); + width += spaceSize.cx + countsSize.cx; + wszCounts = szCounts; + } + } else if (type == CLCIT_INFO) { + if (flags & CLCIIF_GROUPFONT) + changeToFont(FONTID_GROUPS); + else + changeToFont(FONTID_CONTACTS); + } else if (type == CLCIT_DIVIDER) { + changeToFont(FONTID_DIVIDERS); + GetTextExtentPoint32(hdcMem, contact->szText, lstrlen(contact->szText), &textSize); + } + else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) + changeToFont(FONTID_NOTONLIST); + else if (type == CLCIT_CONTACT && ((flags & CONTACTF_INVISTO && GetRealStatus(contact, my_status) != ID_STATUS_INVISIBLE) || (flags & CONTACTF_VISTO && GetRealStatus(contact, my_status) == ID_STATUS_INVISIBLE))) { + changeToFont(flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS); + } else if (type == CLCIT_CONTACT && !(flags & CONTACTF_ONLINE)) + changeToFont(FONTID_OFFLINE); + else + changeToFont(FONTID_CONTACTS); + + if ((style & CLS_CHECKBOXES && type == CLCIT_CONTACT) || (style & CLS_GROUPCHECKBOXES && type == CLCIT_GROUP) || (type == CLCIT_INFO && flags & CLCIIF_CHECKBOX)) + checkboxWidth = dat->checkboxSize + 2; + else + checkboxWidth = 0; + + rc.left = 0; + cstatus = contact->wStatus; + + /***** BACKGROUND DRAWING *****/ + // contacts + + CLC::fHottrackDone = false; + + if(dat->bisEmbedded) { + rc.left = bg_indent_l; + rc.top = y; + rc.right = clRect->right - bg_indent_r; + rc.bottom = y + rowHeight; + if (fSelected) { + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); + Gfx::setTextColor(dat->selTextColour); + } + else { + FillRect(hdcMem, &rc, type == CLCIT_GROUP ? cfg::dat.hBrushCLCGroupsBk : cfg::dat.hBrushCLCBk); + if(CLC::iHottrackItem) + setHotTrackColour(); + } + goto bgskipped; + } + if (type == CLCIT_CONTACT || type == CLCIT_DIVIDER) { + TStatusItem *sitem, *pp_item; + + if (cstatus >= ID_STATUS_OFFLINE && cstatus <= ID_STATUS_OUTTOLUNCH) { + BYTE perstatus_ignored; + + if((flags & CONTACTF_IDLE) && !Skin::statusItems[ID_EXTBKIDLE].IGNORED) + sitem = &Skin::statusItems[ID_EXTBKIDLE]; + else + sitem = &Skin::statusItems[cstatus - ID_STATUS_OFFLINE]; + + if(!dat->bisEmbedded) { + pp_item = cEntry->status_item ? cEntry->status_item : cEntry->proto_status_item; + + if (!(perstatus_ignored = sitem->IGNORED) && !(flags & CONTACTF_NOTONLIST)) + Gfx::setTextColor(sitem->TEXTCOLOR); + + if(cfg::dat.bUsePerProto && pp_item && !pp_item->IGNORED) { + sitem = pp_item; + if((perstatus_ignored || cfg::dat.bOverridePerStatusColors) && sitem->TEXTCOLOR != -1) + Gfx::setTextColor(sitem->TEXTCOLOR); + } + } + else if(!sitem->IGNORED) + Gfx::setTextColor(sitem->TEXTCOLOR); + + rc.left = sitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + sitem->MARGIN_TOP; + rc.right = clRect->right - sitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sitem->MARGIN_BOTTOM; + + // single item in a group + if (!ssingleitem->IGNORED && scanIndex == 0 && group->cl.count == 1 && group->parent != NULL) { + rc.left = ssingleitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + ssingleitem->MARGIN_TOP; + rc.right = clRect->right - ssingleitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - ssingleitem->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) + Gfx::renderSkinItem(this, sevencontact_pos, &rc); + else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) + Gfx::renderSkinItem(this, soddcontact_pos, &rc); + + if (!sitem->IGNORED) + Gfx::renderSkinItem(this, sitem, &rc); + Gfx::renderSkinItem(this, ssingleitem, &rc); + + // first item in a group + } else if (scanIndex == 0 && group->cl.count > 1 && !sfirstitem->IGNORED && group->parent != NULL) { + rc.left = sfirstitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + sfirstitem->MARGIN_TOP; + rc.right = clRect->right - sfirstitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sfirstitem->MARGIN_BOTTOM; + + current_shape = sfirstitem->rect; + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) + Gfx::renderSkinItem(this, sevencontact_pos, &rc); + else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) + Gfx::renderSkinItem(this, soddcontact_pos, &rc); + + if (!sitem->IGNORED) + Gfx::renderSkinItem(this, sitem, &rc); + Gfx::renderSkinItem(this, sfirstitem, &rc); + + // last item in a group + } else if (scanIndex == group->cl.count - 1 && !slastitem->IGNORED && group->parent != NULL) { + rc.left = slastitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + slastitem->MARGIN_TOP; + rc.right = clRect->right - slastitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - slastitem->MARGIN_BOTTOM; + rc.bottom = y + rowHeight - slastitem->MARGIN_BOTTOM; + + current_shape = slastitem->rect; + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) + Gfx::renderSkinItem(this, sevencontact_pos, &rc); + else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) + Gfx::renderSkinItem(this, soddcontact_pos, &rc); + + if (!sitem->IGNORED) + Gfx::renderSkinItem(this, sitem, &rc); + Gfx::renderSkinItem(this, slastitem, &rc); + } else { + // - - - Non-grouped items - - - + if (type != CLCIT_GROUP && group->parent == NULL && !sfirstitem_NG->IGNORED && scanIndex != group->cl.count - 1 && !(bFirstNGdrawn)) { + // first NON-grouped + bFirstNGdrawn = TRUE; + rc.left = sfirstitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + sfirstitem_NG->MARGIN_TOP; + rc.right = clRect->right - sfirstitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sfirstitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) + Gfx::renderSkinItem(this, sevencontact_pos, &rc); + else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) + Gfx::renderSkinItem(this, soddcontact_pos, &rc); + + if (!sitem->IGNORED) + Gfx::renderSkinItem(this, sitem, &rc); + Gfx::renderSkinItem(this, sfirstitem, &rc); + + } else if (type != CLCIT_GROUP && group->parent == NULL && !slastitem_NG->IGNORED && scanIndex == group->cl.count - 1 && (bFirstNGdrawn)) { + // last item of list (NON-group) + // last NON-grouped + rc.left = slastitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + slastitem_NG->MARGIN_TOP; + rc.right = clRect->right - slastitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - slastitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) + Gfx::renderSkinItem(this, sevencontact_pos, &rc); + else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) + Gfx::renderSkinItem(this, soddcontact_pos, &rc); + + if (!sitem->IGNORED) + Gfx::renderSkinItem(this, sitem, &rc); + Gfx::renderSkinItem(this, slastitem, &rc); + } else if (type != CLCIT_GROUP && group->parent == NULL && !slastitem_NG->IGNORED && !(bFirstNGdrawn)) { + // single item of NON-group + // single NON-grouped + rc.left = ssingleitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + ssingleitem_NG->MARGIN_TOP; + rc.right = clRect->right - ssingleitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - ssingleitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) + Gfx::renderSkinItem(this, sevencontact_pos, &rc); + else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) + Gfx::renderSkinItem(this, soddcontact_pos, &rc); + + if (!sitem->IGNORED) + Gfx::renderSkinItem(this, sitem, &rc); + Gfx::renderSkinItem(this, ssingleitem, &rc); + } else { + // draw default grouped + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) + Gfx::renderSkinItem(this, sevencontact_pos, &rc); + else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) + Gfx::renderSkinItem(this, soddcontact_pos, &rc); + + if(!sitem->IGNORED) + Gfx::renderSkinItem(this, sitem, &rc); + } + } + } + } + if (type == CLCIT_GROUP) { + TStatusItem *sempty = &Skin::statusItems[ID_EXTBKEMPTYGROUPS]; + TStatusItem *sexpanded = &Skin::statusItems[ID_EXTBKEXPANDEDGROUP]; + TStatusItem *scollapsed = &Skin::statusItems[ID_EXTBKCOLLAPSEDDGROUP]; + + changeToFont(FONTID_GROUPS); + if (contact->group->cl.count == 0) { + if (!sempty->IGNORED) { + rc.left = sempty->MARGIN_LEFT + bg_indent_l; + rc.top = y + sempty->MARGIN_TOP; + rc.right = clRect->right - sempty->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sempty->MARGIN_BOTTOM; + Gfx::renderSkinItem(this, sempty, &rc); + oldGroupColor = GetTextColor(hdcMem); + Gfx::setTextColor(sempty->TEXTCOLOR); + } + } else if (contact->group->expanded) { + if (!sexpanded->IGNORED) { + rc.left = sexpanded->MARGIN_LEFT + bg_indent_l; + rc.top = y + sexpanded->MARGIN_TOP; + rc.right = clRect->right - sexpanded->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - (char) sexpanded->MARGIN_BOTTOM; + Gfx::renderSkinItem(this, sexpanded, &rc); + oldGroupColor =GetTextColor(hdcMem); + Gfx::setTextColor(sexpanded->TEXTCOLOR); + } + } else { + if (!scollapsed->IGNORED) { + // collapsed but not empty + rc.left = scollapsed->MARGIN_LEFT + bg_indent_l; + rc.top = y + scollapsed->MARGIN_TOP; + rc.right = clRect->right - scollapsed->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - scollapsed->MARGIN_BOTTOM; + Gfx::renderSkinItem(this, scollapsed, &rc); + oldGroupColor = GetTextColor(hdcMem); + Gfx::setTextColor(scollapsed->TEXTCOLOR); + } + } + } + if (fSelected) { + TStatusItem *sselected = &Skin::statusItems[ID_EXTBKSELECTION]; + + if (!g_ignoreselforgroups || type != CLCIT_GROUP) { + rc.left = sselected->MARGIN_LEFT + bg_indent_l; + rc.top = y + sselected->MARGIN_TOP; + rc.right = clRect->right - sselected->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sselected->MARGIN_BOTTOM; + Gfx::renderSkinItem(this, sselected, &rc); + Gfx::setTextColor(sselected->TEXTCOLOR); + } + } + else if (CLC::iHottrackItem) { + TStatusItem *ht = &Skin::statusItems[ID_EXTBKHOTTRACK]; + + if(ht->IGNORED == 0) + Gfx::setTextColor(ht->TEXTCOLOR); + if(!CLC::fHottrackDone) { + if (ht->IGNORED == 0) { + Gfx::renderSkinItem(this, ht, &rc); + } + } + } + + if(g_RTL) { + SetLayout(hdcMem, LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED); + dxBufferDiff = dBufferDiff; + } + else + dxBufferDiff = 0; // adjust discrepancy between the width of the buffered paint dc and the actual window width (bug in buffered paint?) +bgskipped: + + rcContent.top = y + g_padding_y; + rcContent.bottom = y + rowHeight - (2 * g_padding_y); + rcContent.left = leftX + dxBufferDiff; + rcContent.right = clRect->right - dat->rightMargin + dxBufferDiff; + twoRows = ((dat->fontInfo[FONTID_STATUS].fontHeight + m_fontHeight <= rowHeight + 1) && (fSecondLine)) && !dat->bisEmbedded; + + pi_avatar = (!dat->bisEmbedded && fAvatar); + + //checkboxes + if (checkboxWidth) { + RECT rc; + + rc.left = leftX; + rc.right = rc.left + dat->checkboxSize; + rc.top = y + ((rowHeight - dat->checkboxSize) >> 1); + rc.bottom = rc.top + dat->checkboxSize; + if (hTheme) { + Api::pfnDrawThemeBackground(hTheme, hdcMem, BP_CHECKBOX, flags & CONTACTF_CHECKED ? (CLC::iHottrackItem ? CBS_CHECKEDHOT : CBS_CHECKEDNORMAL) : + (CLC::iHottrackItem ? CBS_UNCHECKEDHOT : CBS_UNCHECKEDNORMAL), &rc, &rc); + } + else + DrawFrameControl(hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT | (flags & CONTACTF_CHECKED ? DFCS_CHECKED : 0) | (CLC::iHottrackItem ? DFCS_HOT : 0)); + rcContent.left += checkboxWidth; + leftX += checkboxWidth; + } + + if (type == CLCIT_GROUP) + iImage = (contact->group->expanded) ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; + else if (type == CLCIT_CONTACT) + iImage = contact->iImage; + + + if(pi_avatar && (av_left || av_right)) { + RECT rc; + + rc.left = rcContent.left; + rc.right = clRect->right; + rc.top = y; + rc.bottom = rc.top + rowHeight; + + if(av_left) { + leftOffset += drawAvatar(&rc, contact, y, (WORD)(iImage ? cstatus : 0), rowHeight); + rcContent.left += leftOffset; + leftX += leftOffset; + } + else { + rc.left = (rcContent.right - cfg::dat.avatarSize) + 1; + rightOffset += drawAvatar(&rc, contact, y, (WORD)(iImage ? cstatus : 0), rowHeight); + rcContent.right -= (rightOffset); + } + } + else if(type == CLCIT_CONTACT && !dat->bisEmbedded && !g_selectiveIcon && (dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) && av_local_wanted && (av_left || av_right)) { + if(av_right) + rcContent.right -= (cfg::dat.avatarSize + 2); + if(av_left) + rcContent.left += (cfg::dat.avatarSize + 2); + } + //icon + + // skip icon for groups if the option is enabled... + + if(type == CLCIT_GROUP && dwFlags & CLUI_FRAME_NOGROUPICON) { + iconXSpace = 0; + goto text; + } + if (iImage != -1) { + // this doesnt use CLS_CONTACTLIST since the colour prolly wont match anyway + COLORREF colourFg = dat->selBkColour; + //int clientId = contact->clientId; + int mode = ILD_NORMAL; + pi_selectiveIcon = g_selectiveIcon && (type == CLCIT_CONTACT); + + if((dwFlags & CLUI_FRAME_STATUSICONS && !pi_selectiveIcon) || type != CLCIT_CONTACT || (pi_selectiveIcon && !avatar_done)) { + HIMAGELIST hImgList = CLC::hClistImages; + + if (CLC::iHottrackItem) { + colourFg = dat->hotTextColour; + } else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; + mode = ILD_BLEND50; + } + if (type == CLCIT_CONTACT && dat->showIdle && (flags & CONTACTF_IDLE) && contact->wStatus != ID_STATUS_OFFLINE) + mode = ILD_SELECTED; + + if(pi_selectiveIcon && av_right) { + ImageList_DrawEx(hImgList, iImage, hdcMem, rcContent.right - 18, (twoRows && type == CLCIT_CONTACT && !cfg::dat.bCenterStatusIcons) ? y + 2 : y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + rcContent.right -= 18; + } + else { + LONG offset = 0; + BOOL centered = FALSE; + offset += (type != CLCIT_CONTACT || avatar_done || !(av_local_wanted) ? 20 : dwFlags & CLUI_FRAME_ALWAYSALIGNNICK && av_left && g_selectiveIcon ? cfg::dat.avatarSize + 2 : 20); + centered = (cfg::dat.bCenterStatusIcons && offset == cfg::dat.avatarSize + 2); + ImageList_DrawEx(hImgList, iImage, hdcMem, centered ? rcContent.left + offset / 2 - 10 : rcContent.left, (twoRows && type == CLCIT_CONTACT && !cfg::dat.bCenterStatusIcons) ? y + 2 : y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + rcContent.left += offset; + } + } + else + iconXSpace = 0; + if (type == CLCIT_CONTACT && !dat->bisEmbedded) { + BYTE bApparentModeDontCare = !((flags & CONTACTF_VISTO) ^ (flags & CONTACTF_INVISTO)); + contact->extraIconRightBegin = 0; + if(cEntry && (contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry && cEntry->iExtraValid)) { + int i, iIndex, id; + DWORD dwOldMask = cEntry->dwXMask; + + for(i = EXICON_COUNT - 1; i >= 0; i--) { + iIndex = cfg::dat.exIconOrder[i] - 1; + if(iIndex >= 0 && iIndex < EXICON_COUNT) { + id = OrderTreeData[iIndex].ID; + if(cEntry->iExtraImage[id] != 0xff && ((1 << id) & cEntry->dwXMask)) { + if(contact->extraIconRightBegin == 0 && i != (EXICON_COUNT - 1)) + contact->extraIconRightBegin = rcContent.right; + ImageList_DrawEx(dat->himlExtraColumns, cEntry->iExtraImage[id], hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + rcContent.right -= g_exIconSpacing; + rightIcons++; + } + } + } + cEntry->dwXMask = dwOldMask; + } + if (!bApparentModeDontCare && (dwFlags & CLUI_SHOWVISI) && contact->proto) { + BOOL fVisi; + + if(dwFlags & CLUI_SHOWVISI) + fVisi = contact->dwDFlags & ECF_HIDEVISIBILITY ? 0 : 1; + else + fVisi = contact->dwDFlags & ECF_FORCEVISIBILITY ? 1 : 0; + + if(fVisi) { + if(cEntry->isChatRoom) + DrawIconEx(hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + cfg::dat.hIconChatactive, cfg::dat.exIconScale, cfg::dat.exIconScale, 0, 0, DI_NORMAL | DI_COMPAT); + else + DrawIconEx(hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + flags & CONTACTF_VISTO ? cfg::dat.hIconVisible : cfg::dat.hIconInvisible, cfg::dat.exIconScale, cfg::dat.exIconScale, 0, 0, DI_NORMAL | DI_COMPAT); + rcContent.right -= g_exIconSpacing; + rightIcons++; + } + } + } + } + //text +text: + if (type == CLCIT_DIVIDER) { + RECT rc, rcText; + rc.top = y + ((rowHeight) >> 1) - 1; rc.bottom = rc.top + 2; + rc.left = clRect->left + dat->leftMargin; + rc.right = rc.left - dat->rightMargin + ((clRect->right - rc.left - textSize.cx) >> 1) - 3; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + Api::pfnBufferedPaintSetAlpha(hbp, &rc, 255); + rcText.left = rc.right + 3; + rcText.top = y; + rcText.bottom = y + rowHeight; + rcText.right = rcText.left + textSize.cx; + Gfx::renderText(hdcMem, hTheme, contact->szText, &rcText, DT_CENTER | DT_VCENTER | DT_SINGLELINE); + rc.left = rc.right + 6 + textSize.cx; + rc.right = clRect->right - dat->rightMargin; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + Api::pfnBufferedPaintSetAlpha(hbp, &rc, 255); + } else if (type == CLCIT_GROUP) { + RECT rc; + m_fontHeight = dat->fontInfo[FONTID_GROUPS].fontHeight; + rc.top = y + ((rowHeight - m_fontHeight) >> 1) + cfg::dat.group_padding; + rc.bottom = rc.top + textSize.cy; + if (szCounts[0]) { + int required, labelWidth, offset = 0; + COLORREF clr = GetTextColor(hdcMem); + + changeToFont(FONTID_GROUPCOUNTS); + if(oldGroupColor != -1) + Gfx::setTextColor(clr); + + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + iconXSpace; + rc.right = clRect->right - dat->rightMargin; + + if(indent == 0 && iconXSpace == 0) + rc.left += 2; + + required = textSize.cx + countsSize.cx + spaceSize.cx; + + if(required > rc.right - rc.left) + textSize.cx = (rc.right - rc.left) - countsSize.cx - spaceSize.cx; + + labelWidth = textSize.cx + countsSize.cx + spaceSize.cx; + if(g_center) + offset = ((rc.right - rc.left) - labelWidth) / 2; + + RECT rcCounts = rc; + rcCounts.left += (offset + textSize.cx + spaceSize.cx + dxBufferDiff); + rcCounts.right += dxBufferDiff; + rcCounts.top += groupCountsFontTopShift; + Gfx::renderText(hdcMem, hTheme, wszCounts, &rcCounts, DT_SINGLELINE); + mir_free(wszCounts); + + if (fSelected && !g_ignoreselforgroups) + clr = dat->selTextColour; + else + Gfx::setTextColor(clr); + changeToFont(FONTID_GROUPS); + rc.left += (offset + dxBufferDiff); + rc.right = rc.left + textSize.cx; + qLeft = rc.left; + + Gfx::renderText(hdcMem, hTheme, contact->szText, &rc, DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS); + } else if (g_center && !szCounts[0]) { + int offset; + + rc.left = rcContent.left; + rc.right = clRect->right - dat->rightMargin; + if(textSize.cx >= rc.right - rc.left) + textSize.cx = rc.right - rc.left; + + offset = ((rc.right - rc.left) - textSize.cx) / 2; + rc.left += (offset + dxBufferDiff); + rc.right = rc.left + textSize.cx + dxBufferDiff; + Gfx::renderText(hdcMem, hTheme, contact->szText, &rc, DT_CENTER | DT_NOPREFIX | DT_SINGLELINE); + qLeft = rc.left; + } else { + qLeft = rcContent.left + (indent == 0 && iconXSpace == 0 ? 2 : 0); + rc.left = qLeft; + rc.right = min(rc.left + textSize.cx, clRect->right - dat->rightMargin) + dxBufferDiff; + Gfx::renderText(hdcMem, hTheme, contact->szText, &rc, DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS); + } + } else { + wchar_t *szText = contact->szText; + + rcContent.top = y + ((rowHeight - m_fontHeight) >> 1); + + // avatar + + if(!dat->bisEmbedded) { + if(av_local_wanted && !avatar_done && pi_avatar) { + if(av_rightwithnick) { + RECT rcAvatar = rcContent; + + rcAvatar.left = rcContent.right - (cfg::dat.avatarSize - 1); + drawAvatar(&rcAvatar, contact, y, (WORD)(iImage ? cstatus : 0), rowHeight); + rcContent.right -= (cfg::dat.avatarSize + 2); + } + else + rcContent.left += drawAvatar(&rcContent, contact, y, (WORD)(iImage ? cstatus : 0), rowHeight); + } + else if(dwFlags & CLUI_FRAME_ALWAYSALIGNNICK && !avatar_done && av_local_wanted) + rcContent.left += (dwFlags & (CLUI_FRAME_AVATARSLEFT | CLUI_FRAME_AVATARSRIGHT | CLUI_FRAME_AVATARSRIGHTWITHNICK) ? 0 : cfg::dat.avatarSize + 2); + } + + // nickname + if(!twoRows) + Gfx::renderText(hdcMem, hTheme, szText, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE | dt_nickflags); + else { + DWORD dtFlags = DT_WORD_ELLIPSIS | DT_NOPREFIX | DT_NOCLIP | DT_SINGLELINE; + DWORD saved_right = rcContent.right; + BOOL verticalfit = FALSE; + + rcContent.top = y + cfg::dat.avatarPadding / 2; + + if(cfg::dat.bShowLocalTime) + fLocalTime = contact->dwDFlags & ECF_HIDELOCALTIME ? 0 : 1; + else + fLocalTime = contact->dwDFlags & ECF_FORCELOCALTIME ? 1 : 0; + + if(cEntry->hTimeZone != 0 && fLocalTime) { + wchar_t szResult[80]; + int idOldFont; + SIZE szTime; + RECT rc = rcContent; + COLORREF oldColor = 0; + + if (TimeZone_PrintDateTime(cEntry->hTimeZone, _T("t"), szResult, _countof(szResult), 0))
+ goto nodisplay;
+ + oldColor = Gfx::getTextColor(); + idOldFont = dat->currentFontID; + changeToFont(FONTID_TIMESTAMP); + GetTextExtentPoint32(hdcMem, szResult, lstrlenW(szResult), &szTime); + verticalfit = ((rowHeight - szTime.cy) >= (cfg::dat.exIconScale + 1)); + + if(av_right) { + if(verticalfit) + rc.left = rcContent.right + (rightIcons * g_exIconSpacing) - szTime.cx - 2; + else + rc.left = rcContent.right - szTime.cx - 2; + } + else if(av_rightwithnick) { + if(verticalfit && rightIcons * g_exIconSpacing >= szTime.cx) + rc.left = (clRect->right - dat->rightMargin - szTime.cx) + dxBufferDiff; + else if(verticalfit && !avatar_done) + rc.left = (clRect->right - dat->rightMargin - szTime.cx) + dxBufferDiff; + else { + rc.left = rcContent.right - szTime.cx - 2; + rcContent.right = rc.left - 2; + } + } + else { + if(verticalfit) + rc.left = (clRect->right - dat->rightMargin - szTime.cx) + dxBufferDiff; + else + rc.left = rcContent.right - szTime.cx - 2; + } + rc.right = clRect->right + dxBufferDiff; + Gfx::renderText(hdcMem, hTheme, szResult, &rc, DT_NOPREFIX | DT_NOCLIP | DT_SINGLELINE); + changeToFont(idOldFont); + Gfx::setTextColor(oldColor); + + verticalfit = (rowHeight - m_fontHeight >= cfg::dat.exIconScale + 1); + if(verticalfit && av_right) + rcContent.right = min((clRect->right - cfg::dat.avatarSize - 2) + dxBufferDiff, rc.left - 2); + else if(verticalfit && !av_rightwithnick) + rcContent.right = min((clRect->right - dat->rightMargin) + dxBufferDiff, rc.left - 3); + + } + else { +nodisplay: + verticalfit = (rowHeight - m_fontHeight >= cfg::dat.exIconScale + 1); + if(avatar_done) { + if(verticalfit && av_right) + rcContent.right = (clRect->right - cfg::dat.avatarSize - 2) + dxBufferDiff; + else if(verticalfit && !av_rightwithnick) + rcContent.right = (clRect->right - dat->rightMargin) + dxBufferDiff; + } + } + Gfx::renderText(hdcMem, hTheme, szText, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE | dt_nickflags); + + rcContent.right = saved_right; + rcContent.top += (m_fontHeight - 1); + hPreviousFont = changeToFont(FONTID_STATUS); + rcContent.bottom = y + rowHeight; + + if(cstatus >= ID_STATUS_OFFLINE && cstatus <= ID_STATUS_OUTTOLUNCH) { + wchar_t *szText = NULL; + BYTE smsgValid = cEntry->bStatusMsgValid; + + if((dwFlags & CLUI_FRAME_SHOWSTATUSMSG && smsgValid > STATUSMSG_XSTATUSID) || smsgValid == STATUSMSG_XSTATUSNAME) + szText = cEntry->statusMsg; + else + szText = &statusNames[cstatus - ID_STATUS_OFFLINE][0]; + if(cEntry->dwCFlags & ECF_RTLSTATUSMSG && cfg::dat.bUseDCMirroring == 3) + dt_2ndrowflags |= (DT_RTLREADING | DT_RIGHT); + + if(rightIcons == 0) { + if((rcContent.bottom - rcContent.top) >= (2 * m_fontHeight)) { + dtFlags &= ~(DT_SINGLELINE | DT_BOTTOM | DT_NOCLIP); + dtFlags |= DT_WORDBREAK; + rcContent.bottom -= ((rcContent.bottom - rcContent.top) % m_fontHeight); + } + Gfx::renderText(hdcMem, hTheme, szText, &rcContent, dtFlags | dt_2ndrowflags); + } + else { + if((rcContent.bottom - rcContent.top) < (2 * m_fontHeight) - 2) + Gfx::renderText(hdcMem, hTheme, szText, &rcContent, dtFlags | dt_2ndrowflags); + else { + DRAWTEXTPARAMS dtp = {0}; + LONG rightIconsTop = rcContent.bottom - g_exIconSpacing; + LONG old_right = rcContent.right; + ULONG textCounter = 0; + ULONG ulLen = lstrlen(szText); + LONG old_bottom = rcContent.bottom; + DWORD i_dtFlags = DT_WORDBREAK | DT_NOPREFIX | dt_2ndrowflags; + dtp.cbSize = sizeof(dtp); + rcContent.right = clRect->right - dat->rightMargin - rightOffset; + do { + if(rcContent.top + (m_fontHeight - 1) > rightIconsTop + 1) + rcContent.right = old_right; + dtp.uiLengthDrawn = 0; + rcContent.bottom = rcContent.top + m_fontHeight - 1; + if(rcContent.bottom + m_fontHeight >= old_bottom) + i_dtFlags |= DT_END_ELLIPSIS; + DrawTextEx(hdcMem, &szText[textCounter], -1, &rcContent, i_dtFlags | DT_CALCRECT, &dtp); + if(dtp.uiLengthDrawn) + Gfx::renderText(hdcMem, hTheme, &szText[textCounter], &rcContent, i_dtFlags, 0, dtp.uiLengthDrawn); + rcContent.top += m_fontHeight; + textCounter += dtp.uiLengthDrawn; + } while (textCounter <= ulLen && dtp.uiLengthDrawn && rcContent.top + m_fontHeight <= old_bottom); + } + } + } + } + } + if (fSelected) { + if (type != CLCIT_DIVIDER) { + wchar_t *szText = contact->szText; + RECT rc; + int qlen = lstrlen(dat->szQuickSearch); + if(hPreviousFont) + SelectObject(hdcMem, hPreviousFont); + Gfx::setTextColor(dat->quickSearchColour); + if(type == CLCIT_CONTACT) { + rc.left = rcContent.left; + rc.top = y + ((rowHeight - m_fontHeight) >> 1); + rc.right = clRect->right - rightOffset; + rc.right = rcContent.right; + rc.bottom = rc.top; + if(twoRows) + rc.top = y; + } + else { + rc.left = qLeft; + rc.top = y + ((rowHeight - m_fontHeight) >> 1); + rc.right = clRect->right - rightOffset; + rc.bottom = rc.top; + } + if (qlen) + Gfx::renderText(hdcMem, hTheme, szText, &rc, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + } + //extra icons + DWORD spacing = 1; + for (int i = dat->extraColumnsCount - 1; i >= 0; i--) { + COLORREF colourFg = dat->selBkColour; + int mode = ILD_NORMAL; + if (contact->iExtraImage[i] == 0xffff) + continue; + if (fSelected) + mode = ILD_SELECTED; + else if (CLC::iHottrackItem) { + mode = ILD_FOCUS; colourFg = dat->hotTextColour; + } else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; mode = ILD_BLEND50; + } + ImageList_DrawEx(dat->himlExtraColumns, contact->iExtraImage[i], hdcMem, clRect->right - rightOffset - dat->extraColumnSpacing * (spacing++), y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + } + if(g_RTL) + SetLayout(hdcMem, 0); +} + +void CLC::Paint(HWND hwnd, ClcData *dat, HDC hdc, RECT *rcPaint) +{ + RGBQUAD* rgq = 0; + ClcContact* contact; + int ipxWidth = 0; + HDC hdcMem; + RECT clRect; + ClcGroup* group; + HANDLE hbp = 0; + HFONT hOldFont = 0; + DWORD style = GetWindowLong(hwnd, GWL_STYLE); + int grey = 0, groupCountsFontTopShift; + int line_num = -1; + COLORREF tmpbkcolour = style & CLS_CONTACTLIST ? (dat->useWindowsColours ? GetSysColor(COLOR_3DFACE) : dat->bkColour) : dat->bkColour; + BOOL isFloating = (wndFrameCLC && wndFrameCLC->floating) ? TRUE : FALSE; + bool fFocusCheck; + + fInPaint = true; + g_focusWnd = GetFocus(); + my_status = getGeneralisedStatus(); + g_HDC = hdc; + + /* + * temporary DC for avatar drawing + */ + + g_padding_y = 0; + + hdcTempAV = CreateCompatibleDC(g_HDC); + hbmTempAV = CreateCompatibleBitmap(g_HDC, g_maxAV_X, g_maxAV_Y); + hbmTempOldAV = reinterpret_cast<HBITMAP>(SelectObject(hdcTempAV, hbmTempAV)); + + cfg::dat.t_now = time(NULL); + + /* + * setup static globals used by PaintItem(); + */ + av_left = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSLEFT); + av_right = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSRIGHT); + av_rightwithnick = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSRIGHTWITHNICK); + + mirror_rtl = (cfg::dat.bUseDCMirroring == 2); + mirror_always = (cfg::dat.bUseDCMirroring == 1); + mirror_rtltext = (cfg::dat.bUseDCMirroring == 3); + + g_center = cfg::getByte("CLCExt", "EXBK_CenterGroupnames", 0) && !dat->bisEmbedded; + g_ignoreselforgroups = cfg::getByte("CLC", "IgnoreSelforGroups", 0); + g_exIconSpacing = cfg::dat.exIconScale + 2; + + /* + * check if list should be greyed out based on focus or current status + */ + if (GetForegroundWindow()!= pcli->hwndContactList && dat->greyoutFlags & GREYF_UNFOCUS) + grey = 1; + else if((dat->greyoutFlags & pcli->pfnClcStatusToPf2(my_status)) || style & WS_DISABLED) + grey = 1; + + GetClientRect(hwnd, &clRect); + if (rcPaint == NULL) + rcPaint = &clRect; + +#ifndef _USE_D2D + if (IsRectEmpty(rcPaint)) { + SelectObject(hdcTempAV, hbmTempOldAV); + DeleteObject(hbmTempAV); + DeleteDC(hdcTempAV); + return; + } +#endif + +#ifdef _USE_D2D + HBITMAP hbmMem, hbmMemOld; + if(hwnd == pcli->hwndContactTree) { + rcPaint = &clRect; + hdcMem = CreateCompatibleDC(cfg::dat.hdcBg); + hbmMem = Gfx::createRGBABitmap(clRect.right - clRect.left, clRect.bottom - clRect.top, hdcMem); + hbmMemOld = (HBITMAP)SelectObject(hdcMem, hbmMem); + } + else + hbp = Gfx::initiateBufferedPaint(hdc, clRect, hdcMem); +#else + /* explanation for this weird code.. (dBufferDiff etc..) + * a bufferend paint dc is normally not the same size as the client rectangle of a + * child window (CLC in this case). It's usually much wider. This isn't a problem + * for LTR rendering where everything starts at (0,0) but when using SetLayout() + * to mirror the DC (for RTL support) it becomes a HUGE problem, because right + * becomes left and content will vanish outside the client area. + * + * dBufferDiff is the difference between the width of the buffered DC and the width + * of the actual client rectangle. PaintItem() will add that offset to rcContent.left + * when rendering RTL rows to compensate for the difference in width. + * + */ + dBufferDiff = 0; + INIT_PAINT(hdc, clRect, hdcMem); + Api::pfnGetBufferedPaintBits(hbp, &rgq, &ipxWidth); + dBufferDiff = ipxWidth - clRect.right; +#endif + + { + TEXTMETRIC tm; + hOldFont = reinterpret_cast<HFONT>(SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPS].hFont)); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift = tm.tmAscent; + SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift -= tm.tmAscent; + } + + SetBkMode(hdcMem, TRANSPARENT); + if(!cfg::isAero || dat->bisEmbedded || isFloating) { + HBRUSH hBrush, hoBrush; + hBrush = CreateSolidBrush(tmpbkcolour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRect(hdcMem, rcPaint, hBrush); + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + } + + if(!dat->bisEmbedded && rcPaint && !isFloating) + Gfx::drawBGFromSurface(hwnd, *rcPaint, hdcMem); + + g_selectiveIcon = (CLC::uNrAvatars > 0) && (cfg::dat.dwFlags & CLUI_FRAME_SELECTIVEICONS) && !dat->bisEmbedded; + + group = &dat->list; + group->scanIndex = 0; + + CLCPaintHelper* ph = dat->ph; + + fFocusCheck = dat->showSelAlways || dat->exStyle &CLS_EX_SHOWSELALWAYS || g_focusWnd == hwnd; + + // set up the paint helper + ph->setHDC(hdcMem); + ph->aggctx->attach(rgq, ipxWidth, clRect.bottom); + ph->hTheme = Api::pfnOpenThemeData(hwnd, L"BUTTON"); + ph->style = style; + ph->clRect = &clRect; + ph->y = -dat->yScroll; + ph->indent = 0; + ph->bFirstNGdrawn = false; + ph->groupCountsFontTopShift = groupCountsFontTopShift; + ph->hbp = hbp; + + ph->sevencontact_pos = &Skin::statusItems[ID_EXTBKEVEN_CNTCTPOS]; + ph->soddcontact_pos = &Skin::statusItems[ID_EXTBKODD_CNTCTPOS]; + ph->sfirstitem = &Skin::statusItems[ID_EXTBKFIRSTITEM]; + ph->ssingleitem = &Skin::statusItems[ID_EXTBKSINGLEITEM]; + ph->slastitem = &Skin::statusItems[ID_EXTBKLASTITEM]; + + ph->sfirstitem_NG = &Skin::statusItems[ID_EXTBKFIRSTITEM_NG]; + ph->ssingleitem_NG = &Skin::statusItems[ID_EXTBKSINGLEITEM_NG]; + ph->slastitem_NG = &Skin::statusItems[ID_EXTBKLASTITEM_NG]; + + + hOldFont = ph->changeToFont(FONTID_CONTACTS); + + if ( dat->row_heights == NULL ) + RowHeight::calcRowHeights(dat, hwnd, ph); + + for (ph->index = 0; ph->y < rcPaint->bottom;) { + if (group->scanIndex == group->cl.count) { + group = group->parent; + ph->indent--; + if (group == NULL) { + break; + } + group->scanIndex++; + continue; + } + + line_num++; + contact = group->cl.items[group->scanIndex]; + if(cfg::dat.bForceRefetchOnPaint) + contact->ace = (struct avatarCacheEntry*)-1; + + if (ph->y > rcPaint->top - dat->row_heights[line_num] && ph->y <= rcPaint->bottom) { + if (contact->ace == (struct avatarCacheEntry*)-1 ) + contact->ace = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)group->cl.items[group->scanIndex]->hContact, 0); + + ph->fSelected = (ph->index == dat->selection && contact->type != CLCIT_DIVIDER && fFocusCheck); + iHottrackItem = dat->exStyle & CLS_EX_TRACKSELECT && contact->type == CLCIT_CONTACT && dat->iHotTrack == ph->index; + if (iHottrackItem == ph->fSelected) + iHottrackItem = 0; + if(ph->fSelected && dsp_default.dspOverride[DSP_OVR_SELECTED].fActive) + ph->dsp = &dsp_default.dspOverride[DSP_OVR_SELECTED]; + else if(iHottrackItem && dsp_default.dspOverride[DSP_OVR_HOVERED].fActive) + ph->dsp = &dsp_default.dspOverride[DSP_OVR_HOVERED]; + else if(ID_STATUS_OFFLINE == contact->wStatus) + ph->dsp = &dsp_default.dspOverride[DSP_OVR_OFFLINE]; + else if(ID_STATUS_OFFLINE != contact->wStatus) + ph->dsp = &dsp_default.dspOverride[DSP_OVR_ONLINE]; + else + ph->dsp = 0; // calc dsp profile + RowHeight::getRowHeight(dat, contact, line_num, style, ph); + ph->Paint(group, contact, dat->row_heights[line_num]); + } + ph->index++; + ph->y += dat->row_heights[line_num]; + if (contact->type == CLCIT_GROUP && (contact->group->expanded)) { + group = contact->group; + ph->indent++; + group->scanIndex = 0; + continue; + } + group->scanIndex++; + } + + SelectObject(hdcTempAV, hbmTempOldAV); + DeleteObject(hbmTempAV); + DeleteDC(hdcTempAV); + Api::pfnCloseThemeData(ph->hTheme); + + if (dat->iInsertionMark != -1) { + //insertion mark + HBRUSH hBrush, hoBrush; + POINT pts[8]; + HRGN hRgn; + + pts[0].x=dat->leftMargin; pts[0].y = RowHeight::getItemTopY(dat, dat->iInsertionMark) - dat->yScroll - 4; + //pts[0]. x = dat->leftMargin; pts[0]. y = dat->iInsertionMark * rowHeight - dat->yScroll - 4; + pts[1]. x = pts[0].x + 2; pts[1]. y = pts[0].y + 3; + pts[2]. x = clRect.right - 4; pts[2]. y = pts[1].y; + pts[3]. x = clRect.right - 1; pts[3]. y = pts[0].y - 1; + pts[4]. x = pts[3].x; pts[4]. y = pts[0].y + 7; + pts[5]. x = pts[2].x + 1; pts[5]. y = pts[1].y + 2; + pts[6]. x = pts[1].x; pts[6]. y = pts[5].y; + pts[7]. x = pts[0].x; pts[7]. y = pts[4].y; + hRgn = CreatePolygonRgn(pts, sizeof(pts) / sizeof(pts[0]), ALTERNATE); + hBrush = CreateSolidBrush(dat->fontInfo[FONTID_CONTACTS].colour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRgn(hdcMem, hRgn, hBrush); + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + } + if(hOldFont) + SelectObject(hdcMem, hOldFont); + + fInPaint = false; + if (grey) + Skin::renderNamedImageItem("@GreyOut", &clRect, hdcMem); + +#if defined _USE_D2D + if(hwnd == pcli->hwndContactTree) { + MapWindowPoints(pcli->hwndContactTree, pcli->hwndContactList, (POINT*)&clRect, 2); + Gfx::setBitmapAlpha(hbmMem, 0); + Api::pfnAlphaBlend(cfg::dat.hdcBg, clRect.left, clRect.top, clRect.right - clRect.left, clRect.bottom - clRect.top, + hdcMem, 0, 0, clRect.right - clRect.left, clRect.bottom - clRect.top, CLUI::bf); + SelectObject(hdcMem, hbmMemOld); + DeleteObject(hbmMem); + DeleteDC(hdcMem); + CLUI::updateLayers(); + } + else + FINALIZE_PAINT(hbp, &clRect); +#else + //delete _g; + FINALIZE_PAINT(hbp, &clRect, isFloating ? 255 : 0); +#endif +} diff --git a/plugins/Clist_ng/SRC/clcutils.cpp b/plugins/Clist_ng/SRC/clcutils.cpp new file mode 100644 index 0000000000..440832a7e1 --- /dev/null +++ b/plugins/Clist_ng/SRC/clcutils.cpp @@ -0,0 +1,591 @@ +/*
+ * 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: clcutils.cpp 134 2010-10-01 10:23:10Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include <richedit.h>
+#include "../coolsb/coolscroll.h"
+
+static int MY_pathIsAbsolute(const wchar_t *path)
+{
+ if (!path || !(lstrlen(path) > 2))
+ return 0;
+ if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
+ return 1;
+ return 0;
+}
+
+/**
+ * performs hit-testing for reversed (mirrored) contact rows when using RTL
+ * shares all the init stuff with HitTest(), but needs to reverse the
+ * x-coordinate.
+ */
+
+int CLC::RTL_HitTest(HWND hwnd, ClcData *dat, int testx, int testy, ClcContact *hitcontact, DWORD *flags, int indent, int hit)
+{
+ RECT clRect;
+ int right, checkboxWidth, cxSmIcon, i, width;
+ DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+ SIZE textSize;
+ HDC hdc;
+ HFONT hFont;
+
+ GetClientRect(hwnd, &clRect);
+ right = clRect.right;
+
+ // avatar check
+ if(hitcontact->type == CLCIT_CONTACT && cfg::dat.dwFlags & CLUI_FRAME_AVATARS && hitcontact->ace != NULL && hitcontact->avatarLeft != -1) {
+ if(testx < right - hitcontact->avatarLeft && testx > right - hitcontact->avatarLeft - cfg::dat.avatarSize) {
+ if(flags)
+ *flags |= CLCHT_ONAVATAR;
+ }
+ }
+ if (testx > right - (dat->leftMargin + indent * dat->groupIndent)) {
+ if (flags)
+ *flags |= CLCHT_ONITEMINDENT;
+ return hit;
+ }
+ checkboxWidth = 0;
+ if (style & CLS_CHECKBOXES && hitcontact->type == CLCIT_CONTACT)
+ checkboxWidth = dat->checkboxSize + 2;
+ if (style & CLS_GROUPCHECKBOXES && hitcontact->type == CLCIT_GROUP)
+ checkboxWidth = dat->checkboxSize + 2;
+ if (hitcontact->type == CLCIT_INFO && hitcontact->flags & CLCIIF_CHECKBOX)
+ checkboxWidth = dat->checkboxSize + 2;
+ if (testx > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth)) {
+ if (flags)
+ *flags |= CLCHT_ONITEMCHECK;
+ return hit;
+ }
+ if (testx > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace)) {
+ if (flags)
+ *flags |= CLCHT_ONITEMICON;
+ return hit;
+ }
+ cxSmIcon = GetSystemMetrics(SM_CXSMICON);
+ for (i = 0; i < dat->extraColumnsCount; i++) {
+ if (hitcontact->iExtraImage[i] == 0xFF)
+ continue;
+ if (testx >= dat->extraColumnSpacing * (dat->extraColumnsCount - i) && testx < dat->extraColumnSpacing * (dat->extraColumnsCount - i) + cxSmIcon) {
+ if (flags)
+ *flags |= CLCHT_ONITEMEXTRA | (i << 24);
+ return hit;
+ }
+ }
+ if(hitcontact->extraCacheEntry >= 0 && hitcontact->extraCacheEntry < cfg::nextCacheEntry && cfg::eCache[hitcontact->extraCacheEntry].iExtraValid) {
+ int rightOffset = hitcontact->extraIconRightBegin;
+ int images_present = 0;
+
+ for (i = 5; i >= 0; i--) {
+ if (cfg::eCache[hitcontact->extraCacheEntry].iExtraImage[i] == 0xFF)
+ continue;
+ if(!((1 << i) & cfg::eCache[hitcontact->extraCacheEntry].dwXMask))
+ continue;
+ images_present++;
+ if (testx < right - (rightOffset - (cfg::dat.exIconScale + 2) * images_present) && testx > right - (rightOffset - (cfg::dat.exIconScale + 2) * images_present + (cfg::dat.exIconScale))) {
+ if (flags)
+ *flags |= (CLCHT_ONITEMEXTRAEX | ((i + 1) << 24));
+ return hit;
+ }
+ }
+ }
+
+ hdc = GetDC(hwnd);
+ if (hitcontact->type == CLCIT_GROUP)
+ hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont));
+ else
+ hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_CONTACTS].hFont));
+ GetTextExtentPoint32(hdc, hitcontact->szText, lstrlen(hitcontact->szText), &textSize);
+ width = textSize.cx;
+ if (hitcontact->type == CLCIT_GROUP) {
+ wchar_t *szCounts = pcli->pfnGetGroupCountsText(dat, hitcontact);
+ if (szCounts[0]) {
+ GetTextExtentPoint32W(hdc, L" ", 1, &textSize);
+ width += textSize.cx;
+ SelectObject(hdc, dat->fontInfo[FONTID_GROUPCOUNTS].hFont);
+ GetTextExtentPoint32W(hdc, szCounts, lstrlenW(szCounts), &textSize);
+ width += textSize.cx;
+ }
+ }
+ SelectObject(hdc, hFont);
+ ReleaseDC(hwnd, hdc);
+ if (testx > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0))) {
+ if (flags)
+ *flags |= CLCHT_ONITEMLABEL;
+ return hit;
+ }
+ if (cfg::dat.dwFlags & CLUI_FULLROWSELECT && !(GetKeyState(VK_SHIFT) & 0x8000) && testx < right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0))) {
+ if (flags)
+ *flags |= CLCHT_ONITEMSPACE;
+ return hit;
+ }
+ if (flags)
+ *flags |= CLCHT_NOWHERE;
+ return -1;
+}
+
+/**
+ * peform a hit testing and figure out on which item of a contact row the user clicked.
+ *
+ * @param hwnd clc control window handle
+ * @param dat clc data struct
+ * @param testx x coordinate (mouse)
+ * @param testy y coordinate (mouse)
+ * @param contact affected contact row
+ * @param group contact list group the contact is in
+ * @param flags internal flags
+ * @return DWORD value with flags describing the hit event
+ */
+int CLC::HitTest(HWND hwnd, ClcData *dat, int testx, int testy, ClcContact **contact, ClcGroup **group, DWORD *flags)
+{
+ struct ClcContact *hitcontact = 0;
+ struct ClcGroup *hitgroup = 0;
+ int hit, indent, width, i;
+ int checkboxWidth;
+ SIZE textSize;
+ HDC hdc;
+ RECT clRect;
+ HFONT hFont;
+ DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+ BYTE mirror_mode = cfg::dat.bUseDCMirroring;
+
+ if (flags)
+ *flags = 0;
+ GetClientRect(hwnd, &clRect);
+ if (testx < 0 || testy < 0 || testy >= clRect.bottom || testx >= clRect.right) {
+ if (flags) {
+ if (testx < 0)
+ *flags |= CLCHT_TOLEFT;
+ else if (testx >= clRect.right)
+ *flags |= CLCHT_TORIGHT;
+ if (testy < 0)
+ *flags |= CLCHT_ABOVE;
+ else if (testy >= clRect.bottom)
+ *flags |= CLCHT_BELOW;
+ }
+ return -1;
+ }
+ if (testx < dat->leftMargin) {
+ if (flags)
+ *flags |= CLCHT_INLEFTMARGIN | CLCHT_NOWHERE;
+ return -1;
+ }
+ hit = RowHeight::hitTest(dat, dat->yScroll + testy);
+ if (hit != -1)
+ hit = pcli->pfnGetRowByIndex(dat, hit, &hitcontact, &hitgroup);
+
+ if (hit == -1) {
+ if (flags)
+ *flags |= CLCHT_NOWHERE | CLCHT_BELOWITEMS;
+ return -1;
+ }
+ if (contact)
+ *contact = hitcontact;
+ if (group)
+ *group = hitgroup;
+
+ for (indent = 0; hitgroup->parent; indent++, hitgroup = hitgroup->parent) {
+ ;
+ }
+
+ if(!dat->bisEmbedded) {
+ if(hitcontact->type == CLCIT_CONTACT) {
+ if(mirror_mode == 1 || (mirror_mode == 2 && cfg::eCache[hitcontact->extraCacheEntry].dwCFlags & ECF_RTLNICK))
+ return RTL_HitTest(hwnd, dat, testx, testy, hitcontact, flags, indent, hit);
+ } else if(hitcontact->type == CLCIT_GROUP) {
+ if(cfg::dat.bGroupAlign == CLC_GROUPALIGN_RIGHT || (hitcontact->isRtl && cfg::dat.bGroupAlign == CLC_GROUPALIGN_AUTO))
+ return RTL_HitTest(hwnd, dat, testx, testy, hitcontact, flags, indent, hit);
+ }
+ }
+
+ // avatar check
+ if(hitcontact->type == CLCIT_CONTACT && cfg::dat.dwFlags & CLUI_FRAME_AVATARS && hitcontact->ace != NULL && hitcontact->avatarLeft != -1) {
+ if(testx > hitcontact->avatarLeft && testx < hitcontact->avatarLeft + cfg::dat.avatarSize) {
+ if(flags)
+ *flags |= CLCHT_ONAVATAR;
+ }
+ }
+ if (testx < dat->leftMargin + indent * dat->groupIndent) {
+ if (flags)
+ *flags |= CLCHT_ONITEMINDENT;
+ return hit;
+ }
+ checkboxWidth = 0;
+ if (style & CLS_CHECKBOXES && hitcontact->type == CLCIT_CONTACT)
+ checkboxWidth = dat->checkboxSize + 2;
+ if (style & CLS_GROUPCHECKBOXES && hitcontact->type == CLCIT_GROUP)
+ checkboxWidth = dat->checkboxSize + 2;
+ if (hitcontact->type == CLCIT_INFO && hitcontact->flags & CLCIIF_CHECKBOX)
+ checkboxWidth = dat->checkboxSize + 2;
+ if (testx < dat->leftMargin + indent * dat->groupIndent + checkboxWidth) {
+ if (flags)
+ *flags |= CLCHT_ONITEMCHECK;
+ return hit;
+ }
+ if (testx < dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace) {
+ if (flags)
+ *flags |= CLCHT_ONITEMICON;
+ return hit;
+ }
+
+ int rightOffset = hitcontact->extraIconRightBegin;
+ if (rightOffset) {
+ for (i = dat->extraColumnsCount - 1; i >= 0; i--) {
+ if (hitcontact->iExtraImage[i] == EMPTY_EXTRA_ICON)
+ continue;
+
+ rightOffset -= dat->extraColumnSpacing;
+ if (testx > rightOffset && testx < rightOffset + dat->extraColumnSpacing) {
+ if (flags)
+ *flags |= (CLCHT_ONITEMEXTRA | (i << 24));
+ return hit;
+ }
+ }
+ }
+
+ if (hitcontact->extraCacheEntry >= 0 && hitcontact->extraCacheEntry < cfg::nextCacheEntry && cfg::eCache[hitcontact->extraCacheEntry].iExtraValid) {
+ //int rightOffset = clRect.right;
+ int rightOffset = hitcontact->extraIconRightBegin;
+ int images_present = 0;
+
+ for (i = 5; i >= 0; i--) {
+ if (cfg::eCache[hitcontact->extraCacheEntry].iExtraImage[i] == 0xFF)
+ continue;
+ if(!((1 << i) & cfg::eCache[hitcontact->extraCacheEntry].dwXMask))
+ continue;
+ images_present++;
+ if (testx > (rightOffset - (cfg::dat.exIconScale + 2) * images_present) && testx < (rightOffset - (cfg::dat.exIconScale + 2) * images_present + (cfg::dat.exIconScale))) {
+ if (flags)
+ *flags |= (CLCHT_ONITEMEXTRAEX | ((i + 1) << 24));
+ return hit;
+ }
+ }
+ }
+ hdc = GetDC(hwnd);
+ if (hitcontact->type == CLCIT_GROUP)
+ hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont));
+ else
+ hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_CONTACTS].hFont));
+ GetTextExtentPoint32(hdc, hitcontact->szText, lstrlen(hitcontact->szText), &textSize);
+ width = textSize.cx;
+ if (hitcontact->type == CLCIT_GROUP) {
+ wchar_t *szCounts = pcli->pfnGetGroupCountsText(dat, hitcontact);
+ if (szCounts[0]) {
+ GetTextExtentPoint32W(hdc, L" ", 1, &textSize);
+ width += textSize.cx;
+ SelectObject(hdc, dat->fontInfo[FONTID_GROUPCOUNTS].hFont);
+ GetTextExtentPoint32W(hdc, szCounts, lstrlenW(szCounts), &textSize);
+ width += textSize.cx;
+ }
+ }
+ SelectObject(hdc, hFont);
+ ReleaseDC(hwnd, hdc);
+ if (cfg::dat.dwFlags & CLUI_FULLROWSELECT && !(GetKeyState(VK_SHIFT) & 0x8000) && testx > dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) {
+ if (flags)
+ *flags |= CLCHT_ONITEMSPACE;
+ return hit;
+ }
+ if (testx < dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) {
+ if (flags)
+ *flags |= CLCHT_ONITEMLABEL;
+ return hit;
+ }
+ if (flags)
+ *flags |= CLCHT_NOWHERE;
+ return -1;
+}
+
+void CLC::ScrollTo(HWND hwnd, ClcData *dat, int desty, int noSmooth)
+{
+ DWORD startTick, nowTick;
+ int oldy = dat->yScroll;
+ RECT clRect, rcInvalidate;
+ int maxy, previousy;
+
+ if (dat->iHotTrack != -1 && dat->yScroll != desty) {
+ pcli->pfnInvalidateItem(hwnd, dat, dat->iHotTrack);
+ dat->iHotTrack = -1;
+ ReleaseCapture();
+ }
+ GetClientRect(hwnd, &clRect);
+ rcInvalidate = clRect;
+
+ maxy = RowHeight::getTotalHeight(dat) - clRect.bottom;
+ if (desty > maxy)
+ desty = maxy;
+ if (desty < 0)
+ desty = 0;
+ if (abs(desty - dat->yScroll) < 4)
+ noSmooth = 1;
+ if (!noSmooth && dat->exStyle & CLS_EX_NOSMOOTHSCROLLING)
+ noSmooth = 1;
+ previousy = dat->yScroll;
+ if (!noSmooth) {
+ startTick = GetTickCount();
+ for (; ;) {
+ nowTick = GetTickCount();
+ if (nowTick >= startTick + dat->scrollTime)
+ break;
+ dat->yScroll = oldy + (desty - oldy) * (int) (nowTick - startTick) / dat->scrollTime;
+ ScrollWindowEx(hwnd, 0, previousy - dat->yScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE);
+ previousy = dat->yScroll;
+ CoolSB_SetScrollPos(hwnd, SB_VERT, dat->yScroll, TRUE);
+ UpdateWindow(hwnd);
+ }
+ }
+ dat->yScroll = desty;
+ if(!noSmooth)
+ ScrollWindowEx(hwnd, 0, previousy - dat->yScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE);
+ else
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ CoolSB_SetScrollPos(hwnd, SB_VERT, dat->yScroll, TRUE);
+ dat->forceScroll = 0;
+}
+
+void CLC::RecalcScrollBar(HWND hwnd, ClcData *dat)
+{
+ SCROLLINFO si = { 0 };
+ RECT clRect;
+ NMCLISTCONTROL nm;
+
+ RowHeight::calcRowHeights(dat, hwnd, dat->ph);
+
+ GetClientRect(hwnd, &clRect);
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = pcli->pfnGetRowTotalHeight(dat) - 1;
+ si.nPage = clRect.bottom;
+ si.nPos = dat->yScroll;
+
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_CONTACTLIST) {
+ if (dat->noVScrollbar == 0) {
+ if (cfg::dat.bSkinnedScrollbar && !dat->bisEmbedded)
+ CoolSB_SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ else
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ }
+ }
+ else {
+ if (cfg::dat.bSkinnedScrollbar && !dat->bisEmbedded)
+ CoolSB_SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ else
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ }
+ ScrollTo(hwnd, dat, dat->yScroll, 1);
+ nm.hdr.code = CLN_LISTSIZECHANGE;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.pt.y = si.nMax;
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)& nm);
+}
+
+void SetGroupExpand(HWND hwnd, struct ClcData *dat, struct ClcGroup *group, int newState)
+{
+ int contentCount;
+ int groupy;
+ int newy;
+ int posy;
+ RECT clRect;
+ NMCLISTCONTROL nm;
+
+ if (newState == -1)
+ group->expanded ^= 1;
+ else {
+ if (group->expanded == (newState != 0))
+ return;
+ group->expanded = newState != 0;
+ }
+ InvalidateRect(hwnd, NULL, FALSE);
+ contentCount = pcli->pfnGetGroupContentsCount(group, 1);
+
+ groupy = pcli->pfnGetRowsPriorTo(&dat->list, group, -1);
+ if(dat->selection > groupy && dat->selection < groupy + contentCount) dat->selection = groupy;
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+
+ GetClientRect(hwnd, &clRect);
+ newy = dat->yScroll;
+ posy = RowHeight::getItemBottomY(dat, groupy + contentCount);
+ if(posy >= newy + clRect.bottom)
+ newy = posy - clRect.bottom;
+ posy = RowHeight::getItemTopY(dat, groupy);
+ if(newy > posy) newy = posy;
+ CLC::ScrollTo(hwnd, dat, newy, 0);
+
+ nm.hdr.code = CLN_EXPANDED;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.hItem = (HANDLE)group->groupId;
+ nm.action = (group->expanded);
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&nm);
+}
+
+static WNDPROC OldRenameEditWndProc;
+static LRESULT CALLBACK RenameEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_KEYDOWN:
+ switch (wParam) {
+ case VK_RETURN:
+ pcli->pfnEndRename(GetParent(hwnd), (struct ClcData *) GetWindowLongPtr(GetParent(hwnd), 0), 1);
+ return 0;
+ case VK_ESCAPE:
+ pcli->pfnEndRename(GetParent(hwnd), (struct ClcData *) GetWindowLongPtr(GetParent(hwnd), 0), 0);
+ return 0;
+ }
+ break;
+
+ /*
+ * same as with embedded frames... let the richedit paint itself and
+ * capture it to the buffered paint DC.
+ */
+ case WM_PAINT: {
+ HDC hdc = GetDC(hwnd);
+ HDC hdcMem;
+ RECT rc;
+ HANDLE hbp = 0;
+
+ GetClientRect(hwnd, &rc);
+ INIT_PAINT(hdc, rc, hdcMem);
+ CallWindowProc(OldRenameEditWndProc, hwnd, msg, wParam, lParam);
+ Gfx::drawBGFromSurface(hwnd, rc, hdcMem);
+ BitBlt(hdcMem, 0, 0, rc.right, rc.bottom, hdc, 0, 0, SRCCOPY | CAPTUREBLT);
+ FINALIZE_PAINT(hbp, &rc, 255);
+ ReleaseDC(hwnd, hdc);
+ return(0);
+ }
+
+ case WM_GETDLGCODE:
+ if (lParam) {
+ MSG *msg = (MSG *) lParam;
+ if (msg->message == WM_KEYDOWN && msg->wParam == VK_TAB)
+ return 0;
+ if (msg->message == WM_CHAR && msg->wParam == '\t')
+ return 0;
+ }
+ return DLGC_WANTMESSAGE;
+ case WM_KILLFOCUS:
+ pcli->pfnEndRename(GetParent(hwnd), (struct ClcData *) GetWindowLongPtr(GetParent(hwnd), 0), 1);
+ return 0;
+ }
+ return CallWindowProc(OldRenameEditWndProc, hwnd, msg, wParam, lParam);
+}
+
+void CLC::BeginRenameSelection(HWND hwnd, ClcData *dat)
+{
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ int indent, x, y, h;
+ RECT clRect;
+
+ KillTimer(hwnd, TIMERID_RENAME);
+ ReleaseCapture();
+ dat->iHotTrack = -1;
+ dat->selection = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, &group);
+ if (dat->selection == -1)
+ return;
+ if (contact->type != CLCIT_CONTACT && contact->type != CLCIT_GROUP)
+ return;
+ for (indent = 0; group->parent; indent++, group = group->parent) {
+ ;
+ }
+ GetClientRect(hwnd, &clRect);
+ x = indent * dat->groupIndent + dat->iconXSpace - 2;
+ //y = dat->selection * dat->rowHeight - dat->yScroll;
+ y = RowHeight::getItemTopY(dat, dat->selection) - dat->yScroll;
+
+ h = dat->row_heights[dat->selection];
+ {
+ int i;
+ for (i = 0; i <= FONTID_LAST; i++)
+ if (h < dat->fontInfo[i].fontHeight + 2) h = dat->fontInfo[i].fontHeight + 2;
+ }
+ dat->hwndRenameEdit = CreateWindowEx(0, _T("RichEdit20W"), contact->szText, WS_CHILD | WS_BORDER | ES_MULTILINE | ES_AUTOHSCROLL, x, y, clRect.right - x, h, hwnd, NULL, g_hInst, NULL);
+ {
+ if((contact->type == CLCIT_CONTACT && cfg::eCache[contact->extraCacheEntry].dwCFlags & ECF_RTLNICK) || (contact->type == CLCIT_GROUP && contact->isRtl)) {
+ PARAFORMAT2 pf2;
+ ZeroMemory((void *)&pf2, sizeof(pf2));
+ pf2.cbSize = sizeof(pf2);
+ pf2.dwMask = PFM_RTLPARA;
+ pf2.wEffects = PFE_RTLPARA;
+ SetWindowText(dat->hwndRenameEdit, _T(""));
+ SendMessage(dat->hwndRenameEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ SetWindowText(dat->hwndRenameEdit, contact->szText);
+ }
+ }
+ //dat->hwndRenameEdit = CreateWindow(_T("EDIT"), contact->szText, WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, x, y, clRect.right - x, dat->rowHeight, hwnd, NULL, g_hInst, NULL);
+ OldRenameEditWndProc = (WNDPROC) SetWindowLongPtr(dat->hwndRenameEdit, GWLP_WNDPROC, (LONG_PTR) RenameEditSubclassProc);
+ SendMessage(dat->hwndRenameEdit, WM_SETFONT, (WPARAM) (contact->type == CLCIT_GROUP ? dat->fontInfo[FONTID_GROUPS].hFont : dat->fontInfo[FONTID_CONTACTS].hFont), 0);
+ SendMessage(dat->hwndRenameEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN | EC_USEFONTINFO, 0);
+ SendMessage(dat->hwndRenameEdit, EM_SETSEL, 0, (LPARAM) (-1));
+ ShowWindow(dat->hwndRenameEdit, SW_SHOW);
+ SetFocus(dat->hwndRenameEdit);
+}
+
+void CLC::LoadClcOptions(HWND hwnd, ClcData *dat, BOOL first)
+{
+ HDC hdc = GetDC(hwnd);
+ for (int i = 0; i <= FONTID_MAX; i++) {
+ if (!dat->fontInfo[i].changed)
+ DeleteObject(dat->fontInfo[i].hFont);
+
+ LOGFONT lf;
+ pcli->pfnGetFontSetting(i, &lf, &dat->fontInfo[i].colour);
+ lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+
+ dat->fontInfo[i].hFont = CreateFontIndirect(&lf);
+ dat->fontInfo[i].changed = 0;
+
+ HFONT holdfont = (HFONT)SelectObject(hdc, dat->fontInfo[i].hFont);
+ SIZE fontSize;
+ GetTextExtentPoint32(hdc, _T("x"), 1, &fontSize);
+ SelectObject(hdc, holdfont);
+
+ dat->fontInfo[i].fontHeight = fontSize.cy;
+ }
+ ReleaseDC(hwnd, hdc);
+ dat->min_row_heigh = (int)cfg::getByte("CLC", "RowHeight", CLCDEFAULT_ROWHEIGHT);
+ dat->group_row_height = (int)cfg::getByte("CLC", "GRowHeight", CLCDEFAULT_ROWHEIGHT);
+ dat->row_border = 0;
+ dat->rightMargin = cfg::getByte("CLC", "RightMargin", CLCDEFAULT_LEFTMARGIN);
+ dat->bkColour = cfg::getDword("CLC", "BkColour", GetSysColor(COLOR_WINDOW));
+ if(cfg::dat.hBrushCLCBk)
+ DeleteObject(cfg::dat.hBrushCLCBk);
+ cfg::dat.hBrushCLCBk = CreateSolidBrush(dat->bkColour);
+
+ coreCli.pfnLoadClcOptions(hwnd, dat, first);
+
+ if(cfg::dat.hBrushCLCGroupsBk)
+ DeleteObject(cfg::dat.hBrushCLCGroupsBk);
+ cfg::dat.hBrushCLCGroupsBk = CreateSolidBrush(cfg::getDword("CLC", "BkColourGroups", GetSysColor(COLOR_3DFACE)));
+ DSP_LoadFromDefaults(&dsp_default);
+}
diff --git a/plugins/Clist_ng/SRC/clistevents.cpp b/plugins/Clist_ng/SRC/clistevents.cpp new file mode 100644 index 0000000000..e477a34bdf --- /dev/null +++ b/plugins/Clist_ng/SRC/clistevents.cpp @@ -0,0 +1,455 @@ +/*
+ * 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: clistevents.cpp 134 2010-10-01 10:23:10Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+
+static HWND hwndEventFrame = 0;
+
+extern FRAMEWND *wndFrameEventArea;
+
+extern HPEN g_hPenCLUIFrames;
+
+HWND g_hwndEventArea = 0;
+
+struct CListEvent {
+ int imlIconIndex;
+ int flashesDone;
+ CLISTEVENT cle;
+
+ int menuId;
+ int imlIconOverlayIndex;
+};
+
+struct CListImlIcon {
+ int index;
+ HICON hIcon;
+};
+
+static int iconsOn;
+
+HANDLE hNotifyFrame = (HANDLE) - 1;
+
+CListEvent* CLC::fnCreateEvent()
+{
+ CListEvent *p = reinterpret_cast<CListEvent *>(mir_alloc(sizeof(struct CListEvent)));
+ if(p)
+ ZeroMemory(p, sizeof(struct CListEvent));
+
+ return p;
+}
+
+void CLUI::hideShowNotifyFrame()
+{
+ int dwVisible = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hNotifyFrame), 0) & F_VISIBLE;
+ int desired;
+
+ if(cfg::dat.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
+ desired = cfg::dat.notifyActive ? TRUE : FALSE;
+ else
+ desired = dwVisible;
+
+ if(desired) {
+ if(!dwVisible)
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
+ } else {
+ if(dwVisible)
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
+ }
+}
+
+static CLISTEVENT* MyGetEvent(int iSelection)
+{
+ int i;
+
+ for(i = 0; i < pcli->events.count; i++) {
+ struct CListEvent* p = pcli->events.items[i];
+ if(p->menuId == iSelection)
+ return &p->cle;
+ }
+ return NULL;
+}
+
+/**
+ * paint content of the event area frame
+ * @param hDC device context to use
+ * @param rc target rectangle (client coordinates)
+ * @param hTheme UxTheme handle to use for drawing text
+ */
+void PaintNotifyArea(HDC hDC, RECT *rc, HANDLE hTheme)
+{
+ int iCount;
+ static int ev_lastIcon = 0;
+
+ rc->left += 26; // button
+ iCount = GetMenuItemCount(cfg::dat.hMenuNotify);
+ if(cfg::dat.hUpdateContact != 0) {
+ wchar_t *szName = pcli->pfnGetContactDisplayName(cfg::dat.hUpdateContact, 0);
+ int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) cfg::dat.hUpdateContact, 0);
+
+ ImageList_DrawEx(CLC::hClistImages, iIcon, hDC, rc->left, (rc->bottom + rc->top - CYSMICON) / 2, CXSMICON, CYSMICON, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rc->left += 18;
+ Gfx::renderText(hDC, hTheme, szName, rc, DT_VCENTER | DT_SINGLELINE, 0);
+ ImageList_DrawEx(CLC::hClistImages, (int)cfg::dat.hIconNotify, hDC, 4, (rc->bottom + rc->top - 16) / 2, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ ev_lastIcon = cfg::dat.hIconNotify;
+ } else if(iCount > 0) {
+ MENUITEMINFO mii = {0};
+ struct NotifyMenuItemExData *nmi;
+ wchar_t *szName;
+ int iIcon;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ GetMenuItemInfo(cfg::dat.hMenuNotify, iCount - 1, TRUE, &mii);
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ szName = pcli->pfnGetContactDisplayName(nmi->hContact, 0);
+ iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);
+ ImageList_DrawEx(CLC::hClistImages, iIcon, hDC, rc->left, (rc->bottom + rc->top - CYSMICON) / 2, CXSMICON, CYSMICON, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rc->left += 18;
+ ImageList_DrawEx(CLC::hClistImages, nmi->iIcon, hDC, 4, (rc->bottom + rc->top) / 2 - 8, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ Gfx::renderText(hDC, hTheme, szName, rc, DT_VCENTER | DT_SINGLELINE, 0);
+ ev_lastIcon = (int)nmi->hIcon;
+ } else
+ Gfx::renderText(hDC, hTheme, cfg::dat.szNoEvents, rc, DT_VCENTER | DT_SINGLELINE, 0);
+}
+
+/**
+ * this handles the subclassing for the event area frame.
+ */
+LRESULT CALLBACK CLUI::eventAreaWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_CREATE: {
+ hwndEventFrame = hwnd;
+ return FALSE;
+ }
+ case WM_MEASUREITEM: {
+ MEASUREITEMSTRUCT *lpi = (LPMEASUREITEMSTRUCT) lParam;
+ MENUITEMINFOA mii = {0};
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA | MIIM_ID;
+ if(GetMenuItemInfoA(cfg::dat.hMenuNotify, lpi->itemID, FALSE, &mii) != 0) {
+ if(mii.dwItemData == lpi->itemData) {
+ lpi->itemWidth = 8 + 16;
+ lpi->itemHeight = 0;
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case WM_NCCALCSIZE:
+ return FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam,
+ wndFrameEventArea ? wndFrameEventArea->TitleBar.ShowTitleBar : 0);
+ case WM_NCPAINT:
+ return FrameNCPaint(hwnd, DefWindowProc, wParam, lParam,
+ wndFrameEventArea ? wndFrameEventArea->TitleBar.ShowTitleBar : 0);
+ case WM_DRAWITEM: {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
+
+ if(dis->hwndItem == (HWND) cfg::dat.hMenuNotify) {
+ MENUITEMINFOA mii = {0};
+
+ struct NotifyMenuItemExData *nmi = 0;
+ int iIcon;
+ HICON hIcon;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if(GetMenuItemInfoA(cfg::dat.hMenuNotify, (UINT) dis->itemID, FALSE, &mii) != 0) {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if(nmi) {
+ iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);
+ hIcon = ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL);
+ pcli->pfnDrawMenuItem(dis, hIcon, nmi->hIcon);
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ case WM_LBUTTONUP:
+ if(cfg::dat.bEventAreaEnabled)
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0);
+ break;
+ case WM_COMMAND:
+ if(LOWORD(wParam) == IDC_NOTIFYBUTTON) {
+ int iSelection;
+ MENUITEMINFO mii = {0};
+ POINT pt;
+ struct NotifyMenuItemExData *nmi = 0;
+ int iCount = GetMenuItemCount(cfg::dat.hMenuNotify);
+ BOOL result;
+
+ GetCursorPos(&pt);
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if(iCount > 1)
+ iSelection = TrackPopupMenu(cfg::dat.hMenuNotify, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
+ else
+ iSelection = GetMenuItemID(cfg::dat.hMenuNotify, 0);
+ result = GetMenuItemInfo(cfg::dat.hMenuNotify, (UINT) iSelection, FALSE, &mii);
+ if(result != 0) {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if(nmi) {
+ CLISTEVENT *cle = MyGetEvent(iSelection);
+ if(cle) {
+ CLISTEVENT *cle1 = NULL;
+ CallService(cle->pszService, (WPARAM) NULL, (LPARAM) cle);
+ // re-obtain the pointer, it may already be invalid/point to another event if the
+ // event we're interested in was removed by the service (nasty one...)
+ cle1 = MyGetEvent(iSelection);
+ if(cle1 != NULL)
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM) cle->hContact, (LPARAM) cle->hDbEvent);
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_LBUTTONDOWN: {
+ POINT ptMouse, pt;
+ RECT rcClient;
+
+ if((GetKeyState(VK_CONTROL) & 0x8000) && wndFrameEventArea->floating) {
+ GetCursorPos(&ptMouse);
+ pt = ptMouse;
+ ScreenToClient(hwnd, &ptMouse);
+ GetClientRect(hwnd, &rcClient);
+ return SendMessage(GetParent(hwnd), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y));
+ }
+ break;
+ }
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ RECT rc, rcClient;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ LONG dwLeft;
+ HDC hdcMem;
+ HANDLE hbp = 0;
+ TStatusItem* item;
+ HFONT hFontOld = 0;
+ HANDLE hTheme = Api::pfnOpenThemeData(hwnd, L"BUTTON");
+
+ GetClientRect(hwnd, &rc);
+ rcClient = rc;
+ if(wndFrameEventArea->floating) {
+ hdcMem = hdc;
+ FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_3DFACE));
+ } else
+ INIT_PAINT(hdc, rcClient, hdcMem);
+
+ SetBkMode(hdcMem, TRANSPARENT);
+
+ if(cfg::clcdat)
+ hFontOld = reinterpret_cast<HFONT>(SelectObject(hdcMem, cfg::clcdat->fontInfo[FONTID_EVENTAREA].hFont));
+
+ Gfx::drawBGFromSurface(hwnd, rc, hdcMem);
+ item = &Skin::statusItems[ID_EXTBKEVTAREA];
+ if(!item->IGNORED) {
+ rc.top += item->MARGIN_TOP;
+ rc.bottom -= item->MARGIN_BOTTOM;
+ rc.left += item->MARGIN_LEFT;
+ rc.right -= item->MARGIN_RIGHT;
+
+ Gfx::renderSkinItem(hdcMem, &rc, item->imageItem);
+ Gfx::setTextColor(item->TEXTCOLOR);
+ }
+
+ dwLeft = rc.left;
+
+ PaintNotifyArea(hdcMem, &rc, hTheme);
+ if(hFontOld)
+ SelectObject(hdcMem, hFontOld);
+
+ if(hbp)
+ FINALIZE_PAINT(hbp, &rcClient, 0);
+
+ ps.fErase = FALSE;
+ EndPaint(hwnd, &ps);
+ if(hTheme)
+ Api::pfnCloseThemeData(hTheme);
+ return 0;
+ }
+ default:
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+CListEvent* CLC::AddEvent(CLISTEVENT *cle)
+{
+ CListEvent* p = coreCli.pfnAddEvent(cle);
+ if(p == NULL)
+ return NULL;
+
+ if(p->cle.hContact != 0 && p->cle.hDbEvent != (MEVENT) 1 && !(p->cle.flags & CLEF_ONLYAFEW)) {
+ int j;
+ struct NotifyMenuItemExData *nmi = 0;
+ char *szProto;
+ wchar_t *szName;
+ MENUITEMINFOW mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA | MIIM_BITMAP | MIIM_ID;
+ if(p->cle.pszService && !strncmp("SRMsg/ReadMessage", p->cle.pszService, 17)) {
+ // dup check only for msg events
+ for(j = 0; j < GetMenuItemCount(cfg::dat.hMenuNotify); j++) {
+ if(GetMenuItemInfo(cfg::dat.hMenuNotify, j, TRUE, &mii) != 0) {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if(nmi != 0 && (HANDLE) nmi->hContact == (HANDLE) p->cle.hContact && nmi->iIcon == p->imlIconIndex)
+ return p;
+ }
+ }
+ }
+
+ szProto = GetContactProto(p->cle.hContact);
+ szName = pcli->pfnGetContactDisplayName(p->cle.hContact, 0);
+ if(szProto && szName) {
+ nmi = (struct NotifyMenuItemExData *) malloc(sizeof(struct NotifyMenuItemExData));
+ if(nmi) {
+ wchar_t szBuffer[128];
+ wchar_t* szStatus = pcli->pfnGetStatusModeDescription(cfg::getWord(p->cle.hContact, szProto, "Status", ID_STATUS_OFFLINE), 0);
+ wchar_t szwProto[64];
+ MultiByteToWideChar(CP_ACP, 0, szProto, -1, szwProto, 64);
+ szwProto[63] = 0;
+ _snwprintf(szBuffer, _countof(szBuffer), L"%s: %s (%s)", szwProto, szName, szStatus);
+ szBuffer[127] = 0;
+ AppendMenu(cfg::dat.hMenuNotify, MF_BYCOMMAND | MF_STRING, cfg::dat.wNextMenuID, szBuffer);
+ mii.hbmpItem = HBMMENU_CALLBACK;
+ nmi->hContact = p->cle.hContact;
+ nmi->iIcon = p->imlIconIndex;
+ nmi->hIcon = p->cle.hIcon;
+ nmi->hDbEvent = p->cle.hDbEvent;
+ mii.dwItemData = (ULONG_PTR) nmi;
+ mii.wID = cfg::dat.wNextMenuID;
+ SetMenuItemInfo(cfg::dat.hMenuNotify, cfg::dat.wNextMenuID, FALSE, &mii);
+ p-> menuId = cfg::dat.wNextMenuID;
+ cfg::dat.wNextMenuID++;
+ if(cfg::dat.wNextMenuID > 0x7fff)
+ cfg::dat.wNextMenuID = 1;
+ cfg::dat.hIconNotify = p->imlIconIndex;
+ }
+ }
+ } else if(p->cle.hContact != 0 && (p->cle.flags & CLEF_ONLYAFEW)) {
+ cfg::dat.hIconNotify = p->imlIconIndex;
+ cfg::dat.hUpdateContact = p->cle.hContact;
+ }
+ if(cfg::dat.dwFlags & CLUI_STICKYEVENTS) {
+ HANDLE hItem = (HANDLE) SendMessage(pcli->hwndContactTree, CLM_FINDCONTACT, (WPARAM) p->cle.hContact, 0);
+ if(hItem) {
+ SendMessage(pcli->hwndContactTree, CLM_SETSTICKY, (WPARAM) hItem, 1);
+ pcli->pfnClcBroadcast(INTM_PROTOCHANGED, (WPARAM) p->cle.hContact, 0);
+ }
+ }
+ if(pcli->events.count > 0) {
+ cfg::dat.bEventAreaEnabled = TRUE;
+ if(cfg::dat.notifyActive == 0) {
+ cfg::dat.notifyActive = 1;
+ CLUI::hideShowNotifyFrame();
+ }
+ }
+ InvalidateRect(hwndEventFrame, NULL, FALSE);
+ if(cfg::dat.bUseFloater & CLUI_USE_FLOATER && cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS)
+ SFL_Update(0, 0, 0, NULL, FALSE);
+
+ return p;
+}
+
+// Removes an event from the contact list's queue
+// wParam=(WPARAM)(HANDLE)hContact
+// lParam=(LPARAM)(HANDLE)hDbEvent
+// Returns 0 if the event was successfully removed, or nonzero if the event was not found
+int CLC::RemoveEvent(MCONTACT hContact, MEVENT hDbEvent)
+{
+ HANDLE hItem;
+ int i;
+ BOOL bUnstick = TRUE;
+
+ // Find the event that should be removed
+ for(i = 0; i < pcli->events.count; i++) {
+ if((pcli->events.items[i]->cle.hContact == hContact) && (pcli->events.items[i]->cle.hDbEvent == hDbEvent)) {
+ break;
+ }
+ }
+
+ // Event was not found
+ if(i == pcli->events.count)
+ return 1;
+
+ // remove event from the notify menu
+ if(pcli->events.items[i]->menuId > 0) {
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if(GetMenuItemInfo(cfg::dat.hMenuNotify, pcli->events.items[i]->menuId, FALSE, &mii) != 0) {
+ struct NotifyMenuItemExData *nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if(nmi && nmi->hContact == hContact && nmi->hDbEvent == hDbEvent) {
+ free(nmi);
+ DeleteMenu(cfg::dat.hMenuNotify, pcli->events.items[i]->menuId, MF_BYCOMMAND);
+ }
+ }
+ }
+
+ coreCli.pfnRemoveEvent(hContact, hDbEvent);
+
+ if(pcli->events.count == 0) {
+ cfg::dat.bEventAreaEnabled = FALSE;
+ if(cfg::dat.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY) {
+ cfg::dat.notifyActive = 0;
+ CLUI::hideShowNotifyFrame();
+ }
+ }
+
+ if(bUnstick) {
+ // clear "sticky" (sort) status
+
+ hItem = (HANDLE) SendMessage(pcli->hwndContactTree, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem) {
+ SendMessage(pcli->hwndContactTree, CLM_SETSTICKY, (WPARAM) hItem, 0);
+ pcli->pfnClcBroadcast(INTM_PROTOCHANGED, (WPARAM)hContact, 0);
+ }
+ }
+
+ if(hContact == cfg::dat.hUpdateContact || (INT_PTR)hDbEvent == 1)
+ cfg::dat.hUpdateContact = 0;
+
+ if(cfg::dat.notifyActive) {
+ InvalidateRect(hwndEventFrame, NULL, FALSE);
+ if(cfg::dat.bUseFloater & CLUI_USE_FLOATER && cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS)
+ SFL_Update(0, 0, 0, NULL, FALSE);
+ }
+
+ return 0;
+}
diff --git a/plugins/Clist_ng/SRC/clistmenus.cpp b/plugins/Clist_ng/SRC/clistmenus.cpp new file mode 100644 index 0000000000..6b3f0ea92e --- /dev/null +++ b/plugins/Clist_ng/SRC/clistmenus.cpp @@ -0,0 +1,469 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+*/
+
+#include <commonheaders.h>
+
+#pragma hdrstop
+
+static HMENU hMainMenu, hMainStatusMenu;
+static MWindowList hWindowListIGN = 0;
+
+void DestroyTrayMenu(HMENU hMenu)
+{
+ int i, cnt;
+
+ cnt = GetMenuItemCount(hMenu);
+ for (i=0; i<cnt; ++i)
+ {
+ HMENU hSubMenu = GetSubMenu(hMenu, i);
+ if (hSubMenu == hMainStatusMenu || hSubMenu == hMainMenu)
+ RemoveMenu(hMenu, i--, MF_BYPOSITION);
+ }
+ DestroyMenu(hMenu);
+}
+
+INT_PTR CloseAction(WPARAM wParam,LPARAM lParam)
+{
+ int k;
+ cfg::shutDown = 1;
+ k=CallService(MS_SYSTEM_OKTOEXIT,(WPARAM)0,(LPARAM)0);
+ if (k) {
+ DestroyWindow(pcli->hwndContactList);
+ PostQuitMessage(0);
+ Sleep(0);
+ }
+
+ return(0);
+}
+
+static const UINT xImgCtrlIds[] = {
+ IDC_EXTRA_ICON_RES0,
+ IDC_EXTRA_ICON_EMAIL,
+ IDC_EXTRA_ICON_RES1,
+ IDC_EXTRA_ICON_SMS,
+ IDC_EXTRA_ICON_ADV1,
+ IDC_EXTRA_ICON_ADV2,
+ IDC_EXTRA_ICON_WEB,
+ IDC_EXTRA_ICON_CLIENT,
+ IDC_EXTRA_ICON_RES2,
+ IDC_EXTRA_ICON_ADV3,
+ IDC_EXTRA_ICON_ADV4
+};
+
+static const UINT xImgCtrlBits[] = {
+ EXTRA_ICON_RES0,
+ EXTRA_ICON_EMAIL,
+ EXTRA_ICON_RES1,
+ EXTRA_ICON_SMS,
+ EXTRA_ICON_ADV1,
+ EXTRA_ICON_ADV2,
+ EXTRA_ICON_WEB,
+ EXTRA_ICON_CLIENT,
+ EXTRA_ICON_RES2,
+ EXTRA_ICON_ADV3,
+ EXTRA_ICON_ADV4
+};
+
+
+static INT_PTR CALLBACK IgnoreDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ MCONTACT hContact = (MCONTACT)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ DWORD dwMask;
+ struct ClcContact *contact = NULL;
+ int pCaps;
+ HWND hwndAdd;
+
+ hContact = lParam;
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)hContact);
+ dwMask = cfg::getDword(hContact, "Ignore", "Mask1", 0);
+ SendMessage(hWnd, WM_USER + 100, (WPARAM)hContact, dwMask);
+ SendMessage(hWnd, WM_USER + 120, 0, 0);
+ TranslateDialogDefault(hWnd);
+ hwndAdd = GetDlgItem(hWnd, IDC_IGN_ADDPERMANENTLY); // CreateWindowEx(0, _T("CLCButtonClass"), _T("FOO"), WS_VISIBLE | BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, 200, 276, 106, 24, hWnd, (HMENU)IDC_IGN_ADDPERMANENTLY, g_hInst, NULL);
+ SendMessage(hwndAdd, BUTTONSETASFLATBTN, 0, 1);
+ SendMessage(hwndAdd, BUTTONSETASFLATBTN + 10, 0, 1);
+
+ SendMessage(hwndAdd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadIcon(SKINICON_OTHER_ADDCONTACT));
+ SetWindowText(hwndAdd, TranslateT("Add permanently"));
+ EnableWindow(hwndAdd, cfg::getByte(hContact, "CList", "NotOnList", 0));
+
+ hwndAdd = GetDlgItem(hWnd, IDC_DSP_LOADDEFAULT); // CreateWindowEx(0, _T("CLCButtonClass"), _T("FOO"), WS_VISIBLE | BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, 200, 276, 106, 24, hWnd, (HMENU)IDC_IGN_ADDPERMANENTLY, g_hInst, NULL);
+ SendMessage(hwndAdd, BUTTONSETASFLATBTN, 0, 1);
+ SendMessage(hwndAdd, BUTTONSETASFLATBTN + 10, 0, 1);
+
+ SendMessage(hwndAdd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadIcon(SKINICON_OTHER_DELETE));
+ SetWindowText(hwndAdd, TranslateT("Revert to default"));
+ EnableWindow(hwndAdd, TRUE);
+
+ SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Default (global setting)"));
+ SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Show always when available"));
+ SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Hide always"));
+
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Default (global setting)"));
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Never"));
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always"));
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("When space is available"));
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("When needed by status message"));
+
+ if(cfg::clcdat) {
+ CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)hContact, &contact, NULL, NULL);
+ if(contact && contact->type != CLCIT_CONTACT) {
+ DestroyWindow(hWnd);
+ return FALSE;
+ } else {
+ wchar_t szTitle[512];
+ DWORD dwFlags = cfg::getDword(hContact, "CList", "CLN_Flags", 0);
+ BYTE bSecondLine = cfg::getByte(hContact, "CList", "CLN_2ndline", -1);
+ DWORD dwXMask = cfg::getDword(hContact, "CList", "CLN_xmask", 0);
+ int i = 0;
+
+ mir_sntprintf(szTitle, 512, TranslateT("Contact list display and ignore options for %s"), contact ? contact->szText : pcli->pfnGetContactDisplayName(hContact, 0));
+
+ SetWindowText(hWnd, szTitle);
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)Skin_LoadIcon(SKINICON_OTHER_MIRANDA));
+ pCaps = CallProtoService(contact ? contact->proto : GetContactProto(hContact), PS_GETCAPS, PFLAGNUM_1, 0);
+ Utils::enableDlgControl(hWnd, IDC_IGN_ALWAYSONLINE, pCaps & PF1_INVISLIST ? TRUE : FALSE);
+ Utils::enableDlgControl(hWnd, IDC_IGN_ALWAYSOFFLINE, pCaps & PF1_VISLIST ? TRUE : FALSE);
+ CheckDlgButton(hWnd, IDC_IGN_PRIORITY, cfg::getByte(hContact, "CList", "Priority", 0) ? 1 : 0);
+ Utils::enableDlgControl(hWnd, IDC_IGN_PRIORITY, TRUE);
+ Utils::enableDlgControl(hWnd, IDC_AVATARDISPMODE, TRUE);
+ Utils::enableDlgControl(hWnd, IDC_SECONDLINEMODE, TRUE);
+ if(dwFlags & ECF_FORCEAVATAR)
+ SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 1, 0);
+ else if(dwFlags & ECF_HIDEAVATAR)
+ SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 2, 0);
+ else
+ SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 0, 0);
+
+ if(dwFlags & ECF_FORCEOVERLAY)
+ SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_CHECKED, 0);
+ else if(dwFlags & ECF_HIDEOVERLAY)
+ SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_UNCHECKED, 0);
+ else
+ SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_INDETERMINATE, 0);
+
+ if(dwFlags & ECF_FORCELOCALTIME)
+ SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_SETCHECK, BST_CHECKED, 0);
+ else if(dwFlags & ECF_HIDELOCALTIME)
+ SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_SETCHECK, BST_UNCHECKED, 0);
+ else
+ SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_SETCHECK, BST_INDETERMINATE, 0);
+
+ if(dwFlags & ECF_FORCEVISIBILITY)
+ SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_CHECKED, 0);
+ else if(dwFlags & ECF_HIDEVISIBILITY)
+ SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_UNCHECKED, 0);
+ else
+ SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_INDETERMINATE, 0);
+
+ while(xImgCtrlIds[i] != 0) {
+ if(dwXMask & (1 << (2 * xImgCtrlBits[i])))
+ SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_SETCHECK, BST_CHECKED, 0);
+ else if(dwXMask & (1 << (2 * xImgCtrlBits[i] + 1)))
+ SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_SETCHECK, BST_UNCHECKED, 0);
+ else
+ SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_SETCHECK, BST_INDETERMINATE, 0);
+ i++;
+ }
+
+ if(bSecondLine == 0xff)
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_SETCURSEL, 0, 0);
+ else
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_SETCURSEL, (WPARAM)(bSecondLine + 1), 0);
+ }
+ }
+ WindowList_Add(hWindowListIGN, hWnd, hContact);
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_IGN_PRIORITY:
+ SendMessage(pcli->hwndContactTree, CLM_TOGGLEPRIORITYCONTACT, (WPARAM)hContact, 0);
+ return 0;
+ case IDC_IGN_ALL:
+ SendMessage(hWnd, WM_USER + 100, (WPARAM)hContact, (LPARAM)0xffffffff);
+ return 0;
+ case IDC_IGN_NONE:
+ SendMessage(hWnd, WM_USER + 100, (WPARAM)hContact, (LPARAM)0);
+ return 0;
+ case IDC_IGN_ALWAYSONLINE:
+ if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSONLINE))
+ CheckDlgButton(hWnd, IDC_IGN_ALWAYSOFFLINE, FALSE);
+ break;
+ case IDC_IGN_ALWAYSOFFLINE:
+ if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSOFFLINE))
+ CheckDlgButton(hWnd, IDC_IGN_ALWAYSONLINE, FALSE);
+ break;
+ case IDC_HIDECONTACT:
+ cfg::writeByte(hContact, "CList", "Hidden", (BYTE)(IsDlgButtonChecked(hWnd, IDC_HIDECONTACT) ? 1 : 0));
+ break;
+ case IDC_IGN_ADDPERMANENTLY:
+ {
+ ADDCONTACTSTRUCT acs = {0};
+
+ acs.hContact = hContact;
+ acs.handleType = HANDLE_CONTACT;
+ acs.szProto = 0;
+ CallService(MS_ADDCONTACT_SHOW, (WPARAM)hWnd, (LPARAM)&acs);
+ Utils::enableDlgControl(hWnd, IDC_IGN_ADDPERMANENTLY, cfg::getByte(hContact, "CList", "NotOnList", 0));
+ break;
+ }
+ case IDC_DSP_LOADDEFAULT:
+ {
+ int i = 0;
+
+ SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_SETCURSEL, 0, 0);
+ while(xImgCtrlIds[i] != 0)
+ SendDlgItemMessage(hWnd, xImgCtrlIds[i++], BM_SETCHECK, BST_INDETERMINATE, 0);
+
+ SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_INDETERMINATE, 0);
+ SendDlgItemMessage(hWnd, IDC_LOCALTIME, BM_SETCHECK, BST_INDETERMINATE, 0);
+ SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_INDETERMINATE, 0);
+ break;
+ }
+ case IDOK:
+ {
+ DWORD newMask = 0;
+ struct ClcContact *contact = NULL;
+
+ SendMessage(hWnd, WM_USER + 110, 0, (LPARAM)&newMask);
+ cfg::writeDword(hContact, "Ignore", "Mask1", newMask);
+ SendMessage(hWnd, WM_USER + 130, 0, 0);
+
+ if(cfg::clcdat) {
+ LRESULT iSel = SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_GETCURSEL, 0, 0);
+ DWORD dwFlags = cfg::getDword(hContact, "CList", "CLN_Flags", 0), dwXMask = 0;
+ LRESULT checked = 0;
+ int i = 0;
+
+ CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)hContact, &contact, NULL, NULL);
+ if(iSel != CB_ERR) {
+ dwFlags &= ~(ECF_FORCEAVATAR | ECF_HIDEAVATAR);
+
+ if(iSel == 1)
+ dwFlags |= ECF_FORCEAVATAR;
+ else if(iSel == 2)
+ dwFlags |= ECF_HIDEAVATAR;
+ if(contact)
+ LoadAvatarForContact(contact);
+ }
+
+ dwFlags &= ~(ECF_FORCEOVERLAY | ECF_HIDEOVERLAY | ECF_FORCELOCALTIME | ECF_HIDELOCALTIME |
+ ECF_FORCEVISIBILITY | ECF_HIDEVISIBILITY);
+
+ checked = SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_GETCHECK, 0, 0);
+ if(checked == BST_CHECKED)
+ dwFlags |= ECF_FORCEOVERLAY;
+ else if(checked == BST_UNCHECKED)
+ dwFlags |= ECF_HIDEOVERLAY;
+
+ checked = SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_GETCHECK, 0, 0);
+ if(checked == BST_CHECKED)
+ dwFlags |= ECF_FORCELOCALTIME;
+ else if(checked == BST_UNCHECKED)
+ dwFlags |= ECF_HIDELOCALTIME;
+
+ checked = SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_GETCHECK, 0, 0);
+ if(checked == BST_CHECKED)
+ dwFlags |= ECF_FORCEVISIBILITY;
+ else if(checked == BST_UNCHECKED)
+ dwFlags |= ECF_HIDEVISIBILITY;
+
+ cfg::writeDword(hContact, "CList", "CLN_Flags", dwFlags);
+
+ if((iSel = SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_GETCURSEL, 0, 0)) != CB_ERR) {
+ if(iSel == 0) {
+ db_unset(hContact, "CList", "CLN_2ndline");
+ if(contact)
+ contact->bSecondLineLocal = -1;
+ }
+ else {
+ cfg::writeByte(hContact, "CList", "CLN_2ndline", (BYTE)(iSel - 1));
+ if(contact)
+ contact->bSecondLineLocal = (BYTE)(iSel - 1);
+ }
+ }
+ while(xImgCtrlIds[i] != 0) {
+ checked = SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_GETCHECK, 0, 0);
+ if(checked == BST_CHECKED)
+ dwXMask |= (1 << (2 * xImgCtrlBits[i]));
+ else if(checked == BST_UNCHECKED)
+ dwXMask |= (1 << (2 * xImgCtrlBits[i] + 1));
+ i++;
+ }
+ cfg::writeDword(hContact, "CList", "CLN_xmask", dwXMask);
+ if(contact) {
+ if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry <= cfg::nextCacheEntry) {
+ contact->dwDFlags = dwFlags;
+ cfg::eCache[contact->extraCacheEntry].dwXMask = CalcXMask(hContact);
+ }
+ }
+ else {
+ int iIndex = cfg::getCache(hContact, NULL);
+ if(iIndex >= 0 && iIndex <= cfg::nextCacheEntry)
+ cfg::eCache[iIndex].dwXMask = CalcXMask(hContact);
+ }
+ cfg::writeByte(hContact, "CList", "Priority", (BYTE)(IsDlgButtonChecked(hWnd, IDC_IGN_PRIORITY) ? 1 : 0));
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ }
+ }
+ case IDCANCEL:
+ DestroyWindow(hWnd);
+ break;
+ }
+ break;
+ case WM_USER + 100: // fill dialog (wParam = hContact, lParam = mask)
+ {
+ CheckDlgButton(hWnd, IDC_IGN_MSGEVENTS, lParam & (1 << (IGNOREEVENT_MESSAGE - 1)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hWnd, IDC_IGN_FILEEVENTS, lParam & (1 << (IGNOREEVENT_FILE - 1)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hWnd, IDC_IGN_URLEVENTS, lParam & (1 << (IGNOREEVENT_URL - 1)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hWnd, IDC_IGN_AUTH, lParam & (1 << (IGNOREEVENT_AUTHORIZATION - 1)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hWnd, IDC_IGN_ADD, lParam & (1 << (IGNOREEVENT_YOUWEREADDED - 1)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hWnd, IDC_IGN_ONLINE, lParam & (1 << (IGNOREEVENT_USERONLINE - 1)) ? BST_CHECKED : BST_UNCHECKED);
+ return 0;
+ }
+ case WM_USER + 110: // retrieve value
+ {
+ DWORD *dwNewMask = (DWORD *)lParam, dwMask = 0;
+
+ dwMask = (IsDlgButtonChecked(hWnd, IDC_IGN_MSGEVENTS) ? (1 << (IGNOREEVENT_MESSAGE - 1)) : 0) |
+ (IsDlgButtonChecked(hWnd, IDC_IGN_FILEEVENTS) ? (1 << (IGNOREEVENT_FILE - 1)) : 0) |
+ (IsDlgButtonChecked(hWnd, IDC_IGN_URLEVENTS) ? (1 << (IGNOREEVENT_URL - 1)) : 0) |
+ (IsDlgButtonChecked(hWnd, IDC_IGN_AUTH) ? (1 << (IGNOREEVENT_AUTHORIZATION - 1)) : 0) |
+ (IsDlgButtonChecked(hWnd, IDC_IGN_ADD) ? (1 << (IGNOREEVENT_YOUWEREADDED - 1)) : 0) |
+ (IsDlgButtonChecked(hWnd, IDC_IGN_ONLINE) ? (1 << (IGNOREEVENT_USERONLINE - 1)) : 0);
+
+ if(dwNewMask)
+ *dwNewMask = dwMask;
+ return 0;
+ }
+ case WM_USER + 120: // set visibility status
+ {
+ struct ClcContact *contact = NULL;
+
+ if(CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)hContact, &contact, NULL, NULL)) {
+ if(contact) {
+ WORD wApparentMode = cfg::getWord(contact->hContact, contact->proto, "ApparentMode", 0);
+
+ CheckDlgButton(hWnd, IDC_IGN_ALWAYSOFFLINE, wApparentMode == ID_STATUS_OFFLINE ? TRUE : FALSE);
+ CheckDlgButton(hWnd, IDC_IGN_ALWAYSONLINE, wApparentMode == ID_STATUS_ONLINE ? TRUE : FALSE);
+ }
+ }
+ return 0;
+ }
+ case WM_USER + 130: // update apparent mode
+ {
+ struct ClcContact *contact = NULL;
+
+ if(CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)hContact, &contact, NULL, NULL)) {
+ if(contact) {
+ WORD wApparentMode = 0;
+
+ if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSONLINE))
+ wApparentMode = ID_STATUS_ONLINE;
+ else if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSOFFLINE))
+ wApparentMode = ID_STATUS_OFFLINE;
+
+ CallContactService(hContact, PSS_SETAPPARENTMODE, (WPARAM)wApparentMode, 0);
+ SendMessage(hWnd, WM_USER + 120, 0, 0);
+ }
+ }
+ return 0;
+ }
+ case WM_DESTROY:
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);
+ WindowList_Remove(hWindowListIGN, hWnd);
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ * service function: Open ignore settings dialog for the contact handle in wParam
+ * (clist_nicer+ specific service)
+ *
+ * Servicename = CList/SetContactIgnore
+ *
+ * ensure that dialog is only opened once (the dialog proc saves the window handle of an open dialog
+ * of this type to the contacts database record).
+ *
+ * if dialog is already open, focus it.
+*/
+
+static INT_PTR SetContactIgnore(WPARAM wParam, LPARAM)
+{
+ HWND hWnd = 0;
+
+ if (hWindowListIGN == 0)
+ hWindowListIGN = WindowList_Create();
+
+ hWnd = WindowList_Find(hWindowListIGN, wParam);
+ if (wParam) {
+ if (hWnd == 0)
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_QUICKIGNORE), 0, IgnoreDialogProc, (LPARAM)wParam);
+ else if (IsWindow(hWnd))
+ SetFocus(hWnd);
+ }
+ return 0;
+}
+
+/*
+ * service function: Set a contacts floating status.
+ * (clist_nicer+ specific service)
+ *
+ * Servicename = CList/SetContactFloating
+ *
+ * a floating contact appears as a small independent top level window anywhere on
+ * the desktop.
+*/
+
+static INT_PTR SetContactFloating(WPARAM wParam, LPARAM lParam)
+{
+ SendMessage(pcli->hwndContactTree, CLM_TOGGLEFLOATINGCONTACT, wParam, lParam);
+ return 0;
+}
+
+int InitCustomMenus(void)
+{
+ CreateServiceFunction("CloseAction", CloseAction);
+ CreateServiceFunction("CList/SetContactIgnore", SetContactIgnore);
+
+ CMenuItem mi;
+ mi.position = 200000;
+ mi.pszService = "CList/SetContactIgnore";
+ mi.hIcolibItem = iconItem[0].hIcolib;
+ mi.name.a = LPGEN("&Contact list settings...");
+ Menu_AddContactMenuItem(&mi);
+ return 0;
+}
+
+void UninitCustomMenus(void)
+{
+ WindowList_Destroy(hWindowListIGN);
+}
diff --git a/plugins/Clist_ng/SRC/clistmod.cpp b/plugins/Clist_ng/SRC/clistmod.cpp new file mode 100644 index 0000000000..a36eae8c00 --- /dev/null +++ b/plugins/Clist_ng/SRC/clistmod.cpp @@ -0,0 +1,225 @@ +/*
+ * 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-2015 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ */
+
+#include <commonheaders.h>
+
+void TrayIconUpdateBase(const char *szChangedProto);
+int EventsProcessContactDoubleClick(HANDLE hContact);
+
+extern HANDLE hSvc_GetContactStatusMsg;
+
+static INT_PTR GetContactStatusMessage(WPARAM wParam, LPARAM lParam)
+{
+ if (!cfg::shutDown)
+ return SendMessage(pcli->hwndContactTree, CLM_GETSTATUSMSG, wParam, lParam);
+ return 0;
+}
+
+static INT_PTR GetStatusMode(WPARAM wParam, LPARAM lParam)
+{
+ return(cfg::maxStatus == ID_STATUS_OFFLINE ? pcli->currentDesiredStatusMode : cfg::maxStatus);
+}
+
+int CLC::IconFromStatusMode(const char *szProto, int status, MCONTACT hContact, HICON *phIcon)
+{
+ char *szFinalProto;
+ int finalStatus;
+
+ if (szProto != NULL && !strcmp(szProto, cfg::dat.szMetaName) && cfg::dat.bMetaAvail && hContact != 0) {
+ MCONTACT hSubContact = db_mc_getMostOnline(hContact);
+ szFinalProto = GetContactProto(hSubContact);
+ finalStatus = (status == 0) ? (WORD) cfg::getWord(hSubContact, szFinalProto, "Status", ID_STATUS_OFFLINE) : status;
+ } else {
+ szFinalProto = (char*) szProto;
+ finalStatus = status;
+ }
+
+ if(status >= ID_STATUS_CONNECTING && status < ID_STATUS_OFFLINE && phIcon != NULL) {
+ if(szProto) {
+ char szBuf[128];
+ mir_snprintf(szBuf, 128, "%s_conn", szProto);
+ *phIcon = IcoLib_GetIcon(szBuf);
+ }
+ }
+ return coreCli.pfnIconFromStatusMode(szFinalProto, finalStatus, hContact);
+}
+
+static int MenuItem_LockAvatar(WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+static int ContactListShutdownProc(WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+int LoadContactListModule(void)
+{
+ HookEvent(ME_SYSTEM_SHUTDOWN, ContactListShutdownProc);
+ CreateServiceFunction(MS_CLIST_GETSTATUSMODE, GetStatusMode);
+
+ hSvc_GetContactStatusMsg = CreateServiceFunction("CList/GetContactStatusMsg", GetContactStatusMessage);
+ InitCustomMenus();
+ return 0;
+}
+
+#define GWVS_HIDDEN 1
+#define GWVS_VISIBLE 2
+#define GWVS_COVERED 3
+#define GWVS_PARTIALLY_COVERED 4
+
+int GetWindowVisibleState(HWND hWnd, int iStepX, int iStepY)
+{
+ RECT rc = { 0 };
+ POINT pt = {0};
+ register int i = 0, j = 0, width = 0, height = 0, iCountedDots = 0, iNotCoveredDots = 0;
+ BOOL bPartiallyCovered = FALSE;
+ HWND hAux = 0;
+
+ if (hWnd == NULL) {
+ SetLastError(0x00000006); //Wrong handle
+ return -1;
+ }
+ //Some defaults now. The routine is designed for thin and tall windows.
+
+ if (IsIconic(hWnd) || !IsWindowVisible(hWnd))
+ return GWVS_HIDDEN;
+ else {
+ HRGN rgn = 0;
+ POINT ptOrig;
+ RECT rcClient;
+
+ GetClientRect(hWnd, &rcClient);
+ ptOrig.x = ptOrig.y = 0;
+ ClientToScreen(hWnd, &ptOrig);
+ rc.left = ptOrig.x;
+ rc.top = ptOrig.y;
+ rc.right = rc.left + rcClient.right;
+ rc.bottom = rc.top + rcClient.bottom;
+
+ width = rc.right - rc.left;
+ height = rc.bottom - rc.top;
+
+ if (iStepX <= 0)
+ iStepX = 4;
+ if (iStepY <= 0)
+ iStepY = 16;
+
+ /*
+ * use a rounded clip region to determine which pixels are covered
+ * this will avoid problems with certain XP themes which are using transparency for rounded
+ * window frames (reluna being one popular example).
+
+ * the radius of 8 should be sufficient for most themes as they usually don't use bigger
+ * radii.
+ * also, clip at least 2 pixels from the border (same reason)
+ */
+
+ int clip = max(3, db_get_b(0, "CLUI", "ignoreframepixels", 2));
+ for (i = rc.top + clip; i < rc.bottom - clip; i += (height / iStepY)) {
+ pt.y = i;
+ for (j = rc.left + clip; j < rc.right - clip; j += (width / iStepX)) {
+ pt.x = j;
+ hAux = WindowFromPoint(pt);
+ while (GetParent(hAux) != NULL)
+ hAux = GetParent(hAux);
+ if (hAux != hWnd && hAux) //There's another window!
+ bPartiallyCovered = TRUE;
+ else
+ iNotCoveredDots++; //Let's count the not covered dots.
+ iCountedDots++; //Let's keep track of how many dots we checked.
+ }
+ }
+ if(rgn)
+ DeleteObject(rgn);
+
+ if (iNotCoveredDots == iCountedDots) //Every dot was not covered: the window is visible.
+ return GWVS_VISIBLE;
+ else if (iNotCoveredDots == 0) //They're all covered!
+ return GWVS_COVERED;
+ else //There are dots which are visible, but they are not as many as the ones we counted: it's partially covered.
+ return GWVS_PARTIALLY_COVERED;
+ }
+}
+
+int ShowHide(WPARAM wParam, LPARAM lParam)
+{
+ BOOL bShow = FALSE;
+
+ int iVisibleState = pcli->pfnGetWindowVisibleState(pcli->hwndContactList, 0, 0);
+
+ if(IsIconic(pcli->hwndContactList)) {
+ SendMessage(pcli->hwndContactList, WM_SYSCOMMAND, SC_RESTORE, 0);
+ bShow = TRUE;
+ }
+ else {
+ switch (iVisibleState) {
+ case GWVS_PARTIALLY_COVERED:
+ //If we don't want to bring it to top, we can use a simple break. This goes against readability ;-) but the comment explains it.
+ if (!cfg::getByte("CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT))
+ break;
+ case GWVS_COVERED: //Fall through (and we're already falling)
+ case GWVS_HIDDEN:
+ bShow = TRUE;
+ break;
+ case GWVS_VISIBLE: //This is not needed, but goes for readability.
+ bShow = FALSE;
+ break;
+ case -1: //We can't get here, both cli.hwndContactList and iStepX and iStepY are right.
+ return 0;
+ }
+ }
+
+ if (bShow == TRUE) {
+ RECT rcWindow;
+
+ SetWindowPos(pcli->hwndContactList, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOCOPYBITS);
+ if (!cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT))
+ SetWindowPos(pcli->hwndContactList, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOCOPYBITS);
+ SetForegroundWindow(pcli->hwndContactList);
+ ShowWindow(pcli->hwndContactList, SW_SHOW);
+ cfg::writeByte("CList", "State", SETTING_STATE_NORMAL);
+
+ GetWindowRect(pcli->hwndContactList, &rcWindow);
+ if (Utils_AssertInsideScreen(&rcWindow) == 1)
+ {
+ MoveWindow(pcli->hwndContactList, rcWindow.left, rcWindow.top,
+ rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
+ }
+ }
+ else { //It needs to be hidden
+ ShowWindow(pcli->hwndContactList, SW_HIDE);
+ cfg::writeByte("CList", "State", SETTING_STATE_HIDDEN);
+ if (cfg::getByte("CList", "DisableWorkingSet", 1))
+ SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);
+ }
+ return 0;
+}
diff --git a/plugins/Clist_ng/SRC/clistopts.cpp b/plugins/Clist_ng/SRC/clistopts.cpp new file mode 100644 index 0000000000..44b810d90c --- /dev/null +++ b/plugins/Clist_ng/SRC/clistopts.cpp @@ -0,0 +1,216 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+
+*/
+#include "commonheaders.h"
+
+void LoadContactTree(void);
+void SortContacts(void);
+
+static int opt_gen_opts_changed = 0;
+
+static void __setFlag(DWORD dwFlag, int iMode)
+{
+ cfg::dat.dwFlags = iMode ? cfg::dat.dwFlags | dwFlag : cfg::dat.dwFlags & ~dwFlag;
+}
+
+INT_PTR CALLBACK cfg::DlgProcGenOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_USER+1:
+ {
+ HANDLE hContact = (HANDLE) wParam;
+ DBCONTACTWRITESETTING *ws = (DBCONTACTWRITESETTING *) lParam;
+ if (hContact == NULL && ws != NULL && ws->szModule != NULL && ws->szSetting != NULL && lstrcmpiA(ws->szModule, "CList") == 0 && lstrcmpiA(ws->szSetting, "UseGroups") == 0 && IsWindowVisible(hwndDlg)) {
+ CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, ws->value.bVal == 0);
+ }
+ break;
+ }
+ case WM_DESTROY:
+ UnhookEvent((HANDLE) GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
+ break;
+
+ case WM_INITDIALOG:
+ opt_gen_opts_changed = 0;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED, hwndDlg, WM_USER + 1));
+ CheckDlgButton(hwndDlg, IDC_ONTOP, cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, cfg::getByte(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_HIDEEMPTYGROUPS, cfg::getByte("CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, cfg::getByte("CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) ? BST_UNCHECKED : BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_CONFIRMDELETE, cfg::getByte("CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ {
+ DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0);
+ if (!(caps & CLUIF_HIDEEMPTYGROUPS))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_HIDEEMPTYGROUPS), SW_HIDE);
+ if (!(caps & CLUIF_DISABLEGROUPS))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_DISABLEGROUPS), SW_HIDE);
+ if (caps & CLUIF_HASONTOPOPTION)
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ONTOP), SW_HIDE);
+ if (caps & CLUIF_HASAUTOHIDEOPTION) {
+ }
+ }
+
+ CheckDlgButton(hwndDlg, IDC_SHOWBOTTOMBUTTONS, cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS);
+ CheckDlgButton(hwndDlg, IDC_CLISTSUNKEN, cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN);
+ CheckDlgButton(hwndDlg, IDC_EVENTAREAAUTOHIDE, cfg::dat.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY);
+
+ CheckDlgButton(hwndDlg, IDC_ONECLK, cfg::getByte("CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ALWAYSSTATUS, cfg::getByte("CList", "AlwaysStatus", SETTING_ALWAYSSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ALWAYSMULTI, !cfg::getByte("CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DONTCYCLE, cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CYCLE, cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_CYCLE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_MULTITRAY, cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DISABLEBLINK, cfg::getByte("CList", "DisableTrayFlash", 0) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ICONBLINK, cfg::getByte("CList", "NoIconBlink", 0) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ if (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE)) {
+ Utils::enableDlgControl(hwndDlg, IDC_CYCLETIMESPIN, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_CYCLETIME, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_ALWAYSMULTI, FALSE);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_CYCLE)) {
+ Utils::enableDlgControl(hwndDlg, IDC_PRIMARYSTATUS, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_ALWAYSMULTI, FALSE);
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY)) {
+ Utils::enableDlgControl(hwndDlg, IDC_CYCLETIMESPIN, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_CYCLETIME, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_PRIMARYSTATUS, FALSE);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETRANGE, 0, MAKELONG(120, 1));
+ SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CList", "CycleTime", SETTING_CYCLETIME_DEFAULT), 0)); {
+ int i, count, item;
+ PROTOACCOUNT **accs;
+ DBVARIANT dbv = {
+ DBVT_DELETED
+ };
+ db_get(NULL, "CList", "PrimaryStatus", &dbv);
+ Proto_EnumAccounts( &count, &accs );
+ item = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) TranslateT("Global"));
+ SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM) 0);
+ for (i = 0; i < count; i++) {
+ if ( !Proto_IsAccountEnabled(accs[i]) || CallProtoService(accs[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) == 0)
+ continue;
+
+ item = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) accs[i]->tszAccountName);
+ SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM)accs[i] );
+ if (dbv.type == DBVT_ASCIIZ && !lstrcmpA(dbv.pszVal, accs[i]->szModuleName ))
+ SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, item, 0);
+ }
+ }
+ if (-1 == (int) SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0))
+ SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETBUDDY, (WPARAM) GetDlgItem(hwndDlg, IDC_BLINKTIME), 0); // set buddy
+ SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETRANGE, 0, MAKELONG(0x3FFF, 250));
+ SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CList", "IconFlashTime", 550), 0));
+ CheckDlgButton(hwndDlg, IDC_NOTRAYINFOTIPS, cfg::dat.bNoTrayTips ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_APPLYLASTVIEWMODE, cfg::getByte("CList", "AutoApplyLastViewMode", 0) ? 1 : 0);
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_DONTCYCLE || LOWORD(wParam) == IDC_CYCLE || LOWORD(wParam) == IDC_MULTITRAY) {
+ Utils::enableDlgControl(hwndDlg, IDC_PRIMARYSTATUS, IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE));
+ Utils::enableDlgControl(hwndDlg, IDC_CYCLETIME, IsDlgButtonChecked(hwndDlg, IDC_CYCLE));
+ Utils::enableDlgControl(hwndDlg, IDC_CYCLETIMESPIN, IsDlgButtonChecked(hwndDlg, IDC_CYCLE));
+ Utils::enableDlgControl(hwndDlg, IDC_ALWAYSMULTI, IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY));
+ }
+ if ((LOWORD(wParam) == IDC_CYCLETIME) && HIWORD(wParam) != EN_CHANGE)
+ break;
+ if (LOWORD(wParam) == IDC_PRIMARYSTATUS && HIWORD(wParam) != CBN_SELCHANGE)
+ break;
+ if ((LOWORD(wParam) == IDC_CYCLETIME) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()))
+ return 0;
+ if (LOWORD(wParam) == IDC_BLINKTIME && HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ opt_gen_opts_changed = TRUE;
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ if(!opt_gen_opts_changed)
+ return TRUE;
+
+ cfg::writeByte("CList", "HideOffline", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEOFFLINE));
+ {
+ DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0);
+ if (caps & CLUIF_HIDEEMPTYGROUPS)
+ cfg::writeByte("CList", "HideEmptyGroups", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEEMPTYGROUPS));
+ if (caps & CLUIF_DISABLEGROUPS)
+ cfg::writeByte("CList", "UseGroups", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_DISABLEGROUPS));
+ if (!(caps & CLUIF_HASONTOPOPTION)) {
+ cfg::writeByte("CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP));
+ SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ }
+ if (!(caps & CLUIF_HASAUTOHIDEOPTION)) {
+ }
+ }
+ cfg::writeByte("CList", "ConfirmDelete", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CONFIRMDELETE));
+ cfg::writeByte("CList", "Tray1Click", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONECLK));
+ cfg::writeByte("CList", "AlwaysStatus", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ALWAYSSTATUS));
+ cfg::writeByte("CList", "AlwaysMulti", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_ALWAYSMULTI));
+ cfg::writeByte("CList", "TrayIcon", (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE) ? SETTING_TRAYICON_SINGLE : (IsDlgButtonChecked(hwndDlg, IDC_CYCLE) ? SETTING_TRAYICON_CYCLE : SETTING_TRAYICON_MULTI)));
+ cfg::writeWord("CList", "CycleTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_GETPOS, 0, 0));
+ cfg::writeWord("CList", "IconFlashTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_GETPOS, 0, 0));
+ cfg::writeByte("CList", "DisableTrayFlash", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK));
+ cfg::writeByte("CList", "NoIconBlink", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ICONBLINK));
+ cfg::writeByte("CList", "AutoApplyLastViewMode", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_APPLYLASTVIEWMODE));
+
+ __setFlag(CLUI_FRAME_AUTOHIDENOTIFY, IsDlgButtonChecked(hwndDlg, IDC_EVENTAREAAUTOHIDE));
+
+ __setFlag(CLUI_FRAME_SHOWBOTTOMBUTTONS, IsDlgButtonChecked(hwndDlg, IDC_SHOWBOTTOMBUTTONS));
+ __setFlag(CLUI_FRAME_CLISTSUNKEN, IsDlgButtonChecked(hwndDlg, IDC_CLISTSUNKEN));
+
+ cfg::dat.bNoTrayTips = IsDlgButtonChecked(hwndDlg, IDC_NOTRAYINFOTIPS) ? 1 : 0;
+ cfg::writeByte("CList", "NoTrayTips", (BYTE)cfg::dat.bNoTrayTips);
+ {
+ int cursel = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0);
+ PROTOACCOUNT* pa = (PROTOACCOUNT*)SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETITEMDATA, cursel, 0);
+ if ( !pa )
+ db_unset(NULL, "CList", "PrimaryStatus");
+ else
+ cfg::writeString(NULL, "CList", "PrimaryStatus", pa->szModuleName );
+ }
+ pcli->pfnTrayIconIconsChanged();
+ cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags);
+ CLUI::configureWindowLayout();
+ CLUI::configureGeometry(1);
+ CLUI::configureEventArea(pcli->hwndContactList);
+ CLUI::hideShowNotifyFrame();
+ SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0);
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ CLC::LoadContactTree(); /* this won't do job properly since it only really works when changes happen */
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0);
+
+ opt_gen_opts_changed = 0;
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
diff --git a/plugins/Clist_ng/SRC/clisttray.cpp b/plugins/Clist_ng/SRC/clisttray.cpp new file mode 100644 index 0000000000..1eec622829 --- /dev/null +++ b/plugins/Clist_ng/SRC/clisttray.cpp @@ -0,0 +1,166 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+
+UNICODE done
+
+*/
+#include "commonheaders.h"
+
+#define TRAYICON_ID_BASE 100
+#define TIM_CALLBACK (WM_USER+1857)
+#define TIM_CREATE (WM_USER+1858)
+
+#define NIF_STATE 0x00000008
+#define NIF_INFO 0x00000010
+
+void TrayIconUpdateBase(const char *szChangedProto)
+{
+ int i,count,netProtoCount,changed = -1;
+ PROTOACCOUNT **accs;
+ int averageMode = 0;
+ HWND hwnd = pcli->hwndContactList;
+
+ if (pcli->cycleTimerId)
+ KillTimer(NULL, pcli->cycleTimerId); pcli->cycleTimerId = 0;
+
+ Proto_EnumAccounts( &count, &accs );
+ for (i = 0,netProtoCount = 0; i < count; i++) {
+ if ( !pcli->pfnGetProtocolVisibility( accs[i]->szModuleName ))
+ continue;
+ netProtoCount++;
+ if (!lstrcmpA(szChangedProto, accs[i]->szModuleName ))
+ pcli->cycleStep = i;
+ if (averageMode == 0)
+ averageMode = CallProtoService( accs[i]->szModuleName, PS_GETSTATUS, 0, 0);
+ else if (averageMode != CallProtoService( accs[i]->szModuleName, PS_GETSTATUS, 0, 0)) {
+ averageMode = -1; break;
+ }
+ }
+ if (netProtoCount > 1) {
+ if (averageMode > 0) {
+ if (cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI) {
+ if (cfg::getByte("CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT)) {
+ HICON hIcon = 0;
+ int iIcon = CLC::IconFromStatusMode(szChangedProto, averageMode, 0, &hIcon);
+ if(hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), szChangedProto);
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL), szChangedProto);
+ }
+ else if (pcli->trayIcon && pcli->trayIcon[0].szProto != NULL) {
+ pcli->pfnTrayIconDestroy(hwnd);
+ pcli->pfnTrayIconInit(hwnd);
+ }
+ else {
+ HICON hIcon = 0;
+ int iIcon = CLC::IconFromStatusMode(NULL, averageMode, 0, &hIcon);
+
+ if(hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL);
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL), NULL);
+ }
+ } else {
+ HICON hIcon = 0;
+ int iIcon = CLC::IconFromStatusMode(NULL, averageMode, 0, &hIcon);
+
+ if(hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL);
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL), NULL);
+ }
+ } else {
+ switch (cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT)) {
+ case SETTING_TRAYICON_SINGLE:
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+ int iIcon = 0;
+ HICON hIcon = 0;
+ char *szProto;
+ if (cfg::getString(NULL, "CList", "PrimaryStatus", &dbv))
+ szProto = NULL;
+ else
+ szProto = dbv.pszVal;
+ iIcon = CLC::IconFromStatusMode(szProto, szProto ? CallProtoService(szProto, PS_GETSTATUS, 0, 0) : CallService(MS_CLIST_GETSTATUSMODE, 0, 0), 0, &hIcon);
+ if(hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL);
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL), NULL);
+ db_free(&dbv);
+ break;
+ }
+ case SETTING_TRAYICON_CYCLE:
+ {
+ HICON hIcon = 0;
+ int iIcon = CLC::IconFromStatusMode(szChangedProto, CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0), 0, &hIcon);
+
+ pcli->cycleTimerId = SetTimer(NULL, 0, cfg::getWord("CList", "CycleTime", SETTING_CYCLETIME_DEFAULT) * 1000, pcli->pfnTrayCycleTimerProc);
+ if(hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL);
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL), NULL);
+ break;
+ }
+ case SETTING_TRAYICON_MULTI:
+ if ( !pcli->trayIcon )
+ pcli->pfnTrayIconRemove(NULL, NULL);
+ else if (cfg::getByte("CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT)) {
+ HICON hIcon = 0;
+ int iIcon = CLC::IconFromStatusMode(szChangedProto, CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0), 0, &hIcon);
+
+ if(hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), szChangedProto);
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL), szChangedProto);
+ }
+ else {
+ pcli->pfnTrayIconDestroy(hwnd);
+ pcli->pfnTrayIconInit(hwnd);
+ }
+ break;
+ }
+ }
+ } else {
+ HICON hIcon = 0;
+ int iIcon = CLC::IconFromStatusMode(NULL, averageMode, 0, &hIcon);
+ if ( hIcon )
+ changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL);
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(CLC::hClistImages, iIcon, ILD_NORMAL), NULL);
+ }
+ if (changed != -1 && pcli->trayIcon[changed].isBase)
+ pcli->pfnTrayIconUpdate( pcli->trayIcon[changed].hBaseIcon, NULL, pcli->trayIcon[changed].szProto, 1);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+INT_PTR CLC::TrayIconProcessMessage(WPARAM wParam, LPARAM lParam)
+{
+ MSG* msg = ( MSG* )wParam;
+ if ( msg->message == TIM_CALLBACK && msg->lParam == WM_MOUSEMOVE ) {
+ if ( cfg::dat.bNoTrayTips ) {
+ *((LRESULT *) lParam) = 0;
+ return TRUE;
+ } }
+
+ return coreCli.pfnTrayIconProcessMessage(wParam, lParam);
+}
diff --git a/plugins/Clist_ng/SRC/clui.cpp b/plugins/Clist_ng/SRC/clui.cpp new file mode 100644 index 0000000000..81545a7894 --- /dev/null +++ b/plugins/Clist_ng/SRC/clui.cpp @@ -0,0 +1,2062 @@ +/*
+ * 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: clui.cpp 138 2010-11-01 10:51:15Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include <shobjidl.h>
+#include <m_findadd.h>
+#include <m_icq.h>
+#include "../coolsb/coolscroll.h"
+
+LRESULT (CALLBACK* CLUI::saveContactListWndProc )(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) = 0;
+
+int CLUI::fading_active = 0;
+HPEN CLUI::hPenFrames = 0;
+WNDPROC CLUI::OldStatusBarProc = 0;
+bool CLUI::fInSizing = false;
+RECT CLUI::newRect = {0};
+RECT CLUI::rcWPC = {0};
+RECT CLUI::cluiPos = {0};
+HIMAGELIST CLUI::hExtraImages = 0;
+TImageItem* CLUI::bgImageItem = 0, *CLUI::bgImageItem_nonAero = 0, *CLUI::bgClientItem = 0;
+TButtonItem* CLUI::buttonItems = 0;
+
+#ifdef _USE_D2D
+ ID2D1HwndRenderTarget* CLUI::renderTarget = 0;
+#endif
+UPDATELAYEREDWINDOWINFO CLUI::ulwInfo = {0};
+BLENDFUNCTION CLUI::bf = {0};
+
+static RECT g_PreSizeRect;
+static LONG g_CLUI_x_off, g_CLUI_y_off, g_CLUI_y1_off, g_CLUI_x1_off;
+
+static int transparentFocus = 1;
+static byte oldhideoffline;
+static int disableautoupd = 1;
+HANDLE hFrameContactTree;
+extern PLUGININFOEX pluginInfo;
+
+extern BOOL g_trayTooltipActive;
+extern POINT tray_hover_pos;
+extern HWND g_hwndViewModeFrame, g_hwndEventArea;
+
+extern HBRUSH g_CLUISkinnedBkColor;
+extern HWND g_hwndSFL;
+extern COLORREF g_CLUISkinnedBkColorRGB;
+extern FRAMEWND *wndFrameCLC;
+
+static BYTE old_cliststate;
+
+wchar_t *statusNames[12];
+
+extern HANDLE hNotifyFrame;
+
+void FLT_ShowHideAll(int showCmd);
+void FLT_SnapToEdges(HWND hwnd);
+void DestroyTrayMenu(HMENU hMenu);
+
+extern HANDLE hSoundHook;
+extern HANDLE hIcoLibChanged;
+extern HANDLE hExtraImageListRebuilding, hExtraImageApplying;
+
+SIZE g_oldSize = {0};
+POINT g_oldPos = {0};
+extern int dock_prevent_moving;
+
+static HDC hdcLockedPoint = 0;
+static HBITMAP hbmLockedPoint = 0, hbmOldLockedPoint = 0;
+
+HICON overlayicons[10];
+
+struct CluiTopButton top_buttons[] = {
+ 0, 0, 0, IDC_TBTOPMENU, IDI_TBTOPMENU, 0, "CLN_topmenu", NULL, TOPBUTTON_PUSH | TOPBUTTON_SENDONDOWN, 1, LPGENT("Show menu"),
+ 0, 0, 0, IDC_TBHIDEOFFLINE, IDI_HIDEOFFLINE, 0, "CLN_online", NULL, 0, 2, LPGENT("Show / hide offline contacts"),
+ 0, 0, 0, IDC_TBHIDEGROUPS, IDI_HIDEGROUPS, 0, "CLN_groups", NULL, 0, 4, LPGENT("Toggle group mode"),
+ 0, 0, 0, IDC_TBFINDANDADD, IDI_FINDANDADD, 0, "CLN_findadd", NULL, TOPBUTTON_PUSH, 8, LPGENT("Find and add contacts"),
+ 0, 0, 0, IDC_TBACCOUNTS, IDI_TBACCOUNTS, 0, "CLN_accounts", NULL, TOPBUTTON_PUSH, 8192, LPGENT("Accounts"),
+ 0, 0, 0, IDC_TBOPTIONS, IDI_TBOPTIONS, 0, "CLN_options", NULL, TOPBUTTON_PUSH, 16, LPGENT("Open preferences"),
+ 0, 0, 0, IDC_TBSOUND, IDI_SOUNDSON, IDI_SOUNDSOFF, "CLN_sound", "CLN_soundsoff", 0, 32, LPGENT("Toggle sounds"),
+ 0, 0, 0, IDC_TBMINIMIZE, IDI_MINIMIZE, 0, "CLN_minimize", NULL, TOPBUTTON_PUSH, 64, LPGENT("Minimize contact list"),
+ 0, 0, 0, IDC_TBTOPSTATUS, 0, 0, "CLN_topstatus", NULL, TOPBUTTON_PUSH | TOPBUTTON_SENDONDOWN, 128, LPGENT("Status menu"),
+ 0, 0, 0, IDC_TABSRMMSLIST, IDI_TABSRMMSESSIONLIST, 0, "CLN_slist", NULL, TOPBUTTON_PUSH | TOPBUTTON_SENDONDOWN, 256, LPGENT("tabSRMM session list"),
+ 0, 0, 0, IDC_TABSRMMMENU, IDI_TABSRMMMENU, 0, "CLN_menu", NULL, TOPBUTTON_PUSH | TOPBUTTON_SENDONDOWN, 512, LPGENT("tabSRMM Menu"),
+
+ 0, 0, 0, IDC_TBSELECTVIEWMODE, 0, 0, "CLN_CLVM_select", NULL, TOPBUTTON_PUSH | TOPBUTTON_SENDONDOWN, 1024, LPGENT("Select view mode"),
+ 0, 0, 0, IDC_TBCONFIGUREVIEWMODE, 0, 0, "CLN_CLVM_options", NULL, TOPBUTTON_PUSH, 2048, LPGENT("Setup view modes"),
+ 0, 0, 0, IDC_TBCLEARVIEWMODE, 0, 0, "CLN_CLVM_reset", NULL, TOPBUTTON_PUSH, 4096, LPGENT("Clear view mode"),
+
+ 0, 0, 0, IDC_TBGLOBALSTATUS, 0, 0, "", NULL, TOPBUTTON_PUSH | TOPBUTTON_SENDONDOWN, 0, LPGENT("Set status modes"),
+ 0, 0, 0, IDC_TBMENU, IDI_MINIMIZE, 0, "", NULL, TOPBUTTON_PUSH | TOPBUTTON_SENDONDOWN, 0, LPGENT("Open main menu"),
+ (HWND) - 1, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+IconItemT iconItem[] = {
+ { LPGENT("Toggle show online/offline"), "CLN_online", IDI_HIDEOFFLINE },
+ { LPGENT("Toggle groups"), "CLN_groups", IDI_HIDEGROUPS },
+ { LPGENT("Find contacts"), "CLN_findadd", IDI_FINDANDADD },
+ { LPGENT("Open preferences"), "CLN_options", IDI_TBOPTIONS },
+ { LPGENT("Toggle sounds"), "CLN_sound", IDI_SOUNDSON },
+ { LPGENT("Minimize contact list"), "CLN_minimize", IDI_MINIMIZE },
+ { LPGENT("Show TabSRMM session list"), "CLN_slist", IDI_TABSRMMSESSIONLIST },
+ { LPGENT("Show TabSRMM menu"), "CLN_menu", IDI_TABSRMMMENU },
+ { LPGENT("Sounds are off"), "CLN_soundsoff", IDI_SOUNDSOFF },
+ { LPGENT("Select view mode"), "CLN_CLVM_select", IDI_CLVM_SELECT },
+ { LPGENT("Reset view mode"), "CLN_CLVM_reset", IDI_DELETE },
+ { LPGENT("Configure view modes"), "CLN_CLVM_options", IDI_CLVM_OPTIONS },
+ { LPGENT("Show menu"), "CLN_topmenu", IDI_TBTOPMENU },
+ { LPGENT("Setup accounts"), "CLN_accounts", IDI_TBACCOUNTS }
+};
+
+void CLUI::Tweak_It(const COLORREF clr)
+{
+#ifndef _USE_D2D
+ if(!cfg::isAero)
+ SetLayeredWindowAttributes(pcli->hwndContactList, clr, 0, LWA_COLORKEY);
+#endif
+ cfg::dat.colorkey = clr;
+}
+
+void CLUI::layoutButtons(HWND hwnd, RECT *rc)
+{
+ RECT rect;
+ BYTE left_offset = Skin::metrics.cLeft - (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? 3 : 0);
+ BYTE right_offset = Skin::metrics.cRight - (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? 3 : 0);
+ BYTE delta = left_offset + right_offset;
+ TButtonItem *btnItems = buttonItems;
+ HDWP dwp = 0;
+ bool fFrame = Skin::metrics.fHaveFrame;
+
+ if (rc == NULL)
+ GetClientRect(hwnd, &rect);
+ else
+ rect = *rc;
+
+ rect.bottom -= Skin::metrics.cBottom;
+
+ if (buttonItems || cfg::dat.dwFlags && CLUI_FRAME_SHOWBOTTOMBUTTONS) {
+ LONG x, y;
+ dwp = BeginDeferWindowPos(10);
+
+ while (btnItems) {
+ if(btnItems->dwFlags & BUTTON_FRAMELESS_ONLY) {
+ if(Skin::metrics.fHaveFrame && IsWindowVisible(btnItems->hWnd))
+ ShowWindow(btnItems->hWnd, SW_HIDE);
+ else if(!Skin::metrics.fHaveFrame && !IsWindowVisible(btnItems->hWnd))
+ ShowWindow(btnItems->hWnd, SW_SHOW);
+ }
+ fFrame = Skin::metrics.fHaveFrame || btnItems->dwFlags & BUTTON_FRAMELESS_ONLY;
+
+ x = (btnItems->xOff >= 0) ? rect.left + btnItems->xOff + (!fFrame ? Skin::metrics.cFakeLeftBorder : 0) :
+ rect.right - abs(btnItems->xOff) - (!fFrame ? Skin::metrics.cFakeRightBorder : 0);
+ if(btnItems->dwFlags & BUTTON_VALIGN_B)
+ y = rect.bottom - Skin::metrics.bSBarHeight - abs(btnItems->yOff) - (!fFrame ? Skin::metrics.cFakeBtmBorder : 0);
+ else
+ y = rect.top + btnItems->yOff + (!fFrame ? Skin::metrics.cFakeCaption : 0);
+
+ DeferWindowPos(dwp, btnItems->hWnd, 0, x, y, btnItems->width, btnItems->height,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOREDRAW);
+ btnItems = btnItems->nextItem;
+ }
+ DeferWindowPos(dwp, top_buttons[15].hwnd, 0, 2 + left_offset, rect.bottom - Skin::metrics.bSBarHeight - Skin::metrics.cButtonHeight - 1,
+ BUTTON_WIDTH_D * 3, Skin::metrics.cButtonHeight + 1, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOREDRAW);
+ DeferWindowPos(dwp, top_buttons[14].hwnd, 0, left_offset + (3 * BUTTON_WIDTH_D) + 3, rect.bottom - Skin::metrics.bSBarHeight - Skin::metrics.cButtonHeight - 1,
+ rect.right - delta - (3 * BUTTON_WIDTH_D + 5), Skin::metrics.cButtonHeight + 1, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOREDRAW);
+
+ EndDeferWindowPos(dwp);
+ return;
+ }
+}
+
+static int FS_FontsChanged(WPARAM wParam, LPARAM lParam)
+{
+ pcli->pfnClcOptionsChanged();
+ CLUI::Redraw();
+ return 0;
+}
+
+/*
+* create the CLC control, but not yet the frame. The frame containing the CLC should be created as the
+* last frame of all.
+*/
+
+HWND CLUI::preCreateCLC(HWND parent)
+{
+ pcli->hwndContactTree = CreateWindow(_T(CLISTCONTROL_CLASS), L"",
+ WS_CHILD | CLS_CONTACTLIST
+ | (cfg::getByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) ? CLS_USEGROUPS : 0)
+ | CLS_HIDEOFFLINE
+ //|(DBGetContactSettingByte(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)?CLS_HIDEOFFLINE:0)
+ | (cfg::getByte(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) ? CLS_HIDEEMPTYGROUPS : 0)
+ | CLS_MULTICOLUMN
+ , 0, 0, 0, 0, parent, NULL, g_hInst, (LPVOID)0xff00ff00);
+
+ cfg::clcdat = (struct ClcData *)GetWindowLongPtr(pcli->hwndContactTree, 0);
+
+ return pcli->hwndContactTree;
+}
+
+/*
+* create internal frames, including the last frame (actual CLC control)
+*/
+
+int CLUI::createCLC(HWND parent)
+{
+ reloadExtraIcons();
+ CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)oldhideoffline, 0);
+ disableautoupd = 0;
+ {
+ CLISTFrame frame = {0};
+ frame.cbSize = sizeof(frame);
+ frame.tname = _T("EventArea");
+ frame.TBtname = TranslateT("Event Area");
+ frame.hIcon = 0;
+ frame.height = 20;
+ frame.Flags = F_VISIBLE | F_SHOWTBTIP | F_NOBORDER | F_TCHAR;
+ frame.align = alBottom;
+ frame.hWnd = CreateWindowExW(0, L"EventAreaClass", L"evt", WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, pcli->hwndContactList, (HMENU) 0, g_hInst, NULL);
+ g_hwndEventArea = frame.hWnd;
+ hNotifyFrame = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM) & frame, (LPARAM)0);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)hNotifyFrame, FU_FMPOS);
+ hideShowNotifyFrame();
+ CreateViewModeFrame();
+ }
+
+ SetButtonToSkinned();
+
+ {
+ DWORD flags;
+ CLISTFrame Frame;
+ memset(&Frame, 0, sizeof(Frame));
+ Frame.cbSize = sizeof(CLISTFrame);
+ Frame.hWnd = pcli->hwndContactTree;
+ Frame.align = alClient;
+ Frame.hIcon = Skin_LoadIcon(SKINICON_OTHER_MIRANDA);
+ Frame.Flags = F_VISIBLE | F_SHOWTB | F_SHOWTBTIP | F_NOBORDER | F_TCHAR;
+ Frame.tname = _T("My Contacts");
+ Frame.TBtname = TranslateT("My Contacts");
+ Frame.height = 200;
+ hFrameContactTree = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM) & Frame, (LPARAM)0);
+ //free(Frame.name);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_TBTIPNAME, hFrameContactTree), (LPARAM)Translate("My Contacts"));
+
+ /*
+ * ugly, but working hack. Prevent that annoying little scroll bar from appearing in the "My Contacts" title bar
+ */
+
+ flags = (DWORD)CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hFrameContactTree), 0);
+ flags |= F_VISIBLE;
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hFrameContactTree), flags);
+ }
+ return(0);
+}
+
+int CLUI::modulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ MTG_OnmodulesLoad(wParam, lParam);
+ HookEvent(ME_FONT_RELOAD, FS_FontsChanged);
+ return 0;
+}
+
+static HICON hIconSaved = 0;
+
+void ClearIcons(int mode)
+{
+ int i;
+
+ for (i = IDI_OVL_OFFLINE; i <= IDI_OVL_OUTTOLUNCH; i++) {
+ if (overlayicons[i - IDI_OVL_OFFLINE] != 0) {
+ if (mode)
+ DestroyIcon(overlayicons[i - IDI_OVL_OFFLINE]);
+ overlayicons[i - IDI_OVL_OFFLINE] = 0;
+ }
+ }
+ hIconSaved = ImageList_GetIcon(CLUI::hExtraImages, 3, ILD_NORMAL);
+ ImageList_RemoveAll(CLUI::hExtraImages);
+}
+
+static void CacheClientIcons()
+{
+ int i = 0;
+ char szBuffer[128];
+
+ ClearIcons(0);
+
+ for (i = IDI_OVL_OFFLINE; i <= IDI_OVL_OUTTOLUNCH; i++) {
+ mir_snprintf(szBuffer, sizeof(szBuffer), "cln_ovl_%d", ID_STATUS_OFFLINE + (i - IDI_OVL_OFFLINE));
+ overlayicons[i - IDI_OVL_OFFLINE] = IcoLib_GetIcon(szBuffer);
+ }
+ ImageList_AddIcon(CLUI::hExtraImages, IcoLib_GetIcon("core_main_14"));
+ ImageList_AddIcon(CLUI::hExtraImages, Skin_LoadIcon(SKINICON_EVENT_URL));
+ ImageList_AddIcon(CLUI::hExtraImages, IcoLib_GetIcon("core_main_17"));
+ if (hIconSaved != 0) {
+ ImageList_AddIcon(CLUI::hExtraImages, hIconSaved);
+ DestroyIcon(hIconSaved);
+ hIconSaved = 0;
+ } else
+ ImageList_AddIcon(CLUI::hExtraImages, IcoLib_GetIcon("core_main_17"));
+}
+
+static void InitIcoLib()
+{
+ Icon_RegisterT(g_hInst, LPGENT("Contact list")_T("/")LPGENT("Default"),iconItem, _countof(iconItem));
+
+ for (int i = IDI_OVL_OFFLINE; i <= IDI_OVL_OUTTOLUNCH; i++) {
+ char szBuffer[128];
+ mir_snprintf(szBuffer, _countof(szBuffer), "cln_ovl_%d", ID_STATUS_OFFLINE + (i - IDI_OVL_OFFLINE));
+ IconItemT icon = { pcli->pfnGetStatusModeDescription(ID_STATUS_OFFLINE + (i - IDI_OVL_OFFLINE), 0), szBuffer, i };
+ Icon_RegisterT(g_hInst, LPGENT("Contact list")_T("/")LPGENT("Overlay icons"), &icon, 1);
+ }
+
+ PROTOACCOUNT **accs = NULL;
+ int p_count = 0;
+ Proto_EnumAccounts(&p_count, &accs);
+ for (int k = 0; k < p_count; k++) {
+ if (!Proto_IsAccountEnabled(accs[k]) || CallProtoService(accs[k]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) == 0)
+ continue;
+
+ TCHAR szDescr[128];
+ mir_sntprintf(szDescr, _countof(szDescr), TranslateT("%s connecting"), accs[k]->tszAccountName);
+ IconItemT icon = { szDescr, "conn", IDI_PROTOCONNECTING };
+ Icon_RegisterT(g_hInst, LPGENT("Contact list")_T("/")LPGENT("Connecting icons"), &icon, 1, accs[k]->szModuleName);
+ }
+}
+
+static int IcoLibChanged(WPARAM wParam, LPARAM lParam)
+{
+ IcoLibReloadIcons();
+ return 0;
+}
+
+/*
+* if mode != 0 we do first time init, otherwise only reload the extra icon stuff
+*/
+
+void CLN_LoadAllIcons(BOOL mode)
+{
+ if (mode) {
+ InitIcoLib();
+ HookEvent(ME_SKIN2_ICONSCHANGED, IcoLibChanged);
+ }
+ CacheClientIcons();
+ /*
+ if (mode) {
+ InitIcoLib();
+ hIcoLibChanged = HookEvent(ME_SKIN2_ICONSCHANGED, IcoLibChanged);
+ cfg::dat.hIconVisible = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_visible");
+ cfg::dat.hIconInvisible = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_invisible");
+ cfg::dat.hIconChatactive = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_chatactive");
+ }
+ CacheClientIcons();
+ */
+}
+
+void CLUI::configureEventArea(HWND hwnd)
+{
+ int iCount = GetMenuItemCount(cfg::dat.hMenuNotify);
+ DWORD dwFlags = cfg::dat.dwFlags;
+ int oldstate = cfg::dat.notifyActive;
+ int dwVisible = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hNotifyFrame), 0) & F_VISIBLE;
+
+ if (dwVisible) {
+ if (dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
+ cfg::dat.notifyActive = iCount > 0 ? 1 : 0;
+ else
+ cfg::dat.notifyActive = 1;
+ } else
+ cfg::dat.notifyActive = 0;
+
+ if (oldstate != cfg::dat.notifyActive)
+ hideShowNotifyFrame();
+}
+
+void CLUI::configureWindowLayout()
+{
+ int i;
+
+ for (i = 0; ; i++) {
+ if (top_buttons[i].szTooltip == NULL)
+ break;
+ if (top_buttons[i].hwnd == 0)
+ continue;
+ switch (top_buttons[i].id) {
+ case IDC_TBMENU:
+ case IDC_TBGLOBALSTATUS:
+ ShowWindow(top_buttons[i].hwnd, cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS ? SW_SHOW : SW_HIDE);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void IcoLibReloadIcons()
+{
+ int i;
+ HICON hIcon;
+
+ for (i = 0; ; i++) {
+ if (top_buttons[i].szTooltip == NULL)
+ break;
+
+ if (top_buttons[i].id == IDC_TBMENU || top_buttons[i].id == IDC_TBGLOBALSTATUS || top_buttons[i].id == IDC_TBTOPSTATUS)
+ continue;
+
+ hIcon = IcoLib_GetIcon(top_buttons[i].szIcoLibIcon);
+ if (top_buttons[i].hwnd && IsWindow(top_buttons[i].hwnd)) {
+ SendMessage(top_buttons[i].hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
+ InvalidateRect(top_buttons[i].hwnd, NULL, TRUE);
+ }
+ }
+ cfg::dat.hIconVisible = IcoLib_GetIcon("CLN_visible");
+ cfg::dat.hIconInvisible = IcoLib_GetIcon("CLN_invisible");
+ cfg::dat.hIconChatactive = IcoLib_GetIcon("CLN_chatactive");
+ CacheClientIcons();
+ CLUI::reloadExtraIcons();
+
+ // force client icons reload
+ {
+ int i;
+
+ for (i = 0; i < cfg::nextCacheEntry; i++) {
+ if (cfg::eCache[i].hContact)
+ NotifyEventHooks(hExtraImageApplying, (WPARAM)cfg::eCache[i].hContact, 0);
+ }
+ }
+ //
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ SendMessage(g_hwndViewModeFrame, WM_USER + 100, 0, 0);
+}
+
+void CreateButtonBar(HWND hWnd)
+{
+ int i;
+ HICON hIcon;
+
+ for (i = 0; ; i++) {
+ if (top_buttons[i].szTooltip == NULL)
+ break;
+ if (top_buttons[i].hwnd)
+ continue;
+
+ if (top_buttons[i].id != IDC_TBGLOBALSTATUS && top_buttons[i].id != IDC_TBMENU)
+ continue;
+
+ top_buttons[i].hwnd = CreateWindowEx(0, _T("CLCButtonClass"), _T(""), BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, hWnd, (HMENU) top_buttons[i].id, g_hInst, NULL);
+
+ hIcon = top_buttons[i].hIcon = IcoLib_GetIcon(top_buttons[i].szIcoLibIcon);
+ if (top_buttons[i].szIcoLibAltIcon)
+ top_buttons[i].hAltIcon = IcoLib_GetIcon(top_buttons[i].szIcoLibAltIcon);
+
+ if (top_buttons[i].id == IDC_TBMENU) {
+ SetWindowText(top_buttons[i].hwnd, TranslateT("Menu"));
+ SendMessage(top_buttons[i].hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM) Skin_LoadIcon(SKINICON_OTHER_MIRANDA));
+ }
+ if (top_buttons[i].id == IDC_TBGLOBALSTATUS) {
+ SetWindowText(top_buttons[i].hwnd, TranslateT("Offline"));
+ SendMessage(top_buttons[i].hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM) Skin_LoadIcon(SKINICON_STATUS_OFFLINE));
+ }
+ SendMessage(top_buttons[i].hwnd, BUTTONADDTOOLTIP, (WPARAM) TranslateTS(top_buttons[i].szTooltip), 0);
+ }
+}
+
+/*
+ * to properly configure the CLUI window
+ *
+ * 1) applyBorderStyle()
+ * 2) configureGeometry()
+ */
+void CLUI::configureGeometry(int mode)
+{
+ RECT rcStatus;
+
+ Skin::metrics.cLeft = Skin::metrics.fHaveFrame ? (Skin::metrics.cLeftFramed + Skin::metrics.cLeftButtonset) :
+ (Skin::metrics.cLeftSkinned + Skin::metrics.cFakeLeftBorder + Skin::metrics.cLeftButtonset);
+
+ Skin::metrics.cRight = Skin::metrics.fHaveFrame ? (Skin::metrics.cRightFramed + Skin::metrics.cRightButtonset) :
+ (Skin::metrics.cRightSkinned + Skin::metrics.cFakeRightBorder + Skin::metrics.cRightButtonset);
+
+ Skin::metrics.cTop = Skin::metrics.fHaveFrame ? (Skin::metrics.cTopFramed + Skin::metrics.cTopButtonset) :
+ (Skin::metrics.cTopSkinned + Skin::metrics.cFakeCaption + Skin::metrics.cTopButtonset);
+
+ Skin::metrics.cBottom = Skin::metrics.fHaveFrame ? (Skin::metrics.cBottomFramed + Skin::metrics.cBottomButtonset) :
+ (Skin::metrics.cBottomSkinned + Skin::metrics.cFakeBtmBorder + Skin::metrics.cBottomButtonset);
+
+ if (mode) {
+ if (cfg::dat.dwFlags & CLUI_FRAME_SBARSHOW) {
+ SendMessage(pcli->hwndStatus, WM_SIZE, 0, 0);
+ GetWindowRect(pcli->hwndStatus, &rcStatus);
+ Skin::metrics.bSBarHeight = (rcStatus.bottom - rcStatus.top);
+ } else
+ Skin::metrics.bSBarHeight = 0;
+ }
+
+ Skin::metrics.dwTopOffset = Skin::metrics.cTop;
+ Skin::metrics.dwBottomOffset = (cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS ? 2 + Skin::metrics.cButtonHeight : 0) + Skin::metrics.cBottom;
+
+ if (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN) {
+ Skin::metrics.dwTopOffset += 2;
+ Skin::metrics.dwBottomOffset += 2;
+ Skin::metrics.cLeft += 3;
+ Skin::metrics.cRight += 3;
+ }
+}
+
+/*
+ * set the states of defined database action buttons (only if button is a toggle)
+*/
+
+void CLUI::setFrameButtonStates(MCONTACT hPassedContact)
+{
+ TButtonItem *buttonItem = buttonItems;
+ MCONTACT hContact = 0, hFinalContact = 0;
+ char *szModule, *szSetting;
+ int sel = cfg::clcdat ? cfg::clcdat->selection : -1;
+ struct ClcContact *contact = 0;
+
+ if (sel != -1 && hPassedContact == 0) {
+ sel = pcli->pfnGetRowByIndex(cfg::clcdat, cfg::clcdat->selection, &contact, NULL);
+ if (contact && contact->type == CLCIT_CONTACT) {
+ hContact = contact->hContact;
+ }
+ }
+
+ while (buttonItem) {
+ BOOL result = FALSE;
+
+ if (!(buttonItem->dwFlags & BUTTON_ISTOGGLE && buttonItem->dwFlags & BUTTON_ISDBACTION)) {
+ buttonItem = buttonItem->nextItem;
+ continue;
+ }
+ szModule = buttonItem->szModule;
+ szSetting = buttonItem->szSetting;
+ if (buttonItem->dwFlags & BUTTON_DBACTIONONCONTACT || buttonItem->dwFlags & BUTTON_ISCONTACTDBACTION) {
+ if (hContact == 0) {
+ SendMessage(buttonItem->hWnd, BM_SETCHECK, BST_UNCHECKED, 0);
+ buttonItem = buttonItem->nextItem;
+ continue;
+ }
+ if (buttonItem->dwFlags & BUTTON_ISCONTACTDBACTION)
+ szModule = GetContactProto(hContact);
+ hFinalContact = hContact;
+ } else
+ hFinalContact = 0;
+
+ if (buttonItem->type == DBVT_ASCIIZ) {
+ DBVARIANT dbv = {0};
+
+ if (!cfg::getString(hFinalContact, szModule, szSetting, &dbv)) {
+ result = !strcmp((char *)buttonItem->bValuePush, dbv.pszVal);
+ db_free(&dbv);
+ }
+ } else {
+ switch (buttonItem->type) {
+ case DBVT_BYTE: {
+ BYTE val = cfg::getByte(hFinalContact, szModule, szSetting, 0);
+ result = (val == buttonItem->bValuePush[0]);
+ break;
+ }
+ case DBVT_WORD: {
+ WORD val = cfg::getWord(hFinalContact, szModule, szSetting, 0);
+ result = (val == *((WORD *) & buttonItem->bValuePush));
+ break;
+ }
+ case DBVT_DWORD: {
+ DWORD val = cfg::getDword(hFinalContact, szModule, szSetting, 0);
+ result = (val == *((DWORD *) & buttonItem->bValuePush));
+ break;
+ }
+ }
+ }
+ SendMessage(buttonItem->hWnd, BM_SETCHECK, (WPARAM)result, 0);
+ buttonItem = buttonItem->nextItem;
+ }
+}
+
+/*
+ * set states of standard buttons (pressed/unpressed
+ */
+void CLUI::setButtonStates(HWND hwnd)
+{
+ BYTE iMode;
+ TButtonItem *buttonItem = buttonItems;
+
+ iMode = cfg::getByte("CList", "HideOffline", 0);
+ while (buttonItem) {
+ if (buttonItem->dwFlags & BUTTON_ISINTERNAL) {
+ switch (buttonItem->uId) {
+ case IDC_TBSOUND:
+ SendMessage(buttonItem->hWnd, BM_SETCHECK, cfg::dat.soundsOff ? BST_UNCHECKED : BST_CHECKED, 0);
+ break;
+ case IDC_TBHIDEOFFLINE:
+ SendMessage(buttonItem->hWnd, BM_SETCHECK, iMode ? BST_CHECKED : BST_UNCHECKED, 0);
+ break;
+ case IDC_TBHIDEGROUPS:
+ SendMessage(buttonItem->hWnd, BM_SETCHECK, cfg::getByte("CList", "UseGroups", 0) ? BST_CHECKED : BST_UNCHECKED, 0);
+ break;
+ }
+ }
+ buttonItem = buttonItem->nextItem;
+ }
+}
+
+
+void ReloadThemedOptions()
+{
+ cfg::dat.bUsePerProto = cfg::getByte("CLCExt", "useperproto", 0);
+ cfg::dat.bOverridePerStatusColors = cfg::getByte("CLCExt", "override_status", 0);
+ cfg::dat.bRowSpacing = cfg::getByte("CLC", "RowGap", 0);
+ cfg::dat.exIconScale = cfg::getByte("CLC", "ExIconScale", 16);
+ cfg::dat.bApplyIndentToBg = cfg::getByte("CLCExt", "applyindentbg", 0);
+ cfg::dat.gapBetweenFrames = (BYTE)cfg::getDword("CLUIFrames", "GapBetweenFrames", 1);
+ cfg::dat.bUseDCMirroring = cfg::getByte("CLC", "MirrorDC", 0);
+ cfg::dat.bGroupAlign = cfg::getByte("CLC", "GroupAlign", 0);
+ cfg::dat.bUseFloater = cfg::getByte("CLUI", "FloaterMode", 0);
+ cfg::dat.titleBarHeight = cfg::getByte("CLCExt", "frame_height", DEFAULT_TITLEBAR_HEIGHT);
+ cfg::dat.group_padding = cfg::getDword("CLCExt", "grp_padding", 0);
+}
+
+static RECT rcWindow = {0};
+
+static void sttProcessResize(HWND hwnd, NMCLISTCONTROL *nmc)
+{
+ RECT rcTree, rcWorkArea, rcOld;
+ int maxHeight, newHeight;
+ int winstyle, skinHeight = 0;
+
+ if (disableautoupd)
+ return;
+
+ if (!cfg::getByte("CLUI", "AutoSize", 0))
+ return;
+
+ if (Docking_IsDocked(0, 0))
+ return;
+ if (hFrameContactTree == 0)
+ return;
+
+ maxHeight = cfg::getByte("CLUI", "MaxSizeHeight", 75);
+ rcOld = rcWindow;
+
+ GetWindowRect(hwnd, &rcWindow);
+ GetWindowRect(pcli->hwndContactTree, &rcTree);
+ winstyle = GetWindowLong(pcli->hwndContactTree, GWL_STYLE);
+
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, FALSE);
+ if (nmc->pt.y > (rcWorkArea.bottom - rcWorkArea.top)) {
+ nmc->pt.y = (rcWorkArea.bottom - rcWorkArea.top);
+ }
+
+ if (winstyle & CLS_SKINNEDFRAME) {
+ BOOL hasTitleBar = wndFrameCLC ? wndFrameCLC->TitleBar.ShowTitleBar : 0;
+ TStatusItem *item = &Skin::statusItems[(hasTitleBar ? ID_EXTBKOWNEDFRAMEBORDERTB : ID_EXTBKOWNEDFRAMEBORDER)];
+ skinHeight = item->IGNORED ? 0 : item->MARGIN_BOTTOM + item->MARGIN_TOP;
+ }
+
+ newHeight = max(nmc->pt.y, 3) + 1 + ((winstyle & WS_BORDER) ? 2 : 0) + skinHeight + (rcWindow.bottom - rcWindow.top) - (rcTree.bottom - rcTree.top);
+ if (newHeight == (rcWindow.bottom - rcWindow.top))
+ return;
+
+ if (newHeight > (rcWorkArea.bottom - rcWorkArea.top)*maxHeight / 100)
+ newHeight = (rcWorkArea.bottom - rcWorkArea.top) * maxHeight / 100;
+ if (cfg::getByte("CLUI", "AutoSizeUpward", 0)) {
+ rcWindow.top = rcWindow.bottom - newHeight;
+ if (rcWindow.top < rcWorkArea.top) rcWindow.top = rcWorkArea.top;
+ } else {
+ rcWindow.bottom = rcWindow.top + newHeight;
+ if (rcWindow.bottom > rcWorkArea.bottom) rcWindow.bottom = rcWorkArea.bottom;
+ }
+ if (cfg::dat.szOldCTreeSize.cx != rcTree.right - rcTree.left) {
+ cfg::dat.szOldCTreeSize.cx = rcTree.right - rcTree.left;
+ return;
+ }
+ KillTimer(hwnd, TIMERID_AUTOSIZE);
+ SetTimer(hwnd, TIMERID_AUTOSIZE, 50, 0);
+}
+
+BP_PAINTPARAMS bppp = {0, 0, 0, 0};
+
+static char* _sbItemNames[] = {
+ "@ScrollBackUpper",
+ "@ScrollBackLower",
+ "@ScrollThumb",
+ "@ScrollButton",
+ "@ScrollArrowUp",
+ "@ScrollArrowDn"
+};
+
+#define ID_SBARSKIN_BACK_UPR 0
+#define ID_SBARSKIN_BACK_LWR 1
+#define ID_SBARSKIN_THUMB 2
+#define ID_SBARSKIN_BUTTON 3
+#define ID_SBARSKIN_ARROWUP 4
+#define ID_SBARSKIN_ARROWDN 5
+
+/**
+ * draw the custom scroll bar
+ * TODO Scrollbar: improve this to allow selective skinning of hovered/selected/pressed
+ * elements.
+ * @param nmcsbcd custom control drawing structure
+ * @return
+ */
+int CustomDrawScrollBars(NMCSBCUSTOMDRAW *nmcsbcd)
+{
+ switch (nmcsbcd->hdr.code) {
+ case NM_COOLSB_CUSTOMDRAW: {
+ static HDC hdcScroll = 0;
+ //static HBITMAP hbmScroll, hbmScrollOld;
+ static LONG scrollLeft, scrollRight, scrollHeight, scrollYmin, scrollYmax;
+
+ switch (nmcsbcd->dwDrawStage) {
+ case CDDS_PREPAINT:
+ if (cfg::dat.bSkinnedScrollbar)
+ return CDRF_SKIPDEFAULT;
+ else
+ return CDRF_DODEFAULT;
+ case CDDS_POSTPAINT:
+ return 0;
+ case CDDS_ITEMPREPAINT: {
+ HDC hdc = nmcsbcd->hdc;
+ UINT uItemID = ID_SBARSKIN_BACK_UPR;
+ RECT rcWindow;
+ POINT pt;
+ DWORD dfcFlags;
+ GetWindowRect(pcli->hwndContactTree, &rcWindow);
+ pt.x = rcWindow.left;
+ pt.y = rcWindow.top;
+ ScreenToClient(pcli->hwndContactList, &pt);
+
+ bppp.cbSize = sizeof(BP_PAINTPARAMS);
+ HANDLE hbp = Api::pfnBeginBufferedPaint(hdc, &nmcsbcd->rect, BPBF_TOPDOWNDIB, &bppp, &hdcScroll);
+
+ //hdcScroll = hdc;
+ BitBlt(hdcScroll, nmcsbcd->rect.left, nmcsbcd->rect.top, nmcsbcd->rect.right - nmcsbcd->rect.left,
+ nmcsbcd->rect.bottom - nmcsbcd->rect.top, cfg::dat.hdcBg, pt.x + nmcsbcd->rect.left, pt.y + nmcsbcd->rect.top, SRCCOPY);
+
+ switch (nmcsbcd->uItem) {
+ case HTSCROLL_UP:
+ case HTSCROLL_DOWN:
+ uItemID = (nmcsbcd->uState == CDIS_DEFAULT || nmcsbcd->uState == CDIS_DISABLED) ? ID_SBARSKIN_BUTTON :
+ (nmcsbcd->uState == CDIS_HOT ? ID_SBARSKIN_BUTTON : ID_SBARSKIN_BUTTON);
+ break;
+ case HTSCROLL_PAGEGDOWN:
+ case HTSCROLL_PAGEGUP:
+ uItemID = nmcsbcd->uItem == HTSCROLL_PAGEGUP ? ID_SBARSKIN_BACK_UPR : ID_SBARSKIN_BACK_LWR;
+ break;
+ case HTSCROLL_THUMB:
+ uItemID = nmcsbcd->uState == CDIS_HOT ? ID_SBARSKIN_THUMB : ID_SBARSKIN_THUMB;
+ uItemID = nmcsbcd->uState == CDIS_SELECTED ? ID_SBARSKIN_THUMB : ID_SBARSKIN_THUMB;
+ break;
+ default:
+ break;
+ }
+
+ Skin::renderNamedImageItem(_sbItemNames[uItemID], &nmcsbcd->rect, hdcScroll);
+ dfcFlags = DFCS_FLAT | (nmcsbcd->uState == CDIS_DISABLED ? DFCS_INACTIVE :
+ (nmcsbcd->uState == CDIS_HOT ? DFCS_HOT :
+ (nmcsbcd->uState == CDIS_SELECTED ? DFCS_PUSHED : 0)));
+
+ if (nmcsbcd->uItem == HTSCROLL_UP)
+ uItemID = ID_SBARSKIN_ARROWUP;
+ if (nmcsbcd->uItem == HTSCROLL_DOWN)
+ uItemID = ID_SBARSKIN_ARROWDN;
+ Skin::renderNamedImageItem(_sbItemNames[uItemID], &nmcsbcd->rect, hdcScroll);
+ Api::pfnEndBufferedPaint(hbp, TRUE);
+ }
+ default:
+ break;
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
+static int ServiceParamsOK(TButtonItem *item, WPARAM *wParam, LPARAM *lParam, MCONTACT hContact)
+{
+ if (item->dwFlags & BUTTON_PASSHCONTACTW || item->dwFlags & BUTTON_PASSHCONTACTL || item->dwFlags & BUTTON_ISCONTACTDBACTION) {
+ if (hContact == 0)
+ return 0;
+ if (item->dwFlags & BUTTON_PASSHCONTACTW)
+ *wParam = (WPARAM)hContact;
+ else if (item->dwFlags & BUTTON_PASSHCONTACTL)
+ *lParam = (LPARAM)hContact;
+ return 1;
+ }
+ return 1; // doesn't need a paramter
+}
+void CLUI::Show(HWND hwnd)
+{
+ int state = old_cliststate;
+ int onTop = cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT);
+
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, FALSE);
+ if (state == SETTING_STATE_NORMAL) {
+ ShowWindow(pcli->hwndContactList, SW_SHOWNORMAL);
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ Redraw();
+ } else if (state == SETTING_STATE_MINIMIZED) {
+ cfg::dat.forceResize = TRUE;
+ ShowWindow(pcli->hwndContactList, SW_HIDE);
+ } else if (state == SETTING_STATE_HIDDEN) {
+ cfg::dat.forceResize = TRUE;
+ ShowWindow(pcli->hwndContactList, SW_HIDE);
+ }
+ SetWindowPos(pcli->hwndContactList, onTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING);
+ if (cfg::dat.autosize) {
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0);
+ }
+ SFL_Create();
+ SFL_SetState(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE ? (old_cliststate == SETTING_STATE_NORMAL ? 0 : 1) : 1);
+}
+
+#define M_CREATECLC (WM_USER+1)
+LRESULT CALLBACK CLUI::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_CREATE: {
+ int i;
+ wchar_t szSkinFile[MAX_PATH];
+ wchar_t* pszSkinToLoad = 0;
+ DBVARIANT dbv = {0};
+
+ SetMenu(hwnd, 0);
+ Skin::Unload();
+ if(0 == cfg::getTString(0, SKIN_DB_MODULE, "gCurrentSkin", &dbv)) {
+ mir_sntprintf(szSkinFile, MAX_PATH, L"%s%s", cfg::szProfileDir, dbv.ptszVal);
+ if(PathFileExistsW(szSkinFile))
+ pszSkinToLoad = szSkinFile;
+ db_free(&dbv);
+ }
+ SkinLoader *sLoader = new SkinLoader(pszSkinToLoad);
+
+ if(sLoader->isValid())
+ sLoader->Load();
+ else
+ WarningDlg::show(WarningDlg::WARN_SKIN_LOADER_ERROR, WarningDlg::CWF_UNTRANSLATED|MB_OK|MB_ICONERROR);
+ delete sLoader;
+
+ Skin::updateAeroState();
+ int flags = WS_CHILD | CCS_BOTTOM;
+ flags |= cfg::getByte("CLUI", "ShowSBar", 1) ? WS_VISIBLE : 0;
+ pcli->hwndStatus = CreateWindowExW(0, STATUSCLASSNAME, NULL, flags, 0, 0, 0, 0, hwnd, NULL, g_hInst, NULL);
+ //SendMessage(pcli->hwndStatus, SB_SETMINHEIGHT, 12, 0);
+ if (flags & WS_VISIBLE) {
+ ShowWindow(pcli->hwndStatus, SW_SHOW);
+ SendMessage(pcli->hwndStatus, WM_SIZE, 0, 0);
+ }
+ OldStatusBarProc = (WNDPROC)SetWindowLongPtr(pcli->hwndStatus, GWLP_WNDPROC, (LONG_PTR)NewStatusBarWndProc);
+ SetClassLong(pcli->hwndStatus, GCL_STYLE, GetClassLong(pcli->hwndStatus, GCL_STYLE) & ~(CS_VREDRAW | CS_HREDRAW));
+
+ g_oldSize.cx = g_oldSize.cy = 0;
+ old_cliststate = cfg::getByte("CList", "State", SETTING_STATE_NORMAL);
+ cfg::writeByte("CList", "State", SETTING_STATE_HIDDEN);
+ SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_VISIBLE);
+ SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CLIPCHILDREN);
+ if (!cfg::dat.bFirstRun)
+ configureEventArea(hwnd);
+ CluiProtocolStatusChanged(0, 0);
+
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ statusNames[i - ID_STATUS_OFFLINE] = pcli->pfnGetStatusModeDescription(i, 0);
+
+ SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | (WS_EX_LAYERED));
+
+#ifndef _USE_D2D
+ SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 255, LWA_ALPHA);
+#endif
+ transparentFocus = 1;
+
+ TranslateMenu(GetMenu(hwnd));
+ PostMessage(hwnd, M_CREATECLC, 0, 0);
+ bf.BlendOp = AC_SRC_OVER;
+ bf.AlphaFormat = AC_SRC_ALPHA;
+ bf.SourceConstantAlpha = 255;
+
+ ulwInfo.cbSize = sizeof(UPDATELAYEREDWINDOWINFO);
+ ulwInfo.pblend = &bf;
+ Skin::setAeroMargins();
+ return FALSE;
+ }
+ case WM_NCCREATE: {
+ LPCREATESTRUCT p = (LPCREATESTRUCT)lParam;
+ p->style &= ~(CS_HREDRAW | CS_VREDRAW);
+ pcli->hwndContactList = hwnd;
+ }
+ break;
+ case M_CREATECLC: {
+ CreateButtonBar(hwnd);
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, FALSE);
+ {
+ ShowWindow(pcli->hwndContactList, SW_HIDE);
+ applyBorderStyle();
+ configureGeometry(0);
+ SendMessage(hwnd, WM_SIZE, 0, 0);
+ SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOACTIVATE);
+ }
+
+ if (cfg::dat.soundsOff)
+ hSoundHook = HookEvent(ME_SKIN_PLAYINGSOUND, ClcSoundHook);
+ configureWindowLayout();
+ setButtonStates(hwnd);
+
+ createCLC(hwnd);
+ cfg::clcdat = (struct ClcData *)GetWindowLongPtr(pcli->hwndContactTree, 0);
+
+ cfg::writeByte("CList", "State", old_cliststate);
+
+ if (cfg::getByte("CList", "AutoApplyLastViewMode", 0)) {
+ DBVARIANT dbv = {0};
+ if (!db_get(NULL, "CList", "LastViewMode", &dbv)) {
+ if (lstrlenA(dbv.pszVal) > 2) {
+ if (cfg::getDword(NULL, CLVM_MODULE, dbv.pszVal, -1) != 0xffffffff)
+ ApplyViewMode((char *)dbv.pszVal);
+ }
+ db_free(&dbv);
+ }
+ }
+ Show(hwnd);
+ return 0;
+ }
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ RECT rc, rcFrame, rcClient;
+ HDC hdc;
+ HDC hdcReal = BeginPaint(hwnd, &ps);
+ TImageItem* activeItem = cfg::isAero ? bgImageItem : bgImageItem_nonAero;
+
+ GetClientRect(hwnd, &rcClient);
+ CopyRect(&rc, &rcClient);
+
+ if (!cfg::dat.hdcBg || rc.right != cfg::dat.dcSize.cx || rc.bottom + Skin::metrics.bSBarHeight != cfg::dat.dcSize.cy) {
+ cfg::dat.dcSize.cy = rc.bottom + Skin::metrics.bSBarHeight;
+ cfg::dat.dcSize.cx = rc.right;
+ if (cfg::dat.hdcBg) {
+ SelectObject(cfg::dat.hdcBg, cfg::dat.hbmBgOld);
+ DeleteObject(cfg::dat.hbmBg);
+ DeleteDC(cfg::dat.hdcBg);
+ }
+ cfg::dat.hdcBg = CreateCompatibleDC(hdcReal);
+ cfg::dat.hbmBg = Gfx::createRGBABitmap(cfg::dat.dcSize.cx, cfg::dat.dcSize.cy);
+ cfg::dat.hbmBgOld = reinterpret_cast<HBITMAP>(SelectObject(cfg::dat.hdcBg, cfg::dat.hbmBg));
+ }
+
+ if (cfg::shutDown) {
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+
+ hdc = cfg::dat.hdcBg;
+
+ CopyRect(&rcFrame, &rcClient);
+
+ cfg::dat.ptW.x = cfg::dat.ptW.y = 0;
+ ClientToScreen(hwnd, &cfg::dat.ptW);
+
+ if(cfg::isAero)
+ FillRect(hdc, &rcClient, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
+ else if (g_CLUISkinnedBkColor)
+ FillRect(hdc, &rcClient, g_CLUISkinnedBkColor);
+ if(!Skin::metrics.fHaveFrame) {
+ if (activeItem) {
+ Gfx::renderImageItem(hdc, activeItem, &rcFrame);
+ goto skipbg;
+ }
+ }
+ else {
+ if(bgClientItem) {
+ Gfx::renderImageItem(hdc, bgClientItem, &rcFrame);
+ goto skipbg;
+ }
+ }
+
+ rcFrame.left += (Skin::metrics.cLeft - 1);
+ rcFrame.right -= (Skin::metrics.cRight - 1);
+ rcFrame.bottom++;
+ rcFrame.bottom -= Skin::metrics.bSBarHeight;
+ rcFrame.top += (Skin::metrics.dwTopOffset - 1);
+
+ if (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN) {
+ InflateRect(&rcFrame, 1, 1);
+ if (cfg::dat.bSkinnedButtonMode)
+ rcFrame.bottom -= (Skin::metrics.dwBottomOffset);
+ DrawEdge(hdc, &rcFrame, BDR_SUNKENOUTER, BF_RECT);
+ }
+skipbg:
+#ifndef _USE_D2D
+ BitBlt(hdcReal, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdc, 0, 0, SRCCOPY);
+#endif
+ EndPaint(hwnd, &ps);
+ /*
+ if(renderTarget) {
+ renderTarget->BeginDraw();
+ ID2D1SolidColorBrush* brush;
+ D2D1_COLOR_F clr;
+ clr.b = clr.r = clr.g = 0.0;
+ clr.r = 25.0;
+ clr.a = 0.0;
+
+ D2D1_BRUSH_PROPERTIES bp;
+ bp.transform = D2D1::Matrix3x2F();
+ bp.opacity = 0.0;
+ D2D1_RECT_F rect;
+ rect.left = rect.top = 0;
+ rect.right = rcClient.right;
+ rect.bottom = rcClient.bottom;
+ renderTarget->CreateSolidColorBrush(clr, bp, &brush);
+ renderTarget->FillRectangle(&rect, brush);
+ renderTarget->EndDraw();
+ brush->Release();
+ }
+ */
+#ifdef _USE_D2D
+ //updateLayers();
+#endif
+ return 0;
+ }
+
+ case WM_NCPAINT:
+ if(Skin::metrics.fHaveFrame)
+ break;
+ return(0);
+
+ case WM_ENTERSIZEMOVE: {
+ RECT rc;
+ POINT pt = {0};
+
+ GetWindowRect(hwnd, &g_PreSizeRect);
+ GetClientRect(hwnd, &rc);
+ ClientToScreen(hwnd, &pt);
+ g_CLUI_x_off = pt.x - g_PreSizeRect.left;
+ g_CLUI_y_off = pt.y - g_PreSizeRect.top;
+ pt.x = rc.right;
+ ClientToScreen(hwnd, &pt);
+ g_CLUI_x1_off = g_PreSizeRect.right - pt.x;
+ pt.x = 0;
+ pt.y = rc.bottom;
+ ClientToScreen(hwnd, &pt);
+ g_CLUI_y1_off = g_PreSizeRect.bottom - pt.y;
+ break;
+ }
+ case WM_EXITSIZEMOVE:
+ PostMessage(hwnd, CLUIINTM_REDRAW, 0, 0);
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ return(0);
+
+ case WM_WINDOWPOSCHANGING: {
+ WINDOWPOS *wp = (WINDOWPOS *)lParam;
+
+ if (wp && wp->flags & SWP_NOSIZE)
+ return FALSE;
+
+ if (Docking_IsDocked(0, 0))
+ break;
+
+ if (pcli->hwndContactList != NULL) {
+
+ //dsize.width = rcOld.right - rcOld.left;
+ //dsize.height = rcOld.bottom - rcOld.top;
+
+ /*
+ if(0 == renderTarget) {
+ D2D1_RENDER_TARGET_PROPERTIES rp = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), 0, 0, D2D1_RENDER_TARGET_USAGE_NONE,
+ D2D1_FEATURE_LEVEL_DEFAULT);
+
+ D2D1_HWND_RENDER_TARGET_PROPERTIES hp = D2D1::HwndRenderTargetProperties(hwnd, dsize, D2D1_PRESENT_OPTIONS_NONE);
+ Gfx::pD2DFactory->CreateHwndRenderTarget(&rp, &hp, &renderTarget);
+ if(0 == renderTarget)
+ MessageBox(0, L"Creating render target failed", L"foo", MB_OK);
+
+ }
+ else
+ renderTarget->Resize(&dsize);
+ */
+ fInSizing = true;
+
+ newRect.left = 0;
+ newRect.right = wp->cx - (g_CLUI_x_off + g_CLUI_x1_off);
+ newRect.top = 0;
+ newRect.bottom = wp->cy - g_CLUI_y_off - g_CLUI_y1_off;
+
+ if(!cfg::isAero)
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ if (cfg::dat.dwFlags & CLUI_FRAME_SBARSHOW) {
+ RECT rcStatus;
+ SetWindowPos(pcli->hwndStatus, 0, 0, newRect.bottom - 20 - (Skin::metrics.fHaveFrame ? 0 : Skin::metrics.cFakeBtmBorder), newRect.right, 20, SWP_NOZORDER);
+ GetWindowRect(pcli->hwndStatus, &rcStatus);
+ Skin::metrics.bSBarHeight = (rcStatus.bottom - rcStatus.top);
+ } else
+ Skin::metrics.bSBarHeight = 0;
+
+ SizeFramesByWindowRect(&newRect);
+ dock_prevent_moving = 0;
+ layoutButtons(hwnd, &newRect);
+ if (wp->cx != g_oldSize.cx)
+ SendMessage(hwnd, CLUIINTM_STATUSBARUPDATE, 0, 0);
+ dock_prevent_moving = 1;
+ g_oldPos.x = wp->x;
+ g_oldPos.y = wp->y;
+ g_oldSize.cx = wp->cx;
+ g_oldSize.cy = wp->cy;
+ rcWPC = newRect;
+
+ fInSizing = false;
+ }
+ fInSizing = false;
+ return(0);
+ }
+
+ case WM_SIZE: {
+ RECT rc;
+
+ if ((wParam == 0 && lParam == 0) || Docking_IsDocked(0, 0)) {
+
+ if (IsZoomed(hwnd))
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+
+ if (pcli->hwndContactList != 0) {
+ SendMessage(hwnd, WM_ENTERSIZEMOVE, 0, 0);
+ GetWindowRect(hwnd, &rc);
+ WINDOWPOS wp = {0};
+ wp.cx = rc.right - rc.left;
+ wp.cy = rc.bottom - rc.top;
+ wp.x = rc.left;
+ wp.y = rc.top;
+ wp.flags = 0;
+ SendMessage(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&wp);
+ SendMessage(hwnd, WM_EXITSIZEMOVE, 0, 0);
+ }
+ }
+ }
+ case WM_MOVE:
+ if (!IsIconic(hwnd)) {
+ RECT rc;
+ GetWindowRect(hwnd, &rc);
+
+ if (!Docking_IsDocked(0, 0)) {
+ cluiPos.bottom = (DWORD)(rc.bottom - rc.top);
+ cluiPos.left = rc.left;
+ cluiPos.top = rc.top;
+ }
+ cluiPos.right = rc.right - rc.left;
+ if (cfg::dat.realTimeSaving) {
+ RECT rc;
+ GetWindowRect(hwnd, &rc);
+
+ if (!CallService(MS_CLIST_DOCKINGISDOCKED, 0, 0)) { //if docked, dont remember pos (except for width)
+ cfg::writeDword("CList", "Height", (DWORD)(rc.bottom - rc.top));
+ cfg::writeDword("CList", "x", (DWORD) rc.left);
+ cfg::writeDword("CList", "y", (DWORD) rc.top);
+ }
+ cfg::writeDword("CList", "Width", (DWORD)(rc.right - rc.left));
+ }
+ }
+ return TRUE;
+
+ case WM_SETFOCUS:
+ SetFocus(pcli->hwndContactTree);
+ return 0;
+
+ case CLUIINTM_REMOVEFROMTASKBAR: {
+ if (Skin::metrics.bWindowStyle == SETTING_WINDOWSTYLE_DEFAULT && cfg::getByte("CList", "AlwaysHideOnTB", 0))
+ removeFromTaskBar(hwnd);
+ return 0;
+ }
+ case WM_ACTIVATE:
+ if (fading_active) {
+ if (wParam != WA_INACTIVE && cfg::dat.isTransparent)
+ transparentFocus = 1;
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ if (wParam == WA_INACTIVE) {
+ if ((HWND) wParam != hwnd)
+ if (cfg::dat.isTransparent)
+ if (transparentFocus)
+ SetTimer(hwnd, TM_AUTOALPHA, 250, NULL);
+ } else {
+ if (cfg::dat.isTransparent) {
+ KillTimer(hwnd, TM_AUTOALPHA);
+ setLayeredAttributes(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.alpha, LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ transparentFocus = 1;
+ }
+ SetWindowPos(pcli->hwndContactList, cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOSENDCHANGING);
+ }
+ PostMessage(hwnd, CLUIINTM_REMOVEFROMTASKBAR, 0, 0);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_SETCURSOR:
+ if (cfg::dat.isTransparent) {
+ if (!transparentFocus && GetForegroundWindow() != hwnd) {
+ setLayeredAttributes(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.alpha, LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ transparentFocus = 1;
+ SetTimer(hwnd, TM_AUTOALPHA, 250, NULL);
+ }
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_NCHITTEST: {
+ LRESULT result;
+ RECT r;
+ POINT pt;
+
+ GetWindowRect(hwnd, &r);
+ GetCursorPos(&pt);
+ if (pt.y <= r.bottom && pt.y >= r.bottom - 6 && !cfg::getByte("CLUI", "AutoSize", 0)) {
+ if (pt.x > r.left + 10 && pt.x < r.right - 10)
+ return HTBOTTOM;
+ if (pt.x < r.left + 10)
+ return HTBOTTOMLEFT;
+ if (pt.x > r.right - 10)
+ return HTBOTTOMRIGHT;
+
+ } else if (pt.y >= r.top && pt.y <= r.top + 3 && !cfg::getByte("CLUI", "AutoSize", 0)) {
+ if (pt.x > r.left + 10 && pt.x < r.right - 10)
+ return HTTOP;
+ if (pt.x < r.left + 10)
+ return HTTOPLEFT;
+ if (pt.x > r.right - 10)
+ return HTTOPRIGHT;
+ } else if (pt.x >= r.left && pt.x <= r.left + 6)
+ return HTLEFT;
+ else if (pt.x >= r.right - 6 && pt.x <= r.right)
+ return HTRIGHT;
+
+ result = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
+ if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT || result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT)
+ if (cfg::dat.autosize)
+ return HTCLIENT;
+ return result;
+ }
+
+ case WM_TIMER:
+ if ((int) wParam == TM_AUTOALPHA) {
+ int inwnd;
+
+ if (GetForegroundWindow() == hwnd) {
+ KillTimer(hwnd, TM_AUTOALPHA);
+ inwnd = 1;
+ } else {
+ POINT pt;
+ HWND hwndPt;
+ pt.x = (short) LOWORD(GetMessagePos());
+ pt.y = (short) HIWORD(GetMessagePos());
+ hwndPt = WindowFromPoint(pt);
+ inwnd = (hwndPt == hwnd || GetParent(hwndPt) == hwnd);
+ }
+ if (inwnd != transparentFocus) {
+ //change
+ transparentFocus = inwnd;
+ if (transparentFocus)
+ setLayeredAttributes(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.alpha, LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ else
+ setLayeredAttributes(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.autoalpha, LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ }
+ if (!transparentFocus)
+ KillTimer(hwnd, TM_AUTOALPHA);
+ } else if (wParam == TIMERID_AUTOSIZE) {
+ KillTimer(hwnd, wParam);
+ SetWindowPos(hwnd, 0, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
+ SendMessage(hwnd, WM_SIZE, 0, 0);
+ if(cfg::isAero)
+ RedrawWindow(hwnd, 0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ else
+ PostMessage(hwnd, CLUIINTM_REDRAW, 0, 0);
+ }
+ return TRUE;
+ case WM_SHOWWINDOW: {
+ static int noRecurse = 0;
+ DWORD thisTick, startTick;
+ int sourceAlpha, destAlpha;
+
+ if (cfg::dat.forceResize && wParam != SW_HIDE) {
+ cfg::dat.forceResize = FALSE;
+ PostMessage(hwnd, WM_SIZE, 0, 0);
+ PostMessage(hwnd, CLUIINTM_REDRAW, 0, 0);
+ }
+ PostMessage(hwnd, CLUIINTM_REMOVEFROMTASKBAR, 0, 0);
+
+ if (g_floatoptions.enabled) {
+ if (wParam)
+ FLT_ShowHideAll(SW_HIDE);
+ else
+ FLT_ShowHideAll(SW_SHOWNOACTIVATE);
+ }
+
+ if (!cfg::dat.fadeinout)
+ SFL_SetState(-1);
+ if (lParam)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ if (noRecurse)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ if (!cfg::dat.fadeinout)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ fading_active = 1;
+
+ if (wParam) {
+ sourceAlpha = 0;
+ destAlpha = cfg::dat.isTransparent ? cfg::dat.alpha : 255;
+ setLayeredAttributes(Skin::metrics.fHaveColorkey ? (COLORREF)cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)sourceAlpha, LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ noRecurse = 1;
+ ShowWindow(hwnd, SW_SHOW);
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+ noRecurse = 0;
+ } else {
+ sourceAlpha = cfg::dat.isTransparent ? (transparentFocus ? cfg::dat.alpha : cfg::dat.autoalpha) : 255;
+ destAlpha = 0;
+ }
+ for (startTick = GetTickCount(); ;) {
+ thisTick = GetTickCount();
+ if (thisTick >= startTick + 200) {
+ SFL_SetState(-1);
+ setLayeredAttributes(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)(destAlpha), LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ fading_active = 0;
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ setLayeredAttributes(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)(sourceAlpha + (destAlpha - sourceAlpha) * (int)(thisTick - startTick) / 200), LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ }
+ //setLayeredAttributes(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)(destAlpha), LWA_ALPHA | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0));
+ //return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+
+ case WM_SYSCOMMAND:
+ if(SETTING_WINDOWSTYLE_DEFAULT == Skin::metrics.bWindowStyle && SC_RESTORE == wParam) {
+ CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
+ SendMessage(hwnd, WM_SIZE, 0, 0);
+ Redraw();
+ cfg::writeByte("CList", "State", SETTING_STATE_NORMAL);
+ break;
+ }
+
+ if (wParam == SC_MAXIMIZE)
+ return 0;
+ else if (wParam == SC_MINIMIZE) {
+ if(SETTING_WINDOWSTYLE_DEFAULT == Skin::metrics.bWindowStyle) {
+ cfg::writeByte("CList", "State", SETTING_STATE_MINIMIZED);
+ break;
+ }
+ pcli->pfnShowHide(0, 0);
+ return 0;
+ }
+ else if (wParam == SC_RESTORE) {
+ pcli->pfnShowHide(0, 0);
+ return(0);
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_COMMAND: {
+ DWORD dwOldFlags = cfg::dat.dwFlags;
+ if (HIWORD(wParam) == BN_CLICKED && lParam != 0) {
+ if (LOWORD(wParam) == IDC_TBFIRSTUID - 1)
+ break;
+ else if (LOWORD(wParam) >= IDC_TBFIRSTUID) { // skinnable buttons handling
+ TButtonItem *item = buttonItems;
+ WPARAM wwParam = 0;
+ LPARAM llParam = 0;
+ MCONTACT hContact = 0;
+ ClcContact *contact = 0;
+ int sel = cfg::clcdat ? cfg::clcdat->selection : -1;
+ int serviceFailure = FALSE;
+
+ if (sel != -1) {
+ sel = pcli->pfnGetRowByIndex(cfg::clcdat, cfg::clcdat->selection, &contact, NULL);
+ if (contact && contact->type == CLCIT_CONTACT) {
+ hContact = contact->hContact;
+ }
+ }
+ while (item) {
+ if (item->uId == (DWORD)LOWORD(wParam)) {
+ int contactOK = ServiceParamsOK(item, &wwParam, &llParam, hContact);
+
+ if (item->dwFlags & BUTTON_ISSERVICE) {
+ if (ServiceExists(item->szService) && contactOK)
+ CallService(item->szService, wwParam, llParam);
+ else if (contactOK)
+ serviceFailure = TRUE;
+ } else if (item->dwFlags & BUTTON_ISPROTOSERVICE && cfg::clcdat) {
+ if (contactOK) {
+ char szFinalService[512];
+
+ mir_snprintf(szFinalService, 512, "%s/%s", GetContactProto(hContact), item->szService);
+ if (ServiceExists(szFinalService))
+ CallService(szFinalService, wwParam, llParam);
+ else
+ serviceFailure = TRUE;
+ }
+ } else if (item->dwFlags & BUTTON_ISDBACTION) {
+ BYTE *pValue;
+ char *szModule = item->szModule;
+ char *szSetting = item->szSetting;
+ MCONTACT finalhContact = 0;
+
+ if (item->dwFlags & BUTTON_ISCONTACTDBACTION || item->dwFlags & BUTTON_DBACTIONONCONTACT) {
+ contactOK = ServiceParamsOK(item, &wwParam, &llParam, hContact);
+ if (contactOK && item->dwFlags & BUTTON_ISCONTACTDBACTION)
+ szModule = GetContactProto(hContact);
+ finalhContact = hContact;
+ } else
+ contactOK = 1;
+
+ if (contactOK) {
+ BOOL fDelete = FALSE;
+
+ if (item->dwFlags & BUTTON_ISTOGGLE) {
+ BOOL fChecked = (SendMessage(item->hWnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED);
+
+ pValue = fChecked ? item->bValueRelease : item->bValuePush;
+ if (fChecked && pValue[0] == 0)
+ fDelete = TRUE;
+ } else
+ pValue = item->bValuePush;
+
+ if (fDelete) {
+ //_DebugTraceA("delete value: %s, %s ON %d", szModule, szSetting, finalhContact);
+ db_unset(finalhContact, szModule, szSetting);
+ } else {
+ switch (item->type) {
+ case DBVT_BYTE:
+ cfg::writeByte(finalhContact, szModule, szSetting, pValue[0]);
+ break;
+ case DBVT_WORD:
+ cfg::writeWord(finalhContact, szModule, szSetting, *((WORD *)&pValue[0]));
+ //_DebugTraceA("set WORD value: %s, %s, %d ON %d", szModule, item->szSetting, *((WORD *)&pValue[0]), finalhContact);
+ break;
+ case DBVT_DWORD:
+ cfg::writeDword(finalhContact, szModule, szSetting, *((DWORD *)&pValue[0]));
+ break;
+ case DBVT_ASCIIZ:
+ cfg::writeString(finalhContact, szModule, szSetting, (char *)pValue);
+ break;
+ }
+ }
+ } else if (item->dwFlags & BUTTON_ISTOGGLE)
+ SendMessage(item->hWnd, BM_SETCHECK, 0, 0);
+ }
+ if (!contactOK)
+ MessageBox(0, _T("The requested action requires a valid contact selection. Please select a contact from the contact list and repeat"), _T("Parameter mismatch"), MB_OK);
+ if (serviceFailure) {
+ char szError[512];
+
+ mir_snprintf(szError, 512, "The service %s specified by the %s button definition was not found. You may need to install additional plugins", item->szService, item->szName);
+ MessageBoxA(0, szError, "Service failure", MB_OK);
+ }
+ break;
+ }
+ item = item->nextItem;
+ }
+ goto buttons_done;
+ }
+ switch (LOWORD(wParam)) {
+ case IDC_TBMENU:
+ case IDC_TBTOPMENU: {
+ RECT rc;
+ HMENU hMenu = Menu_GetMainMenu();
+
+ GetWindowRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc);
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, rc.left, LOWORD(wParam) == IDC_TBMENU ? rc.top : rc.bottom, 0, hwnd, NULL);
+ return 0;
+ }
+ case IDC_TBGLOBALSTATUS:
+ case IDC_TBTOPSTATUS: {
+ RECT rc;
+ HMENU hmenu = Menu_GetStatusMenu();
+ GetWindowRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc);
+ TrackPopupMenu(hmenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, rc.left, rc.top, 0, hwnd, NULL);
+ return 0;
+ }
+ case IDC_TBSOUND: {
+ cfg::dat.soundsOff = !cfg::dat.soundsOff;
+ cfg::writeByte("CLUI", "NoSounds", (BYTE)cfg::dat.soundsOff);
+ cfg::writeByte("Skin", "UseSound", (BYTE)(cfg::dat.soundsOff ? 0 : 1));
+ return 0;
+ }
+ case IDC_TBSELECTVIEWMODE:
+ SendMessage(g_hwndViewModeFrame, WM_COMMAND, IDC_SELECTMODE, lParam);
+ break;
+ case IDC_TBCLEARVIEWMODE:
+ SendMessage(g_hwndViewModeFrame, WM_COMMAND, IDC_RESETMODES, lParam);
+ break;
+ case IDC_TBCONFIGUREVIEWMODE:
+ SendMessage(g_hwndViewModeFrame, WM_COMMAND, IDC_CONFIGUREMODES, lParam);
+ break;
+ case IDC_TBFINDANDADD:
+ CallService(MS_FINDADD_FINDADD, 0, 0);
+ return 0;
+ case IDC_TBACCOUNTS:
+ CallService(MS_PROTO_SHOWACCMGR, 0, 0);
+ break;
+ case IDC_TBOPTIONS:
+ CallService("Options/OptionsCommand", 0, 0);
+ return 0;
+ }
+ } else if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_MAINMENU), (LPARAM)(HANDLE) NULL))
+ return 0;
+
+buttons_done:
+ switch (LOWORD(wParam)) {
+ case ID_TRAY_EXIT:
+ case ID_ICQ_EXIT:
+ cfg::shutDown = 1;
+ if (CallService(MS_SYSTEM_OKTOEXIT, 0, 0))
+ DestroyWindow(hwnd);
+ break;
+ case IDC_TBMINIMIZE:
+ case ID_TRAY_HIDE:
+ pcli->pfnShowHide(0, 0);
+ break;
+ case POPUP_NEWGROUP:
+ SendMessage(pcli->hwndContactTree, CLM_SETHIDEEMPTYGROUPS, 0, 0);
+ CallService(MS_CLIST_GROUPCREATE, 0, 0);
+ break;
+ case POPUP_HIDEOFFLINE:
+ case IDC_TBHIDEOFFLINE:
+ CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)(-1), 0);
+ break;
+ case POPUP_HIDEOFFLINEROOT:
+ SendMessage(pcli->hwndContactTree, CLM_SETHIDEOFFLINEROOT, !SendMessage(pcli->hwndContactTree, CLM_GETHIDEOFFLINEROOT, 0, 0), 0);
+ break;
+ case POPUP_HIDEEMPTYGROUPS: {
+ int newVal = !(GetWindowLong(pcli->hwndContactTree, GWL_STYLE) & CLS_HIDEEMPTYGROUPS);
+ cfg::writeByte("CList", "HideEmptyGroups", (BYTE) newVal);
+ SendMessage(pcli->hwndContactTree, CLM_SETHIDEEMPTYGROUPS, newVal, 0);
+ break;
+ }
+ case POPUP_DISABLEGROUPS:
+ case IDC_TBHIDEGROUPS: {
+ int newVal = !(GetWindowLong(pcli->hwndContactTree, GWL_STYLE) & CLS_USEGROUPS);
+ cfg::writeByte("CList", "UseGroups", (BYTE) newVal);
+ SendMessage(pcli->hwndContactTree, CLM_SETUSEGROUPS, newVal, 0);
+ CheckDlgButton(hwnd, IDC_TBHIDEGROUPS, newVal ? BST_CHECKED : BST_UNCHECKED);
+ break;
+ }
+ case POPUP_HIDEMIRANDA:
+ pcli->pfnShowHide(0, 0);
+ break;
+ case POPUP_VISIBILITY:
+ cfg::dat.dwFlags ^= CLUI_SHOWVISI;
+ break;
+ case POPUP_FRAME:
+ cfg::dat.dwFlags ^= CLUI_FRAME_CLISTSUNKEN;
+ break;
+ case POPUP_BUTTONS:
+ cfg::dat.dwFlags ^= CLUI_FRAME_SHOWBOTTOMBUTTONS;
+ break;
+ case POPUP_SHOWSTATUSICONS:
+ cfg::dat.dwFlags ^= CLUI_FRAME_STATUSICONS;
+ break;
+ case POPUP_FLOATER:
+ cfg::dat.bUseFloater ^= CLUI_USE_FLOATER;
+ if (cfg::dat.bUseFloater & CLUI_USE_FLOATER) {
+ SFL_Create();
+ SFL_SetState(-1);
+ } else
+ SFL_Destroy();
+ cfg::writeByte("CLUI", "FloaterMode", cfg::dat.bUseFloater);
+ break;
+ case POPUP_FLOATER_AUTOHIDE:
+ cfg::dat.bUseFloater ^= CLUI_FLOATER_AUTOHIDE;
+ SFL_SetState(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE ? (cfg::getByte("CList", "State", SETTING_STATE_NORMAL) == SETTING_STATE_NORMAL ? 0 : 1) : 1);
+ cfg::writeByte("CLUI", "FloaterMode", cfg::dat.bUseFloater);
+ break;
+ case POPUP_FLOATER_EVENTS:
+ cfg::dat.bUseFloater ^= CLUI_FLOATER_EVENTS;
+ SFL_SetSize();
+ SFL_Update(0, 0, 0, NULL, FALSE);
+ cfg::writeByte("CLUI", "FloaterMode", cfg::dat.bUseFloater);
+ break;
+ }
+ if (dwOldFlags != cfg::dat.dwFlags) {
+ InvalidateRect(pcli->hwndContactTree, NULL, FALSE);
+ cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags);
+ if ((dwOldFlags & (CLUI_FRAME_SHOWBOTTOMBUTTONS | CLUI_FRAME_CLISTSUNKEN)) != (cfg::dat.dwFlags & (CLUI_FRAME_SHOWBOTTOMBUTTONS | CLUI_FRAME_CLISTSUNKEN))) {
+ configureWindowLayout();
+ configureGeometry(1);
+ }
+ configureEventArea(pcli->hwndContactList);
+ PostMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0);
+ }
+ return FALSE;
+ }
+ case WM_LBUTTONDOWN: {
+ if (buttonItems) {
+ POINT ptMouse, pt;
+ RECT rcClient;
+
+ GetCursorPos(&ptMouse);
+ pt = ptMouse;
+ if (buttonItems)
+ return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y));
+ ScreenToClient(hwnd, &ptMouse);
+ GetClientRect(hwnd, &rcClient);
+ rcClient.bottom = Skin::metrics.dwTopOffset;
+ if (PtInRect(&rcClient, ptMouse))
+ return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y));
+ }
+ break;
+ }
+ case WM_DISPLAYCHANGE:
+ SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0); //forces it to send a cln_listsizechanged
+ break;
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->hwndFrom == pcli->hwndContactTree) {
+ switch (((LPNMHDR) lParam)->code) {
+ case CLN_LISTSIZECHANGE:
+ sttProcessResize(hwnd, (NMCLISTCONTROL*)lParam);
+ return FALSE;
+
+ case NM_CLICK: {
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL *) lParam;
+ DWORD hitFlags;
+ HANDLE hItem;
+
+ hItem = (HANDLE)SendMessage(pcli->hwndContactTree, CLM_HITTEST, (WPARAM) & hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y));
+
+ if ((hitFlags & (CLCHT_NOWHERE | CLCHT_INLEFTMARGIN | CLCHT_BELOWITEMS)) == 0)
+ break;
+ if (cfg::getByte("CLUI", "ClientAreaDrag", SETTING_CLIENTDRAG_DEFAULT)) {
+ POINT pt;
+ pt = nm->pt;
+ ClientToScreen(pcli->hwndContactTree, &pt);
+ return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y));
+ }
+ }
+ return FALSE;
+ }
+ }
+ break;
+ case WM_CONTEXTMENU: {
+ RECT rc;
+ POINT pt;
+
+ pt.x = (short) LOWORD(lParam);
+ pt.y = (short) HIWORD(lParam);
+ // x/y might be -1 if it was generated by a kb click
+ GetWindowRect(pcli->hwndContactTree, &rc);
+ if (pt.x == -1 && pt.y == -1) {
+ // all this is done in screen-coords!
+ GetCursorPos(&pt);
+ // the mouse isnt near the window, so put it in the middle of the window
+ if (!PtInRect(&rc, pt)) {
+ pt.x = rc.left + (rc.right - rc.left) / 2;
+ pt.y = rc.top + (rc.bottom - rc.top) / 2;
+ }
+ }
+ if (PtInRect(&rc, pt)) {
+ HMENU hMenu;
+ hMenu = Menu_BuildGroupMenu();
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL);
+ DestroyTrayMenu(hMenu);
+ return 0;
+ }
+ GetWindowRect(pcli->hwndStatus, &rc);
+ if (PtInRect(&rc, pt)) {
+ HMENU hMenu;
+ if (cfg::getByte("CLUI", "SBarRightClk", 0))
+ hMenu = Menu_GetMainMenu();
+ else
+ hMenu = Menu_GetStatusMenu();
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL);
+ return 0;
+ }
+ }
+ break;
+
+ case WM_MEASUREITEM:
+ if (((LPMEASUREITEMSTRUCT) lParam)->itemData == MENU_MIRANDAMENU) {
+ ((LPMEASUREITEMSTRUCT) lParam)->itemWidth = CXSMICON * 4 / 3;
+ ((LPMEASUREITEMSTRUCT) lParam)->itemHeight = 0;
+ return TRUE;
+ }
+ return Menu_MeasureItem((LPMEASUREITEMSTRUCT)lParam);
+ case WM_DRAWITEM: {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
+
+ if (hbmLockedPoint == 0) {
+ hdcLockedPoint = CreateCompatibleDC(dis->hDC);
+ hbmLockedPoint = CreateCompatibleBitmap(dis->hDC, 5, 5);
+ hbmOldLockedPoint = reinterpret_cast<HBITMAP>(SelectObject(hdcLockedPoint, hbmLockedPoint));
+ }
+ if (dis->hwndItem == pcli->hwndStatus) {
+ ProtocolData *pd = (ProtocolData *)dis->itemData;
+ int nParts = SendMessage(pcli->hwndStatus, SB_GETPARTS, 0, 0);
+ char *szProto;
+ int status, x;
+ SIZE textSize;
+ BYTE showOpts = cfg::getByte("CLUI", "SBarShow", 1);
+ if (IsBadCodePtr((FARPROC)pd))
+ return TRUE;
+ if (cfg::shutDown)
+ return TRUE;
+ szProto = pd->RealName;
+ status = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ SetBkMode(dis->hDC, TRANSPARENT);
+ x = dis->rcItem.left;
+
+ if (showOpts & 1) {
+ HICON hIcon;
+
+ if (status >= ID_STATUS_CONNECTING && status < ID_STATUS_OFFLINE) {
+ char szBuffer[128];
+ mir_snprintf(szBuffer, 128, "%s_conn", pd->RealName);
+ hIcon = IcoLib_GetIcon(szBuffer);
+ } else
+ hIcon = Skin_LoadProtoIcon(szProto, status);
+
+ if (!(showOpts & 6) && cfg::dat.bEqualSections)
+ x = (dis->rcItem.left + dis->rcItem.right - 16) >> 1;
+ if (pd->protopos == 0)
+ x += (cfg::dat.bEqualSections ? (Skin::metrics.cLeft / 2) : Skin::metrics.cLeft);
+ else if (pd->protopos == nParts - 1)
+ x -= (Skin::metrics.cRight / 2);
+ DrawIconEx(dis->hDC, x, 2, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ IcoLib_ReleaseIcon(hIcon);
+
+ if (cfg::getByte("CLUI", "sbar_showlocked", 1)) {
+ if (cfg::getByte(szProto, "LockMainStatus", 0)) {
+ hIcon = Skin_LoadIcon(SKINICON_OTHER_STATUS_LOCKED);
+ if (hIcon != NULL) {
+ DrawIconEx(dis->hDC, x, 2, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ IcoLib_ReleaseIcon(hIcon);
+ }
+ }
+ }
+ x += 18;
+ } else {
+ x += 2;
+ if (pd->protopos == 0)
+ x += (cfg::dat.bEqualSections ? (Skin::metrics.cLeft / 2) : Skin::metrics.cLeft);
+ else if (pd->protopos == nParts - 1)
+ x -= (Skin::metrics.cRight / 2);
+ }
+ dis->rcItem.bottom += (dis->rcItem.top + 16);
+ if (showOpts & 2) {
+ wchar_t szName[64];
+ PROTOACCOUNT* pa = Proto_GetAccount( szProto );
+ if ( pa ) {
+ lstrcpyn(szName, pa->tszAccountName, _countof(szName));
+ szName[_countof(szName) - 1] = 0;
+ }
+ else szName[0] = 0;
+
+ if (lstrlen(szName) < sizeof(szName) - 1)
+ lstrcat(szName, _T(" "));
+ GetTextExtentPoint32(dis->hDC, szName, lstrlen(szName), &textSize);
+ dis->rcItem.left += x;
+ Gfx::renderText(dis->hDC, (HANDLE)dis->CtlID, szName, &dis->rcItem, DT_VCENTER | DT_SINGLELINE, 0);
+ x += textSize.cx;
+ }
+ if (showOpts & 4) {
+ wchar_t *szStatus = pcli->pfnGetStatusModeDescription( status, 0 );
+ dis->rcItem.left += x;
+ Gfx::renderText(dis->hDC, (HANDLE)dis->CtlID, szStatus, &dis->rcItem, DT_VCENTER | DT_SINGLELINE, 0);
+ }
+ } else if (dis->CtlType == ODT_MENU) {
+ if (dis->itemData == MENU_MIRANDAMENU)
+ break;
+ return Menu_DrawItem(dis);
+ }
+ return 0;
+ }
+
+ case WM_CLOSE:
+ if(SETTING_WINDOWSTYLE_DEFAULT == Skin::metrics.bWindowStyle && !cfg::getByte("CList", "AlwaysHideOnTB", 0)) {
+ PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ return(0);
+ }
+ pcli->pfnShowHide(0, 0);
+ return(0);
+
+ case CLUIINTM_REDRAW:
+ Redraw();
+ return 0;
+ case CLUIINTM_STATUSBARUPDATE:
+ CluiProtocolStatusChanged(0, 0);
+ return 0;
+
+ case WM_THEMECHANGED:
+ Api::updateState();
+ break;
+
+ case WM_NCDESTROY:
+#if _USE_D2D
+ if(renderTarget) {
+ renderTarget->Release();
+ renderTarget = 0;
+ }
+#endif
+ break;
+
+ case WM_DESTROY:
+ if (cfg::dat.hdcBg) {
+ SelectObject(cfg::dat.hdcBg, cfg::dat.hbmBgOld);
+ DeleteObject(cfg::dat.hbmBg);
+ DeleteDC(cfg::dat.hdcBg);
+ cfg::dat.hdcBg = NULL;
+ }
+ FreeProtocolData();
+ if (hdcLockedPoint) {
+ SelectObject(hdcLockedPoint, hbmOldLockedPoint);
+ DeleteObject(hbmLockedPoint);
+ DeleteDC(hdcLockedPoint);
+ }
+ /*
+ * if this has not yet been set, do it now.
+ * indicates that clist is shutting down and prevents various things
+ * from happening at shutdown.
+ */
+ if (!cfg::shutDown)
+ cfg::shutDown = 1;
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)hFrameContactTree, (LPARAM)0);
+ break;
+ }
+ return saveContactListWndProc(hwnd, msg, wParam, lParam);
+}
+
+static int MetaChanged(WPARAM wParam, LPARAM lParam)
+{
+ pcli->pfnClcBroadcast(INTM_METACHANGEDEVENT, wParam, lParam);
+ return 0;
+}
+
+static BOOL g_AboutDlgActive = 0;
+
+INT_PTR CALLBACK DlgProcAbout(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HICON hIcon;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ {
+ int h;
+ HFONT hFont;
+ LOGFONT lf;
+
+ g_AboutDlgActive = TRUE;
+ hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_GETFONT, 0, 0);
+ GetObject(hFont, sizeof(lf), &lf);
+ h = lf.lfHeight;
+ lf.lfHeight = (int)(lf.lfHeight * 1.5);
+ lf.lfWeight = FW_BOLD;
+ hFont = CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_SETFONT, (WPARAM)hFont, 0);
+ lf.lfHeight = h;
+ hFont = CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg, IDC_VERSION, WM_SETFONT, (WPARAM)hFont, 0);
+ }
+ {
+ char str[64];
+ DWORD v = pluginInfo.version;
+ mir_snprintf(str, sizeof(str), "%s %d.%d.%d.%d (Unicode)", Translate("Version"), HIBYTE(HIWORD(v)), LOBYTE(HIWORD(v)), HIBYTE(LOWORD(v)), LOBYTE(LOWORD(v)));
+ SetDlgItemTextA(hwndDlg, IDC_VERSION, str);
+ mir_snprintf(str, sizeof(str), Translate("Built %s %s"), __DATE__, __TIME__);
+ SetDlgItemTextA(hwndDlg, IDC_BUILDTIME, str);
+ }
+ hIcon = LoadIcon(GetModuleHandleA("miranda32.exe"), MAKEINTRESOURCE(102));
+ SendDlgItemMessage(hwndDlg, IDC_LOGO, STM_SETICON, (WPARAM)hIcon, 0);
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ case IDC_SUPPORT:
+ //CallService(MS_UTILS_OPENURL, 1, (LPARAM)"http://miranda-im.org/download/details.php?action=viewfile&id=2365");
+ break;
+ }
+ break;
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_WHITERECT)
+ || (HWND)lParam == GetDlgItem(hwndDlg, IDC_CLNICER)
+ || (HWND)lParam == GetDlgItem(hwndDlg, IDC_VERSION)
+ || (HWND)lParam == GetDlgItem(hwndDlg, IDC_BUILDTIME)
+ || (HWND)lParam == GetDlgItem(hwndDlg, IDC_COPYRIGHT)
+ || (HWND)lParam == GetDlgItem(hwndDlg, IDC_SUPPORT)
+ || (HWND)lParam == GetDlgItem(hwndDlg, IDC_LOGO)) {
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_CLNICER))
+ SetTextColor((HDC)wParam, RGB(180, 10, 10));
+ else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_VERSION))
+ SetTextColor((HDC)wParam, RGB(70, 70, 70));
+ else
+ SetTextColor((HDC)wParam, RGB(0, 0, 0));
+ SetBkColor((HDC)wParam, RGB(255, 255, 255));
+ return (INT_PTR)GetStockObject(WHITE_BRUSH);
+ }
+ break;
+ case WM_DESTROY: {
+ HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_GETFONT, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0), 0);
+ DeleteObject(hFont);
+ hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_VERSION, WM_GETFONT, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_VERSION, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0), 0);
+ DeleteObject(hFont);
+ g_AboutDlgActive = FALSE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CLN_ShowAbout(WPARAM wParam, LPARAM lParam)
+{
+ if (!g_AboutDlgActive)
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CLNABOUT), 0, DlgProcAbout, 0);
+ return 0;
+}
+
+static INT_PTR CLN_ShowMainMenu(WPARAM wParam, LPARAM lParam)
+{
+ HMENU hMenu;
+ POINT pt;
+
+ hMenu = Menu_GetMainMenu();
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, 0, pcli->hwndContactList, NULL);
+ return 0;
+}
+
+static INT_PTR CLN_ShowStatusMenu(WPARAM wParam, LPARAM lParam)
+{
+ HMENU hMenu;
+ POINT pt;
+
+ hMenu = Menu_GetStatusMenu();
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, 0, pcli->hwndContactList, NULL);
+ return 0;
+}
+
+#define MS_CLUI_SHOWMAINMENU "CList/ShowMainMenu"
+#define MS_CLUI_SHOWSTATUSMENU "CList/ShowStatusMenu"
+
+void CLUI::loadModule(void)
+{
+ WNDCLASSW wndclass;
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, CLUI::modulesLoaded);
+ HookEvent(ME_MC_DEFAULTTCHANGED, MetaChanged);
+ HookEvent(ME_MC_SUBCONTACTSCHANGED, MetaChanged);
+
+// InitGroupMenus();
+
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = eventAreaWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = 0;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE);
+ wndclass.lpszMenuName = 0;
+ wndclass.lpszClassName = L"EventAreaClass";
+ RegisterClassW(&wndclass);
+
+ oldhideoffline = cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT);
+ cluiPos.left = cfg::getDword("CList", "x", 600);
+ cluiPos.top = cfg::getDword("CList", "y", 200);
+ cluiPos.right = cfg::getDword("CList", "Width", 150);
+ cluiPos.bottom = cfg::getDword("CList", "Height", 350);
+
+ loadExtraIconModule();
+ SFL_RegisterWindowClass();
+
+ preCreateCLC(pcli->hwndContactList);
+ //cfg::FrameMgr = new CLUIFrames();
+ CreateServiceFunction("CLN/About", CLN_ShowAbout);
+ CreateServiceFunction(MS_CLUI_SHOWMAINMENU, CLN_ShowMainMenu);
+ CreateServiceFunction(MS_CLUI_SHOWSTATUSMENU, CLN_ShowStatusMenu);
+}
+
+
+
+void CLUI::removeFromTaskBar(HWND hWnd)
+{
+ ITaskbarList *pTaskbarList = NULL;
+
+ if (SUCCEEDED(CoCreateInstance(CLSID_TaskbarList, 0, CLSCTX_INPROC_SERVER, IID_ITaskbarList,
+ (void **)(&pTaskbarList))) && pTaskbarList != NULL) {
+ if (SUCCEEDED(pTaskbarList->HrInit())) {
+ pTaskbarList->DeleteTab(hWnd);
+ }
+ pTaskbarList->Release();
+ }
+}
+
+void CLUI::addToTaskBar(HWND hWnd)
+{
+ ITaskbarList *pTaskbarList = NULL;
+
+ if (SUCCEEDED(CoCreateInstance(CLSID_TaskbarList, 0, CLSCTX_INPROC_SERVER, IID_ITaskbarList,
+ (void **)(&pTaskbarList))) && pTaskbarList != NULL) {
+ if (SUCCEEDED(pTaskbarList->HrInit())) {
+ pTaskbarList->AddTab(hWnd);
+ }
+ pTaskbarList->Release();
+ }
+}
+
+void CLUI::updateLayers()
+{
+ SIZE sz;
+ RECT rcWin;
+ POINT ptSrc = {0}, ptDest;
+ GetWindowRect(pcli->hwndContactList, &rcWin);
+ sz.cx = rcWin.right - rcWin.left;
+ sz.cy = rcWin.bottom - rcWin.top;
+ ptDest.x = rcWin.left;
+ ptDest.y = rcWin.top;
+ ulwInfo.dwFlags = ULW_ALPHA;
+ ulwInfo.prcDirty = 0;
+ ulwInfo.hdcSrc = cfg::dat.hdcBg;
+ ulwInfo.pptDst = &ptDest;
+ ulwInfo.pptSrc = &ptSrc;
+ ulwInfo.psize = &sz;
+ Gfx::setBitmapAlpha(cfg::dat.hbmBg, 255);
+ UpdateLayeredWindowIndirect(pcli->hwndContactList, &ulwInfo);
+}
+
+void CLUI::setLayeredAttributes(COLORREF clr, BYTE alpha, DWORD flags)
+{
+ if(cfg::isAero)
+ flags &= LWA_ALPHA;
+
+ SetLayeredWindowAttributes(pcli->hwndContactList, clr, alpha, flags);
+}
diff --git a/plugins/Clist_ng/SRC/cluiopts.cpp b/plugins/Clist_ng/SRC/cluiopts.cpp new file mode 100644 index 0000000000..72d0a78ab3 --- /dev/null +++ b/plugins/Clist_ng/SRC/cluiopts.cpp @@ -0,0 +1,370 @@ +/*
+ * 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: cluiopts.cpp 138 2010-11-01 10:51:15Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+
+extern WNDPROC OldStatusBarProc;
+extern HANDLE hExtraImageApplying;
+extern SIZE g_oldSize;
+extern POINT g_oldPos;
+extern COLORREF g_CLUISkinnedBkColorRGB;
+
+static int opt_clui_changed = 0;
+
+INT_PTR CALLBACK cfg::DlgProcCluiOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ opt_clui_changed = 0;
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_BRINGTOFRONT, cfg::getByte("CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ALWAYSHIDEONTASKBAR, cfg::getByte("CList", "AlwaysHideOnTB", 1) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ONTOP, cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CLIENTDRAG, cfg::getByte("CLUI", "ClientAreaDrag", SETTING_CLIENTDRAG_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_FADEINOUT, cfg::dat.fadeinout ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOSIZE, cfg::dat.autosize);
+ CheckDlgButton(hwndDlg, IDC_ONDESKTOP, cfg::getByte("CList", "OnDesktop", 0) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
+ SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETPOS, 0, cfg::getByte("CLUI", "MaxSizeHeight", 75));
+
+ SendDlgItemMessage(hwndDlg, IDC_CLUIFRAMESBDR, CPM_SETCOLOUR, 0, cfg::getDword("CLUI", "clr_frameborder", RGB(40, 40, 40)));
+
+ CheckDlgButton(hwndDlg, IDC_AUTOSIZEUPWARD, cfg::getByte("CLUI", "AutoSizeUpward", 0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOHIDE, cfg::getByte("CList", "AutoHide", SETTING_AUTOHIDE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETRANGE, 0, MAKELONG(900, 1));
+ SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CList", "HideTime", SETTING_HIDETIME_DEFAULT), 0));
+ Utils::enableDlgControl(hwndDlg, IDC_HIDETIME, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE));
+ Utils::enableDlgControl(hwndDlg, IDC_HIDETIMESPIN, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE));
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC01, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE));
+ if (!IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)) {
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC21, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC22, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_MAXSIZEHEIGHT, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_MAXSIZESPIN, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_AUTOSIZEUPWARD, FALSE);
+ }
+ CheckDlgButton(hwndDlg, IDC_TRANSPARENT, cfg::dat.isTransparent ? BST_CHECKED : BST_UNCHECKED);
+ if (!IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)) {
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC11, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC12, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_TRANSACTIVE, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_TRANSINACTIVE, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_ACTIVEPERC, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_INACTIVEPERC, FALSE);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255));
+ SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255));
+ SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETPOS, TRUE, cfg::dat.alpha);
+ SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETPOS, TRUE, cfg::dat.autoalpha);
+ SendMessage(hwndDlg, WM_HSCROLL, 0x12345678, 0);
+
+ CheckDlgButton(hwndDlg, IDC_USEAERO, Skin::settings.fUseAero ? BST_CHECKED : BST_UNCHECKED);
+ SendDlgItemMessage(hwndDlg, IDC_FRAMEGAPSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0));
+ SendDlgItemMessage(hwndDlg, IDC_FRAMEGAPSPIN, UDM_SETPOS, 0, (LPARAM)cfg::dat.gapBetweenFrames);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_AUTOHIDE) {
+ Utils::enableDlgControl(hwndDlg, IDC_HIDETIME, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE));
+ Utils::enableDlgControl(hwndDlg, IDC_HIDETIMESPIN, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE));
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC01, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE));
+ } else if (LOWORD(wParam) == IDC_TRANSPARENT) {
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC11, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT));
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC12, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT));
+ Utils::enableDlgControl(hwndDlg, IDC_TRANSACTIVE, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT));
+ Utils::enableDlgControl(hwndDlg, IDC_TRANSINACTIVE, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT));
+ Utils::enableDlgControl(hwndDlg, IDC_ACTIVEPERC, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT));
+ Utils::enableDlgControl(hwndDlg, IDC_INACTIVEPERC, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT));
+ } else if (LOWORD(wParam) == IDC_AUTOSIZE) {
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC21, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE));
+ Utils::enableDlgControl(hwndDlg, IDC_STATIC22, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE));
+ Utils::enableDlgControl(hwndDlg, IDC_MAXSIZEHEIGHT, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE));
+ Utils::enableDlgControl(hwndDlg, IDC_MAXSIZESPIN, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE));
+ Utils::enableDlgControl(hwndDlg, IDC_AUTOSIZEUPWARD, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE));
+ }
+ if ((LOWORD(wParam) == IDC_FRAMEGAP || LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_ROWGAP ||
+ LOWORD(wParam) == IDC_MAXSIZEHEIGHT) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()))
+ return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ opt_clui_changed = 1;
+ break;
+
+ case WM_HSCROLL:
+ {
+ char str[10];
+ wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0) / 255);
+ SetDlgItemTextA(hwndDlg, IDC_INACTIVEPERC, str);
+ wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0) / 255);
+ SetDlgItemTextA(hwndDlg, IDC_ACTIVEPERC, str);
+ }
+ if (wParam != 0x12345678) {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ opt_clui_changed = 1;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ BOOL translated;
+ BYTE oldFading;
+ COLORREF clr_cluiframes;
+
+ if(!opt_clui_changed)
+ return TRUE;
+
+ cfg::writeByte("CLUI", "FadeInOut", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_FADEINOUT));
+ cfg::dat.fadeinout = IsDlgButtonChecked(hwndDlg, IDC_FADEINOUT) ? 1 : 0;
+ oldFading = cfg::dat.fadeinout;
+ cfg::dat.fadeinout = FALSE;
+
+ cfg::dat.gapBetweenFrames = GetDlgItemInt(hwndDlg, IDC_FRAMEGAP, &translated, FALSE);
+
+ cfg::writeDword("CLUIFrames", "GapBetweenFrames", cfg::dat.gapBetweenFrames);
+ cfg::writeByte("CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP));
+ SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+
+ cfg::writeByte("CList", "BringToFront", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_BRINGTOFRONT));
+ cfg::writeByte("CList", "AlwaysHideOnTB", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_ALWAYSHIDEONTASKBAR));
+
+ cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags);
+
+ cfg::writeByte("CLUI", "ClientAreaDrag", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CLIENTDRAG));
+
+ clr_cluiframes = (COLORREF)SendDlgItemMessage(hwndDlg, IDC_CLUIFRAMESBDR, CPM_GETCOLOUR, 0, 0);
+
+ if(CLUI::hPenFrames)
+ DeleteObject(CLUI::hPenFrames);
+ CLUI::hPenFrames = CreatePen(PS_SOLID, 1, clr_cluiframes);
+ cfg::writeDword("CLUI", "clr_frameborder", clr_cluiframes);
+
+ CLUI::applyBorderStyle();
+
+ cfg::writeByte("CLUI", "AutoSize", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE));
+
+ if((cfg::dat.autosize = IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE) ? 1 : 0)) {
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0);
+ }
+
+ cfg::writeByte("CLUI", "MaxSizeHeight", (BYTE) GetDlgItemInt(hwndDlg, IDC_MAXSIZEHEIGHT, NULL, FALSE));
+ cfg::writeByte("CLUI", "AutoSizeUpward", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZEUPWARD));
+ cfg::writeByte("CList", "AutoHide", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE));
+ cfg::writeWord("CList", "HideTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_GETPOS, 0, 0));
+
+ cfg::writeByte("CList", "Transparent", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT));
+ cfg::dat.isTransparent = IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT) ? 1 : 0;
+ cfg::writeByte("CList", "Alpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0));
+ cfg::dat.alpha = (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0);
+ cfg::writeByte("CList", "AutoAlpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0));
+ cfg::dat.autoalpha = (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0);
+ cfg::writeByte("CList", "OnDesktop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONDESKTOP));
+ cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags);
+
+ cfg::writeByte(SKIN_DB_MODULE, "sfUseAero", IsDlgButtonChecked(hwndDlg, IDC_USEAERO));
+ if(g_CLUISkinnedBkColorRGB)
+ cfg::dat.colorkey = g_CLUISkinnedBkColorRGB;
+ else {
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ cfg::dat.colorkey = RGB(255, 0, 255);
+ }
+
+ Api::updateState();
+ if(!cfg::isAero) {
+ if (cfg::dat.isTransparent || Skin::metrics.fHaveColorkey) {
+ SetLayeredWindowAttributes(pcli->hwndContactList, 0, 255, LWA_ALPHA | LWA_COLORKEY);
+ SetLayeredWindowAttributes(pcli->hwndContactList,
+ (COLORREF)(Skin::metrics.fHaveColorkey ? cfg::dat.colorkey : 0),
+ (BYTE)(cfg::dat.isTransparent ? cfg::dat.autoalpha : 255),
+ (DWORD)((cfg::dat.isTransparent ? LWA_ALPHA : 0L) | (Skin::metrics.fHaveColorkey ? LWA_COLORKEY : 0L)));
+ } else
+ SetLayeredWindowAttributes(pcli->hwndContactList, RGB(0, 0, 0), (BYTE)255, LWA_ALPHA);
+ }
+ CLUI::configureGeometry(1);
+ ShowWindow(pcli->hwndContactList, SW_SHOW);
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
+ RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
+ cfg::dat.fadeinout = oldFading;
+ SFL_SetState(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE ? (cfg::getByte("CList", "State", SETTING_STATE_NORMAL) == SETTING_STATE_NORMAL ? 0 : 1) : 1);
+ opt_clui_changed = 0;
+ return TRUE;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static int opt_sbar_changed = 0;
+
+INT_PTR CALLBACK cfg::DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ opt_sbar_changed = 0;
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOWSBAR, cfg::getByte("CLUI", "ShowSBar", 1) ? BST_CHECKED : BST_UNCHECKED); {
+ BYTE showOpts = cfg::getByte("CLUI", "SBarShow", 1);
+ CheckDlgButton(hwndDlg, IDC_SHOWICON, showOpts & 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWPROTO, showOpts & 2 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWSTATUS, showOpts & 4 ? BST_CHECKED : BST_UNCHECKED);
+ }
+ CheckDlgButton(hwndDlg, IDC_RIGHTSTATUS, cfg::getByte("CLUI", "SBarRightClk", 0) ? BST_UNCHECKED : BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_RIGHTMIRANDA, !IsDlgButtonChecked(hwndDlg, IDC_RIGHTSTATUS) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_EQUALSECTIONS, cfg::dat.bEqualSections ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_MARKLOCKED, cfg::getByte("CLUI", "sbar_showlocked", 1));
+
+ if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) {
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWICON, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWPROTO, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWSTATUS, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_RIGHTSTATUS, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_RIGHTMIRANDA, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_EQUALSECTIONS, FALSE);
+ }
+ return TRUE;
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_SHOWSBAR) {
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWICON, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR));
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWPROTO, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR));
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWSTATUS, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR));
+ Utils::enableDlgControl(hwndDlg, IDC_RIGHTSTATUS, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR));
+ Utils::enableDlgControl(hwndDlg, IDC_RIGHTMIRANDA, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR));
+ Utils::enableDlgControl(hwndDlg, IDC_EQUALSECTIONS, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR));
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ opt_sbar_changed = 1;
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ if(!opt_sbar_changed)
+ return TRUE;
+
+ cfg::writeByte("CLUI", "ShowSBar", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR));
+ cfg::writeByte("CLUI", "SBarShow", (BYTE) ((IsDlgButtonChecked(hwndDlg, IDC_SHOWICON) ? 1 : 0) | (IsDlgButtonChecked(hwndDlg, IDC_SHOWPROTO) ? 2 : 0) | (IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS) ? 4 : 0)));
+ cfg::writeByte("CLUI", "SBarRightClk", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_RIGHTMIRANDA));
+ cfg::writeByte("CLUI", "EqualSections", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_EQUALSECTIONS));
+ cfg::writeByte("CLUI", "sbar_showlocked", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_MARKLOCKED));
+
+ cfg::dat.bEqualSections = IsDlgButtonChecked(hwndDlg, IDC_EQUALSECTIONS) ? 1 : 0;
+ if (IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) {
+ ShowWindow(pcli->hwndStatus, SW_SHOW);
+ SendMessage(pcli->hwndStatus, WM_SIZE, 0, 0);
+ cfg::dat.dwFlags |= CLUI_FRAME_SBARSHOW;
+ } else {
+ ShowWindow(pcli->hwndStatus, SW_HIDE);
+ cfg::dat.dwFlags &= ~CLUI_FRAME_SBARSHOW;
+ }
+ cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags);
+ CLUI::configureGeometry(1);
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ CluiProtocolStatusChanged(0, 0);
+ PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0);
+ opt_sbar_changed = 0;
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+DWORD CLUI::getWindowStyle(BYTE style)
+{
+ DWORD dwBasic = WS_CLIPCHILDREN;
+
+ if(style == SETTING_WINDOWSTYLE_THINBORDER)
+ return dwBasic | WS_BORDER;
+ else if(style == SETTING_WINDOWSTYLE_TOOLWINDOW || style == 0)
+ return dwBasic | (WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME);
+ else if(style == SETTING_WINDOWSTYLE_NOBORDER)
+ return dwBasic;
+
+ return dwBasic;
+}
+
+void CLUI::applyBorderStyle()
+{
+ BYTE windowStyle = Skin::metrics.bWindowStyle;
+ WINDOWPLACEMENT p = {0};
+ DWORD style;
+ bool minToTray = TRUE;
+
+ p.length = sizeof(p);
+ GetWindowPlacement(pcli->hwndContactList, &p);
+ ShowWindow(pcli->hwndContactList, SW_HIDE);
+
+ Skin::metrics.fHaveFrame = true;
+
+ if (windowStyle == SETTING_WINDOWSTYLE_DEFAULT || windowStyle == SETTING_WINDOWSTYLE_TOOLWINDOW) {
+ SetWindowLong(pcli->hwndContactList, GWL_STYLE, GetWindowLong(pcli->hwndContactList, GWL_STYLE) | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME);
+ if(SETTING_WINDOWSTYLE_DEFAULT == windowStyle) {
+ SetWindowLong(pcli->hwndContactList, GWL_STYLE, GetWindowLong(pcli->hwndContactList, GWL_STYLE) & ~(WS_MAXIMIZEBOX/* | WS_MINIMIZEBOX*/));
+ minToTray = FALSE;
+ }
+ } else if(windowStyle == SETTING_WINDOWSTYLE_THINBORDER) {
+ SetWindowLong(pcli->hwndContactList, GWL_STYLE, GetWindowLong(pcli->hwndContactList, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME));
+ SetWindowLong(pcli->hwndContactList, GWL_STYLE, GetWindowLong(pcli->hwndContactList, GWL_STYLE) | WS_BORDER | WS_CLIPCHILDREN);
+ }
+ else {
+ SetWindowLong(pcli->hwndContactList, GWL_STYLE, GetWindowLong(pcli->hwndContactList, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME));
+ SetWindowLong(pcli->hwndContactList, GWL_STYLE, GetWindowLong(pcli->hwndContactList, GWL_STYLE) | WS_CLIPCHILDREN);
+ Skin::metrics.fHaveFrame = false;
+ }
+
+ style = GetWindowLong(pcli->hwndContactList, GWL_EXSTYLE);
+ if (windowStyle != SETTING_WINDOWSTYLE_DEFAULT)
+ {
+ style |= WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
+ style &= ~WS_EX_APPWINDOW;
+ }
+ else
+ {
+ style &= ~(WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE);
+ if (cfg::getByte("CList", "AlwaysHideOnTB", 1))
+ style &= ~WS_EX_APPWINDOW;
+ else
+ style |= WS_EX_APPWINDOW;
+ }
+
+ SetWindowLong(pcli->hwndContactList, GWL_EXSTYLE, style);
+ p.showCmd = SW_HIDE;
+ SetWindowPlacement(pcli->hwndContactList, &p);
+
+ cfg::writeByte(0, "CList", "Min2Tray", minToTray);
+}
diff --git a/plugins/Clist_ng/SRC/cluiservices.cpp b/plugins/Clist_ng/SRC/cluiservices.cpp new file mode 100644 index 0000000000..088b0db00e --- /dev/null +++ b/plugins/Clist_ng/SRC/cluiservices.cpp @@ -0,0 +1,264 @@ +/*
+ * 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: cluiservices.cpp 133 2010-09-30 06:27:18Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include <m_icq.h>
+
+extern PLUGININFOEX pluginInfo;
+
+static INT_PTR GetClistVersion(WPARAM wParam, LPARAM lParam)
+{
+ static char g_szVersionString[256];
+
+ mir_snprintf(g_szVersionString, 256, "%s, %d.%d.%d.%d", pluginInfo.shortName, HIBYTE(HIWORD(pluginInfo.version)), LOBYTE(HIWORD(pluginInfo.version)), HIBYTE(LOWORD(pluginInfo.version)), LOBYTE(LOBYTE(pluginInfo.version)));
+ if(!IsBadWritePtr((LPVOID)lParam, 4))
+ *((DWORD *)lParam) = pluginInfo.version;
+
+ return (INT_PTR)g_szVersionString;
+}
+
+
+void FreeProtocolData( void )
+{
+ //free protocol data
+ int nPanel;
+ int nParts=SendMessage(pcli->hwndStatus,SB_GETPARTS,0,0);
+ for (nPanel=0;nPanel<nParts;nPanel++) {
+ ProtocolData *PD;
+ PD=(ProtocolData *)SendMessage(pcli->hwndStatus,SB_GETTEXT,(WPARAM)nPanel,(LPARAM)0);
+ if (PD!=NULL&&!IsBadCodePtr((FARPROC)PD)) {
+ SendMessage(pcli->hwndStatus,SB_SETTEXT,(WPARAM)nPanel|SBT_OWNERDRAW,(LPARAM)0);
+ if (PD->RealName) mir_free(PD->RealName);
+ if (PD) mir_free(PD);
+ }
+ }
+}
+
+char g_maxProto[100] = "";
+
+void CluiProtocolStatusChanged( int parStatus, const char* szProto )
+{
+ int protoCount,i;
+ PROTOACCOUNT **accs;
+ int *partWidths,partCount;
+ int borders[3];
+ int status;
+ int toshow;
+ wchar_t *szStatus = NULL;
+ char *szMaxProto = NULL;
+ int maxOnline = 0, onlineness = 0;
+ WORD maxStatus = ID_STATUS_OFFLINE, wStatus = ID_STATUS_OFFLINE;
+ DBVARIANT dbv = {0};
+ int iIcon = 0;
+ HICON hIcon = 0;
+ int rdelta = Skin::metrics.cLeft + Skin::metrics.cRight;
+ BYTE windowStyle;
+
+ if (pcli->hwndStatus == 0 || cfg::shutDown)
+ return;
+
+ Proto_EnumAccounts( &protoCount, &accs );
+ if (protoCount == 0)
+ return;
+
+ FreeProtocolData();
+ cfg::maxStatus = ID_STATUS_OFFLINE;
+ g_maxProto[0] = 0;
+
+ SendMessage(pcli->hwndStatus,SB_GETBORDERS,0,(LPARAM)&borders);
+
+ partWidths=(int*)_alloca(( protoCount+1)*sizeof(int));
+
+ if (cfg::dat.bEqualSections) {
+ RECT rc;
+ int part;
+ GetClientRect(pcli->hwndStatus,&rc);
+ rc.right-=borders[0]*2;
+ toshow=0;
+ for ( i=0; i < protoCount; i++ )
+ if ( pcli->pfnGetProtocolVisibility( accs[i]->szModuleName ))
+ toshow++;
+
+ if ( toshow > 0 ) {
+ for ( part=0, i=0; i < protoCount; i++ ) {
+ if ( !pcli->pfnGetProtocolVisibility( accs[i]->szModuleName ))
+ continue;
+
+ partWidths[ part ] = ((rc.right-rc.left-rdelta)/toshow)*(part+1) + Skin::metrics.cLeft;
+ if ( part == toshow-1 )
+ partWidths[ part ] += Skin::metrics.cRight;
+ part++;
+ }
+ }
+ partCount=toshow;
+ }
+ else {
+ HDC hdc;
+ SIZE textSize;
+ BYTE showOpts = cfg::getByte("CLUI","SBarShow",1);
+ int x;
+ HFONT hofont;
+ wchar_t szName[32];
+ PROTOACCOUNT* pa;
+
+ hdc=GetDC(NULL);
+ hofont = reinterpret_cast<HFONT>(SelectObject(hdc,(HFONT)SendMessage(pcli->hwndStatus,WM_GETFONT,0,0)));
+
+ for ( partCount=0,i=0; i < protoCount; i++ ) { //count down since built in ones tend to go at the end
+ int idx = pcli->pfnGetAccountIndexByPos( i );
+ if ( idx == -1 )
+ continue;
+
+ pa = accs[idx];
+ if ( !pcli->pfnGetProtocolVisibility( pa->szModuleName ))
+ continue;
+
+ x=2;
+ if (showOpts & 1)
+ x += 16;
+ if (showOpts & 2) {
+ lstrcpyn( szName, pa->tszAccountName, _countof(szName));
+ szName[ _countof(szName)-1 ] = 0;
+ if (( showOpts & 4 ) && lstrlen(szName) < sizeof(szName)-1 )
+ lstrcat( szName, _T(" "));
+ GetTextExtentPoint32( hdc, szName, lstrlen(szName), &textSize );
+ x += textSize.cx + GetSystemMetrics(SM_CXBORDER) * 4; // The SB panel doesnt allocate enough room
+ }
+ if (showOpts & 4) {
+ wchar_t* modeDescr = pcli->pfnGetStatusModeDescription( CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0 ), 0 );
+ GetTextExtentPoint32(hdc, modeDescr, lstrlen(modeDescr), &textSize );
+ x += textSize.cx + GetSystemMetrics(SM_CXBORDER) * 4; // The SB panel doesnt allocate enough room
+ }
+ partWidths[partCount]=(partCount?partWidths[partCount-1]:Skin::metrics.cLeft)+ x + 2;
+ partCount++;
+ }
+ SelectObject(hdc,hofont);
+ ReleaseDC(NULL,hdc);
+ }
+ if (partCount==0) {
+ SendMessage(pcli->hwndStatus,SB_SIMPLE,TRUE,0);
+ return;
+ }
+ SendMessage(pcli->hwndStatus,SB_SIMPLE,FALSE,0);
+
+ partWidths[partCount-1]=-1;
+ windowStyle = Skin::metrics.bWindowStyle;
+ //SendMessage(pcli->hwndStatus,SB_SETMINHEIGHT, 12 + ((windowStyle == SETTING_WINDOWSTYLE_THINBORDER || windowStyle == SETTING_WINDOWSTYLE_NOBORDER) ? 3 : 0), 0);
+ SendMessage(pcli->hwndStatus, SB_SETPARTS, partCount, (LPARAM)partWidths);
+
+ for ( partCount=0, i=0; i < protoCount; i++ ) { //count down since built in ones tend to go at the end
+ ProtocolData *PD;
+ PROTOACCOUNT *pa;
+ int caps1, caps2;
+
+ int idx = pcli->pfnGetAccountIndexByPos( i );
+ if ( idx == -1 )
+ continue;
+
+ pa = accs[idx];
+ if ( !pcli->pfnGetProtocolVisibility( pa->szModuleName ))
+ continue;
+
+ status = CallProtoService( pa->szModuleName,PS_GETSTATUS,0,0);
+ PD = ( ProtocolData* )mir_alloc(sizeof(ProtocolData));
+ PD->RealName = mir_strdup( pa->szModuleName );
+ PD->protopos = partCount;
+ {
+ int flags;
+ flags = SBT_OWNERDRAW;
+ if ( cfg::getByte("CLUI","SBarBevel", 1)==0 )
+ flags |= SBT_NOBORDERS;
+ SendMessageA( pcli->hwndStatus, SB_SETTEXTA, partCount|flags,(LPARAM)PD );
+ }
+ caps2 = CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0);
+ caps1 = CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
+ if((caps1 & PF1_IM) && (caps2 & (PF2_LONGAWAY | PF2_SHORTAWAY))) {
+ onlineness = CLC::getStatusOnlineness(status, false);
+ if(onlineness > maxOnline) {
+ maxStatus = status;
+ maxOnline = onlineness;
+ szMaxProto = pa->szModuleName;
+ }
+ }
+ partCount++;
+ }
+ // update the clui button
+
+ if (!db_get(NULL, "CList", "PrimaryStatus", &dbv)) {
+ if (dbv.type == DBVT_ASCIIZ && lstrlenA(dbv.pszVal) > 1) {
+ wStatus = (WORD) CallProtoService(dbv.pszVal, PS_GETSTATUS, 0, 0);
+ iIcon = CLC::IconFromStatusMode(dbv.pszVal, (int) wStatus, 0, &hIcon);
+ }
+ mir_free(dbv.pszVal);
+ } else {
+ wStatus = maxStatus;
+ iIcon = CLC::IconFromStatusMode((wStatus >= ID_STATUS_CONNECTING && wStatus < ID_STATUS_OFFLINE) ? szMaxProto : NULL, (int) wStatus, 0, &hIcon);
+ cfg::maxStatus = (int)wStatus;
+ if(szMaxProto) {
+ lstrcpynA(g_maxProto, szMaxProto, 100);
+ g_maxProto[99] = 0;
+ }
+ }
+ /*
+ * this is used globally (actually, by the clist control only) to determine if
+ * any protocol is "in connection" state. If true, then the clist discards redraws
+ * and uses timer based sort and redraw handling. This can improve performance
+ * when connecting multiple protocols significantly.
+ */
+ //g_isConnecting = (wStatus >= ID_STATUS_CONNECTING && wStatus < ID_STATUS_OFFLINE);
+
+ szStatus = pcli->pfnGetStatusModeDescription(wStatus, 0);
+
+ /*
+ * set the global status icon and display the global (most online) status mode on the
+ * status mode button
+ */
+
+ if (szStatus) {
+ if(pcli->hwndContactList && IsWindow(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS)) && IsWindow(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS))) {
+ SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), WM_SETTEXT, 0, (LPARAM) szStatus);
+ if(!hIcon) {
+ SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), BM_SETIMLICON, (WPARAM) CLC::hClistImages, (LPARAM) iIcon);
+ if(CLUI::buttonItems == NULL)
+ SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS), BM_SETIMLICON, (WPARAM) CLC::hClistImages, (LPARAM) iIcon);
+ }
+ else {
+ SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), BM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
+ if(CLUI::buttonItems == NULL)
+ SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS), BM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
+ }
+ InvalidateRect(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), NULL, TRUE);
+ InvalidateRect(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS), NULL, TRUE);
+ SFL_Update(hIcon, iIcon, CLC::hClistImages, szStatus, TRUE);
+ } }
+ return;
+}
diff --git a/plugins/Clist_ng/SRC/config.cpp b/plugins/Clist_ng/SRC/config.cpp new file mode 100644 index 0000000000..4674f398c5 --- /dev/null +++ b/plugins/Clist_ng/SRC/config.cpp @@ -0,0 +1,626 @@ +
+/*
+ * 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: config.cpp 137 2010-10-16 21:03:23Z silvercircle $
+ *
+ * plugin configuration and low level API handling
+ *
+ */
+
+#include <commonheaders.h>
+
+TCluiData cfg::dat = {0};
+ClcData* cfg::clcdat = 0;
+TExtraCache* cfg::eCache = 0;
+int cfg::nextCacheEntry = 0, cfg::maxCacheEntry = 0;
+bool cfg::isAero = true;
+bool cfg::fBaseSkinValid = true;
+FI_INTERFACE* cfg::fif = 0;
+CRITICAL_SECTION cfg::cachecs = {0};
+
+bool cfg::shutDown = false;
+wchar_t cfg::szProfileDir[MAX_PATH] = L"\0";
+int cfg::maxStatus = ID_STATUS_OFFLINE;
+CLUIFrames *cfg::FrameMgr = nullptr;
+
+
+pfnAlphaBlend_t Api::pfnAlphaBlend = 0;
+PGF Api::pfnGradientFill = 0;
+pfnGetTickCount64_t Api::pfnGetTickCount64 = 0;
+
+TSysConfig Api::sysConfig = {0};
+TSysState Api::sysState = {0};
+
+pfnIsThemeActive_t Api::pfnIsThemeActive = 0;
+pfnOpenThemeData_t Api::pfnOpenThemeData = 0;
+pfnDrawThemeBackground_t Api::pfnDrawThemeBackground = 0;
+pfnCloseThemeData_t Api::pfnCloseThemeData = 0;
+pfnDrawThemeText_t Api::pfnDrawThemeText = 0;
+pfnDrawThemeTextEx_t Api::pfnDrawThemeTextEx = 0;
+pfnIsThemeBackgroundPartiallyTransparent_t Api::pfnIsThemeBackgroundPartiallyTransparent = 0;
+pfnDrawThemeParentBackground_t Api::pfnDrawThemeParentBackground = 0;
+pfnGetThemeBackgroundContentRect_t Api::pfnGetThemeBackgroundContentRect = 0;
+pfnEnableThemeDialogTexture_t Api::pfnEnableThemeDialogTexture = 0;
+
+pfnDwmExtendFrameIntoClientArea_t Api::pfnDwmExtendFrameIntoClientArea = 0;
+pfnDwmIsCompositionEnabled_t Api::pfnDwmIsCompositionEnabled = 0;
+
+pfnBufferedPaintInit_t Api::pfnBufferedPaintInit = 0;
+pfnBufferedPaintUninit_t Api::pfnBufferedPaintUninit = 0;
+
+pfnBeginBufferedPaint_t Api::pfnBeginBufferedPaint = 0;
+pfnEndBufferedPaint_t Api::pfnEndBufferedPaint = 0;
+pfnBufferedPaintSetAlpha_t Api::pfnBufferedPaintSetAlpha = 0;
+pfnBufferedPaintClear_t Api::pfnBufferedPaintClear = 0;
+pfnGetBufferedPaintBits_t Api::pfnGetBufferedPaintBits = 0;
+
+pfnDwmGetColorizationColor_t Api::pfnDwmGetColorizationColor = 0;
+pfnDwmBlurBehindWindow_t Api::pfnDwmBlurBehindWindow = 0;
+
+EXCEPTION_RECORD Api::exRecord = {0};
+CONTEXT Api::exCtx = {0};
+LRESULT Api::exLastResult = 0;
+char Api::exSzFile[MAX_PATH] = "\0";
+wchar_t Api::exReason[256] = L"\0";
+int Api::exLine = 0;
+bool Api::exAllowContinue = false;
+HMODULE Api::hUxTheme = 0, Api::hDwm = 0;
+
+void cfg::initCache()
+{
+ InitializeCriticalSection(&cachecs);
+}
+
+DWORD cfg::getDword(const MCONTACT hContact = 0, const char *szModule = 0, const char *szSetting = 0, DWORD uDefault = 0)
+{
+ return(db_get_dw(hContact, szModule, szSetting, uDefault));
+}
+
+/*
+ * read a setting from our default module (Tab_SRMSG)
+ */
+
+DWORD cfg::getDword(const char *szSetting = 0, DWORD uDefault = 0)
+{
+ return(db_get_dw(0, DEFAULT_MODULE, szSetting, uDefault));
+}
+
+/*
+ * read a setting from module only
+ */
+
+DWORD cfg::getDword(const char *szModule, const char *szSetting, DWORD uDefault)
+{
+ return(db_get_dw(0, szModule, szSetting, uDefault));
+}
+
+
+WORD cfg::getWord(const MCONTACT hContact = 0, const char *szModule = 0, const char *szSetting = 0, WORD uDefault = 0)
+{
+ return(db_get_w(hContact, szModule, szSetting, uDefault));
+}
+
+/*
+ * read a setting from our default module (Tab_SRMSG)
+ */
+
+WORD cfg::getWord(const char *szSetting = 0, WORD uDefault = 0)
+{
+ return(db_get_w(0, DEFAULT_MODULE, szSetting, uDefault));
+}
+
+/*
+ * read a setting from module only
+ */
+
+WORD cfg::getWord(const char *szModule, const char *szSetting, WORD uDefault)
+{
+ return(db_get_w(0, szModule, szSetting, uDefault));
+}
+
+/*
+ * same for bytes now
+ */
+int cfg::getByte(const MCONTACT hContact = 0, const char *szModule = 0, const char *szSetting = 0, int uDefault = 0)
+{
+ return(db_get_b(hContact, szModule, szSetting, uDefault));
+}
+
+int cfg::getByte(const char *szSetting = 0, int uDefault = 0)
+{
+ return(db_get_b(0, DEFAULT_MODULE, szSetting, uDefault));
+}
+
+int cfg::getByte(const char *szModule, const char *szSetting, int uDefault)
+{
+ return(db_get_b(0, szModule, szSetting, uDefault));
+}
+
+INT_PTR cfg::getTString(const MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ return(db_get_ws(hContact, szModule, szSetting, dbv));
+}
+
+INT_PTR cfg::getString(const MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ return(db_get_s(hContact, szModule, szSetting, dbv));
+}
+
+/*
+ * writer functions
+ */
+
+INT_PTR cfg::writeDword(const MCONTACT hContact = 0, const char *szModule = 0, const char *szSetting = 0, DWORD value = 0)
+{
+ return(db_set_dw(hContact, szModule, szSetting, value));
+}
+
+INT_PTR cfg::writeDword(const char *szModule = 0, const char *szSetting = 0, DWORD value = 0)
+{
+ return(db_set_dw(0, szModule, szSetting, value));
+}
+
+INT_PTR cfg::writeWord(const MCONTACT hContact = 0, const char *szModule = 0, const char *szSetting = 0, WORD value = 0)
+{
+ return(db_set_w(hContact, szModule, szSetting, value));
+}
+
+INT_PTR cfg::writeWord(const char *szModule = 0, const char *szSetting = 0, WORD value = 0)
+{
+ return(db_set_w(0, szModule, szSetting, value));
+}
+
+INT_PTR cfg::writeByte(const MCONTACT hContact = 0, const char *szModule = 0, const char *szSetting = 0, BYTE value = 0)
+{
+ return(db_set_b(hContact, szModule, szSetting, value));
+}
+
+INT_PTR cfg::writeByte(const char *szModule = 0, const char *szSetting = 0, BYTE value = 0)
+{
+ return(db_set_b(0, szModule, szSetting, value));
+}
+
+INT_PTR cfg::writeTString(const MCONTACT hContact, const char *szModule = 0, const char *szSetting = 0, const wchar_t *str = 0)
+{
+ return(db_set_ws(hContact, szModule, szSetting, str));
+}
+
+INT_PTR cfg::writeString(const MCONTACT hContact, const char *szModule = 0, const char *szSetting = 0, const char *str = 0)
+{
+ return(db_set_s(hContact, szModule, szSetting, str));
+}
+
+int cfg::getCache(const MCONTACT hContact, const char *szProto)
+{
+ int i, iFound = -1;
+
+ for(i = 0; i < nextCacheEntry; i++) {
+ if(eCache[i].hContact == hContact) {
+ iFound = i;
+ break;
+ }
+ }
+ if(iFound == -1) {
+ EnterCriticalSection(&cachecs);
+ if(nextCacheEntry == maxCacheEntry) {
+ maxCacheEntry += 100;
+ cfg::eCache = (TExtraCache *)realloc(cfg::eCache, maxCacheEntry * sizeof(TExtraCache));
+ }
+ memset(&cfg::eCache[nextCacheEntry], 0, sizeof(TExtraCache));
+ cfg::eCache[nextCacheEntry].hContact = hContact;
+ memset(cfg::eCache[nextCacheEntry].iExtraImage, 0xff, MAXEXTRACOLUMNS);
+ cfg::eCache[nextCacheEntry].iExtraValid = 0;
+ cfg::eCache[nextCacheEntry].valid = FALSE;
+ cfg::eCache[nextCacheEntry].bStatusMsgValid = 0;
+ cfg::eCache[nextCacheEntry].statusMsg = NULL;
+ cfg::eCache[nextCacheEntry].status_item = NULL;
+ cfg::eCache[nextCacheEntry].dwCFlags = 0;
+ cfg::eCache[nextCacheEntry].dwXMask = CalcXMask(hContact);
+ GetCachedStatusMsg(nextCacheEntry, const_cast<char *>(szProto));
+ cfg::eCache[nextCacheEntry].dwLastMsgTime = INTSORT_GetLastMsgTime(hContact);
+ iFound = nextCacheEntry++;
+ LeaveCriticalSection(&cachecs);
+ }
+ return iFound;
+}
+
+static struct {
+ UINT id;
+ TCHAR* name;
+} _tagFSINFO[] = {
+ FONTID_CONTACTS, LPGENT("Standard contacts"),
+ FONTID_INVIS, LPGENT("Online contacts to whom you have a different visibility"),
+ FONTID_OFFLINE, LPGENT("Offline contacts"),
+ FONTID_OFFINVIS, LPGENT("Offline contacts to whom you have a different visibility"),
+ FONTID_NOTONLIST, LPGENT("Contacts which are 'not on list'"),
+ FONTID_GROUPS, LPGENT("Groups"),
+ FONTID_GROUPCOUNTS, LPGENT("Group member counts"),
+ FONTID_DIVIDERS, LPGENT("Dividers"),
+ FONTID_STATUS, LPGENT("Status mode"),
+ FONTID_FRAMETITLE, LPGENT("Frame titles"),
+ FONTID_EVENTAREA, LPGENT("Event area"),
+ FONTID_TIMESTAMP, LPGENT("Contact list local time"),
+ 0, NULL
+};
+
+struct ColorOptionsList {
+ int order;
+ TCHAR* tszName;
+ char* szSetting;
+ COLORREF def;
+};
+
+/*
+ * note: bits 24-31 in default color indicates that color is a system color index
+ * (GetSysColor(default_color & 0x00ffffff)), not a rgb value.
+ */
+static ColorOptionsList _clrs[] = {
+ 0, L"List background", "BkColour", COLOR_WINDOW | 0xff000000,
+ 1, L"Group header background", "BkColourGroups", COLOR_3DFACE | 0xff000000,
+ 2, L"Selected text", "SelTextColour", COLOR_HIGHLIGHTTEXT | 0xff000000,
+ 3, L"Hottrack text", "HotTextColour", COLOR_HOTLIGHT | 0xff000000,
+ 4, L"Quicksearch text", "QuickSearchColour", CLCDEFAULT_QUICKSEARCHCOLOUR,
+ 5, L"Frame title background", "BkFrameTitles", COLOR_3DFACE | 0xff000000,
+ 6, L"Event area background", "BkEventAera", COLOR_WINDOW | 0xff000000
+};
+
+void cfg::FS_RegisterFonts()
+{
+ ColourIDT colourid;
+ FontIDT fid = {0};
+ char szTemp[50];
+ DBVARIANT dbv;
+ int j = 0;
+
+ fid.cbSize = sizeof(fid);
+ wcsncpy(fid.group, L"Contact List", _countof(fid.group));
+ strncpy(fid.dbSettingsGroup, "CLC", 5);
+ fid.flags = FIDF_DEFAULTVALID | FIDF_ALLOWEFFECTS | FIDF_APPENDNAME | FIDF_SAVEPOINTSIZE;
+ wcsncpy(fid.backgroundGroup, L"Contact List", _countof(fid.backgroundGroup));
+ while(_tagFSINFO[j].name != 0) {
+ if(FONTID_EVENTAREA == _tagFSINFO[j].id)
+ wcsncpy(fid.backgroundName, L"Event area background", _countof(fid.backgroundName));
+ else if(FONTID_FRAMETITLE == _tagFSINFO[j].id)
+ wcsncpy(fid.backgroundName, L"Frame title background", _countof(fid.backgroundName));
+ else if(FONTID_GROUPCOUNTS == _tagFSINFO[j].id || FONTID_GROUPS == _tagFSINFO[j].id)
+ _tcsncpy(fid.backgroundName, L"Group header background", _countof(fid.backgroundName));
+ else
+ wcsncpy(fid.backgroundName, L"List background", _countof(fid.backgroundName));
+
+ mir_snprintf(szTemp, sizeof(szTemp), "Font%d", _tagFSINFO[j].id);
+ strncpy(fid.prefix, szTemp, sizeof(fid.prefix));
+ fid.order = _tagFSINFO[j].id;
+ wcsncpy(fid.name, _tagFSINFO[j].name, 60);
+ _snprintf(szTemp, sizeof(szTemp), "Font%dCol", _tagFSINFO[j].id);
+ fid.deffontsettings.colour = (COLORREF)cfg::getDword("CLC", szTemp, GetSysColor(COLOR_WINDOWTEXT));
+
+ _snprintf(szTemp, sizeof(szTemp), "Font%dSize", _tagFSINFO[j].id);
+ fid.deffontsettings.size = (BYTE)cfg::getByte("CLC", szTemp, 8);
+
+ _snprintf(szTemp, sizeof(szTemp), "Font%dSty", _tagFSINFO[j].id);
+ fid.deffontsettings.style = cfg::getByte("CLC", szTemp, 0);
+ _snprintf(szTemp, sizeof(szTemp), "Font%dSet", _tagFSINFO[j].id);
+ fid.deffontsettings.charset = cfg::getByte("CLC", szTemp, DEFAULT_CHARSET);
+ _snprintf(szTemp, sizeof(szTemp), "Font%dName", _tagFSINFO[j].id);
+ if(cfg::getString(NULL, "CLC", szTemp, &dbv))
+ lstrcpyn(fid.deffontsettings.szFace, L"Tahoma", LF_FACESIZE);
+ else {
+ lstrcpyn(fid.deffontsettings.szFace, dbv.ptszVal, LF_FACESIZE);
+ mir_free(dbv.ptszVal);
+ }
+ FontRegisterT(&fid);
+ j++;
+ }
+
+ colourid.order = 0;
+ strncpy(colourid.dbSettingsGroup, "CLC", sizeof(colourid.dbSettingsGroup));
+ colourid.cbSize = sizeof(ColourIDT);
+ mir_sntprintf(colourid.group, _countof(colourid.group), L"%s", L"Contact List");
+ for (int i = 0; i < _countof(_clrs); i++) {
+ colourid.order = _clrs[i].order;
+ mir_snprintf(colourid.setting, sizeof(colourid.setting), "%s", _clrs[i].szSetting);
+ mir_sntprintf(colourid.name, _countof(colourid.name), L"%s", _clrs[i].tszName);
+ colourid.defcolour = (_clrs[i].def & 0xff000000 ? GetSysColor(_clrs[i].def & 0x00ffffff) : _clrs[i].def);
+ ColourRegisterT(&colourid);
+ }
+}
+
+TSkinDescription cfg::my_default_skin[] = {
+ IDR_SKIN_BASE, _T("base.cng"),
+ IDR_SKIN_BACK, _T("back.png"),
+ IDR_SKIN_BACKAERO, _T("AeroBack.png"),
+ IDR_SKIN_GLYPHS, _T("glyphs.png"),
+};
+
+/**
+ * first stage config init. Just read profile base path and try to
+ * extract the skin from the DLL
+ */
+int cfg::onInit()
+{
+ wchar_t* userdata = ::Utils_ReplaceVarsT(L"%miranda_profilesdir%");
+ wchar_t szBaseSkin[MAX_PATH];
+
+ LRESULT fi_version = CallService(MS_IMG_GETIFVERSION, 0, 0);
+ CallService(MS_IMG_GETINTERFACE, fi_version, (LPARAM)&fif);
+
+ if(0 == fif)
+ return(-S_FALSE);
+
+ mir_sntprintf(szProfileDir, MAX_PATH, L"%s", userdata);
+ mir_free(userdata);
+
+ Utils::ensureTralingBackslash(szProfileDir);
+ mir_sntprintf(szBaseSkin, MAX_PATH, L"%s%s", szProfileDir, L"skin\\clng\\base");
+ CreateDirectoryTreeW(szBaseSkin);
+ extractBaseSkin(false);
+
+ return(fBaseSkinValid ? S_OK : -S_FALSE);
+}
+/**
+ * extract the aero skin images from the DLL and store them in
+ * the private data folder.
+ * runs at every startup
+ *
+ * only overwrites the files when version number does not match or
+ * one of the files is missing.
+ */
+void cfg::extractBaseSkin(bool fForceOverwrite)
+{
+ wchar_t wszBasePath[MAX_PATH], wszTest[MAX_PATH];
+ bool fChecksPassed = true;
+ HANDLE hFile;
+
+ mir_sntprintf(wszBasePath, MAX_PATH, L"%s%s", szProfileDir, L"skin\\clng\\base\\");
+ mir_sntprintf(wszTest, MAX_PATH, L"%s%s", wszBasePath, L"base.cng");
+
+ /*
+ * version check, also fails when the file is simply missing
+ */
+ int uVersion = GetPrivateProfileInt(L"SkinInfo", L"Version", 0, wszTest);
+ if(uVersion < SKIN_REQUIRED_VERSION)
+ fChecksPassed = false;
+
+ /*
+ * version check passed, verify files are present
+ */
+ if(fChecksPassed) {
+ for(int i = 0; i < safe_sizeof(my_default_skin); i++) {
+ mir_sntprintf(wszTest, MAX_PATH, L"%s%s", wszBasePath, my_default_skin[i].tszName);
+ if((hFile = CreateFile(wszTest, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) {
+ fChecksPassed = false;
+ break;
+ }
+ CloseHandle(hFile);
+ }
+ }
+
+ // files are not present in skin dir, extract the default skin
+ if(!fChecksPassed) {
+ try {
+ for(int i = 0; i < safe_sizeof(my_default_skin); i++)
+ Utils::extractResource(g_hInst, my_default_skin[i].ulID, L"SKIN_GLYPH", wszBasePath, my_default_skin[i].tszName, true);
+
+ fBaseSkinValid = true;
+ } catch(CRTException& ex) {
+ ex.display();
+ fBaseSkinValid = false;
+ }
+ }
+}
+
+int Api::onInit()
+{
+ HMODULE hUserDll = 0;
+
+ hUserDll = GetModuleHandleA("user32.dll");
+
+ pfnGradientFill = (PGF) GetProcAddress(GetModuleHandleA("gdi32"), "GdiGradientFill");
+ if(0 == pfnGradientFill)
+ pfnGradientFill = (PGF) GetProcAddress(GetModuleHandleA("msimg32"), "GradientFill");
+
+ pfnAlphaBlend = (pfnAlphaBlend_t) GetProcAddress(GetModuleHandleA("gdi32"), "GdiAlphaBlend");
+ if(0 == pfnAlphaBlend)
+ pfnAlphaBlend = (pfnAlphaBlend_t)GetProcAddress(GetModuleHandleA("msimg32"), "AlphaBlend");
+
+ pfnGetTickCount64 = (pfnGetTickCount64_t)GetProcAddress(GetModuleHandleA("kernel32"), "GetTickCount64");
+
+ sysConfig.isVistaPlus = (IsWinVerVistaPlus() ? true : false);
+ sysConfig.isSevenPlus = (IsWinVer7Plus() ? true : false);
+
+ if(!sysConfig.isVistaPlus)
+ return(-S_FALSE);
+
+ if(sysConfig.isVistaPlus) {
+ if((hUxTheme = Utils::loadSystemLibrary(L"\\uxtheme.dll"), true) != 0) {
+ pfnIsThemeActive = (pfnIsThemeActive_t)GetProcAddress(hUxTheme, "IsThemeActive");
+ pfnOpenThemeData = (pfnOpenThemeData_t)GetProcAddress(hUxTheme, "OpenThemeData");
+ pfnDrawThemeBackground = (pfnDrawThemeBackground_t)GetProcAddress(hUxTheme, "DrawThemeBackground");
+ pfnCloseThemeData = (pfnCloseThemeData_t)GetProcAddress(hUxTheme, "CloseThemeData");
+ pfnDrawThemeText = (pfnDrawThemeText_t)GetProcAddress(hUxTheme, "DrawThemeText");
+ pfnIsThemeBackgroundPartiallyTransparent = (pfnIsThemeBackgroundPartiallyTransparent_t)GetProcAddress(hUxTheme, "IsThemeBackgroundPartiallyTransparent");
+ pfnDrawThemeParentBackground = (pfnDrawThemeParentBackground_t)GetProcAddress(hUxTheme, "DrawThemeParentBackground");
+ pfnGetThemeBackgroundContentRect = (pfnGetThemeBackgroundContentRect_t)GetProcAddress(hUxTheme, "GetThemeBackgroundContentRect");
+ pfnEnableThemeDialogTexture = (pfnEnableThemeDialogTexture_t)GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
+
+ if(pfnIsThemeActive != 0 && pfnOpenThemeData != 0 && pfnDrawThemeBackground != 0 && pfnCloseThemeData != 0
+ && pfnDrawThemeText != 0 && pfnIsThemeBackgroundPartiallyTransparent != 0 && pfnDrawThemeParentBackground != 0
+ && pfnGetThemeBackgroundContentRect != 0) {
+ }
+ pfnBeginBufferedPaint = (pfnBeginBufferedPaint_t)GetProcAddress(hUxTheme, "BeginBufferedPaint");
+ pfnEndBufferedPaint = (pfnEndBufferedPaint_t)GetProcAddress(hUxTheme, "EndBufferedPaint");
+ pfnBufferedPaintInit = (pfnBufferedPaintInit_t)GetProcAddress(hUxTheme, "BufferedPaintInit");
+ pfnBufferedPaintUninit = (pfnBufferedPaintUninit_t)GetProcAddress(hUxTheme, "BufferedPaintUnInit");
+ pfnBufferedPaintSetAlpha = (pfnBufferedPaintSetAlpha_t)GetProcAddress(hUxTheme, "BufferedPaintSetAlpha");
+ pfnBufferedPaintClear = (pfnBufferedPaintClear_t)GetProcAddress(hUxTheme, "BufferedPaintClear");
+ pfnGetBufferedPaintBits = (pfnGetBufferedPaintBits_t)GetProcAddress(hUxTheme, "GetBufferedPaintBits");
+ pfnDrawThemeTextEx = (pfnDrawThemeTextEx_t)GetProcAddress(hUxTheme, "DrawThemeTextEx");
+
+ if((hDwm = Utils::loadSystemLibrary(L"\\dwmapi.dll"), true) != 0) {
+ pfnDwmIsCompositionEnabled = (pfnDwmIsCompositionEnabled_t)GetProcAddress(hDwm, "DwmIsCompositionEnabled");
+ pfnDwmExtendFrameIntoClientArea = (pfnDwmExtendFrameIntoClientArea_t)GetProcAddress(hDwm, "DwmExtendFrameIntoClientArea");
+
+ pfnDwmBlurBehindWindow = (pfnDwmBlurBehindWindow_t)GetProcAddress(hDwm, "DwmEnableBlurBehindWindow");
+ pfnDwmGetColorizationColor = (pfnDwmGetColorizationColor_t)GetProcAddress(hDwm, "DwmGetColorizationColor");
+ }
+ }
+ }
+ pfnBufferedPaintInit();
+ updateState();
+ return(S_OK);
+}
+
+void Api::onUnload()
+{
+ if(hUxTheme)
+ FreeLibrary(hUxTheme);
+
+ pfnBufferedPaintUninit();
+}
+
+/**
+ * update system's state (theme status, aero status, DWM check...
+ *
+ * called when windows broadcasts things like WM_THEMECHANGED or
+ * WM_DWMCOMPOSITIONCHANGED
+ */
+void Api::updateState()
+{
+ BOOL result = FALSE;
+
+ ::ZeroMemory(&sysState, sizeof(TSysState));
+
+ sysState.isThemed = pfnIsThemeActive() ? true : false;
+
+ if(sysConfig.isVistaPlus) {
+ sysState.isDwmActive = (pfnDwmIsCompositionEnabled && (pfnDwmIsCompositionEnabled(&result) == S_OK) && result) ? true : false;
+ sysState.isAero = cfg::getByte(SKIN_DB_MODULE, "fUseAero", 1) && sysState.isDwmActive;
+ }
+ else
+ sysState.isAero = sysState.isDwmActive = false;
+}
+
+/**
+ * exception handling for SEH exceptions
+ */
+
+/**
+ * exception handling - copy error message to clip board
+ * @param hWnd: window handle of the edit control containing the error message
+ */
+void Api::Ex_CopyEditToClipboard(HWND hWnd)
+{
+ SendMessage(hWnd, EM_SETSEL, 0, 65535L);
+ SendMessage(hWnd, WM_COPY, 0 , 0);
+ SendMessage(hWnd, EM_SETSEL, 0, 0);
+}
+
+INT_PTR CALLBACK Api::Ex_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WORD wNotifyCode, wID;
+
+ switch(uMsg) {
+ case WM_INITDIALOG: {
+ char szBuffer[2048];
+#ifdef _WIN64
+ sprintf(szBuffer,
+ "Exception %16.16X at address %16.16X occured in %s at line %d.\r\n\r\nEAX=%16.16X EBX=%16.16X ECX=%16.16X\r\nEDX=%16.16X ESI=%16.16X EDI=%16.16X\r\nEBP=%16.16X ESP=%16.16X EIP=%16.16X",
+ exRecord.ExceptionCode, exRecord.ExceptionAddress, exSzFile, exLine,
+ exCtx.Rax, exCtx.Rbx, exCtx.Rcx, exCtx.Rdx,
+ exCtx.Rsi, exCtx.Rdi, exCtx.Rbp, exCtx.Rsp, exCtx.Rip);
+#else
+ sprintf(szBuffer,
+ "Exception %8.8X at address %8.8X occured in %s at line %d.\r\n\r\nEAX=%8.8X EBX=%8.8X ECX=%8.8X\r\nEDX=%8.8X ESI=%8.8X EDI=%8.8X\r\nEBP=%8.8X ESP=%8.8X EIP=%8.8X",
+ exRecord.ExceptionCode, exRecord.ExceptionAddress, exSzFile, exLine,
+ exCtx.Eax, exCtx.Ebx, exCtx.Ecx, exCtx.Edx,
+ exCtx.Esi, exCtx.Edi, exCtx.Ebp, exCtx.Esp, exCtx.Eip);
+#endif
+ SetDlgItemTextA(hwndDlg, IDC_EXCEPTION_DETAILS, szBuffer);
+ SetFocus(GetDlgItem(hwndDlg, IDC_EXCEPTION_DETAILS));
+ SendDlgItemMessage(hwndDlg, IDC_EXCEPTION_DETAILS, WM_SETFONT, (WPARAM)GetStockObject(OEM_FIXED_FONT), 0);
+ SetDlgItemTextW(hwndDlg, IDC_EX_REASON, exReason);
+ Utils::enableDlgControl(hwndDlg, IDOK, exAllowContinue ? TRUE : FALSE);
+ }
+ break;
+
+ case WM_COMMAND:
+ wNotifyCode = HIWORD(wParam);
+ wID = LOWORD(wParam);
+ if(wNotifyCode == BN_CLICKED) {
+ if(wID == IDOK || wID == IDCANCEL)
+ EndDialog(hwndDlg, wID);
+
+ if(wID == IDC_COPY_EXCEPTION)
+ Ex_CopyEditToClipboard(GetDlgItem(hwndDlg, IDC_EXCEPTION_DETAILS));
+ }
+
+ break;
+ }
+ return FALSE;
+}
+
+void Api::Ex_Handler()
+{
+ if(exLastResult == IDCANCEL)
+ ExitProcess(1);
+}
+
+int Api::Ex_ShowDialog(EXCEPTION_POINTERS *ep, const char *szFile, int line, wchar_t* szReason, bool fAllowContinue)
+{
+ char szDrive[MAX_PATH], szDir[MAX_PATH], szName[MAX_PATH], szExt[MAX_PATH];
+
+ _splitpath(szFile, szDrive, szDir, szName, szExt);
+ memcpy(&exRecord, ep->ExceptionRecord, sizeof(EXCEPTION_RECORD));
+ memcpy(&exCtx, ep->ContextRecord, sizeof(CONTEXT));
+
+ _snprintf(exSzFile, MAX_PATH, "%s%s", szName, szExt);
+ mir_sntprintf(exReason, 256, L"An application error has occured: %s", szReason);
+ exLine = line;
+ exLastResult = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EXCEPTION), 0, Ex_DlgProc, 0);
+ exAllowContinue = fAllowContinue;
+ if(IDCANCEL == exLastResult)
+ ExitProcess(1);
+ return 1;
+}
+
+CRTException::CRTException(const char *szMsg, const wchar_t *szParam) : std::runtime_error(std::string(szMsg))
+{
+ mir_sntprintf(m_szParam, MAX_PATH, szParam);
+}
+
+void CRTException::display() const
+{
+ wchar_t* tszMsg = mir_a2t(what());
+ wchar_t tszBoxMsg[500];
+
+ mir_sntprintf(tszBoxMsg, 500, _T("%s\n\n(%s)"), tszMsg, m_szParam);
+ ::MessageBox(0, tszBoxMsg, _T("ClistNG runtime error"), MB_OK | MB_ICONERROR);
+ mir_free(tszMsg);
+}
+
diff --git a/plugins/Clist_ng/SRC/contact.cpp b/plugins/Clist_ng/SRC/contact.cpp new file mode 100644 index 0000000000..919b49938c --- /dev/null +++ b/plugins/Clist_ng/SRC/contact.cpp @@ -0,0 +1,329 @@ +/*
+ * 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: contact.cpp 116 2010-09-11 10:40:18Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+
+struct {
+ int status,order;
+} statusModeOrder[]={
+ {ID_STATUS_OFFLINE,500},
+ {ID_STATUS_ONLINE,10},
+ {ID_STATUS_AWAY,200},
+ {ID_STATUS_DND,110},
+ {ID_STATUS_NA,450},
+ {ID_STATUS_OCCUPIED,100},
+ {ID_STATUS_FREECHAT,0},
+ {ID_STATUS_INVISIBLE,20},
+ {ID_STATUS_ONTHEPHONE,150},
+ {ID_STATUS_OUTTOLUNCH,425}
+};
+
+static int GetContactStatus(MCONTACT hContact)
+{
+ char *szProto;
+
+ szProto = GetContactProto(hContact);
+ if (szProto == NULL)
+ return ID_STATUS_OFFLINE;
+ return cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+}
+
+int __forceinline GetStatusModeOrdering(int statusMode)
+{
+ int i;
+ for (i = 0; i < sizeof(statusModeOrder) / sizeof(statusModeOrder[0]); i++) {
+ if (statusModeOrder[i].status == statusMode)
+ return statusModeOrder[i].order;
+ }
+ return 1000;
+}
+
+int mf_updatethread_running = TRUE;
+HANDLE hThreadMFUpdate = 0;
+
+/**
+ * calculate message frequency for a single contact
+ */
+static void MF_CalcFrequency(MCONTACT hContact, DWORD dwCutoffDays, int doSleep)
+{
+ DWORD curTime = time(NULL);
+ DWORD frequency, eventCount;
+ DBEVENTINFO dbei = {0};
+ MEVENT hEvent = db_event_last(hContact);
+
+ eventCount = 0;
+ dbei.cbSize = sizeof(dbei);
+ dbei.timestamp = 0;
+
+ while(hEvent) {
+ dbei.cbBlob = 0;
+ dbei.pBlob = NULL;
+ db_event_get(hEvent, &dbei);
+
+ if(dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { // record time of last event
+ eventCount++;
+ }
+ /*
+ * consider the most recent 100 messages and ignore messages that are older than the cutoff days.
+ * this will prevent contacts with a high message rate in the past to keep occupying the
+ * top positions forever.
+ */
+ if(eventCount >= 100 || dbei.timestamp < curTime - (dwCutoffDays * 86400))
+ break;
+ hEvent = db_event_prev(hContact, hEvent);
+ // check for main update thread still running (if not, application is shutting down, so terminate our work)
+ if(doSleep && mf_updatethread_running == FALSE)
+ return;
+ if(doSleep)
+ Sleep(100);
+ }
+
+ if(eventCount == 0) {
+ frequency = 0x7fffffff;
+ cfg::writeDword(hContact, "CList", "mf_firstEvent", curTime - (dwCutoffDays * 86400));
+ }
+ else {
+ frequency = (curTime - dbei.timestamp) / eventCount;
+ cfg::writeDword(hContact, "CList", "mf_firstEvent", dbei.timestamp);
+ }
+
+ cfg::writeDword(hContact, "CList", "mf_freq", frequency);
+ cfg::writeDword(hContact, "CList", "mf_count", eventCount);
+}
+
+extern wchar_t g_ptszEventName[];
+
+/**
+ * This background thread iterates over database contacts and calculates the message frequency
+ * which can be used to sort conctacts based on how frequent they are used as chat partners.
+ * it runs at low priority and scans one contact every 5 seconds. Once it's finished, it will
+ * wait another 1000 seconds and then repeat the process.
+*/
+void MF_UpdateThread(LPVOID)
+{
+ HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, g_ptszEventName);
+
+ WaitForSingleObject(hEvent, 20000);
+ ResetEvent(hEvent);
+
+ while (mf_updatethread_running) {
+ for (MCONTACT hContact = db_find_first(); hContact && mf_updatethread_running; hContact = db_find_next(hContact)) {
+ MF_CalcFrequency(hContact, 50, 1);
+ if (mf_updatethread_running)
+ WaitForSingleObject(hEvent, 5000);
+ ResetEvent(hEvent);
+ }
+ if (mf_updatethread_running)
+ WaitForSingleObject(hEvent, 1000000);
+ ResetEvent(hEvent);
+ }
+ CloseHandle(hEvent);
+}
+
+static BOOL mc_hgh_removed = FALSE;
+
+void CLC::LoadContactTree()
+{
+ MCONTACT hContact;
+ int i, status, hideOffline;
+ BYTE bMsgFrequency = cfg::getByte("CList", "fhistdata", 0);
+
+ CallService(MS_CLUI_LISTBEGINREBUILD, 0, 0);
+ for (i = 1; ; i++) {
+ if (pcli->pfnGetGroupName(i, NULL) == NULL)
+ break;
+ CallService(MS_CLUI_GROUPADDED, i, 0);
+ }
+
+ hideOffline = cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT);
+ hContact = db_find_first();
+ while (hContact != NULL) {
+ status = GetContactStatus(hContact);
+ if ((!hideOffline || status != ID_STATUS_OFFLINE) && !CLVM_GetContactHiddenStatus(hContact, NULL, NULL))
+ pcli->pfnChangeContactIcon(hContact, IconFromStatusMode(GetContactProto(hContact), status, hContact, NULL), 1);
+
+ // build initial data for message frequency
+ if(!bMsgFrequency)
+ MF_CalcFrequency(hContact, 100, 0);
+
+ hContact = db_find_next(hContact);
+ }
+ cfg::writeByte("CList", "fhistdata", 1);
+ mc_hgh_removed = TRUE;
+ //CallService(MS_CLUI_SORTLIST, 0, 0);
+ CallService(MS_CLUI_LISTENDREBUILD, 0, 0);
+}
+
+DWORD INTSORT_GetLastMsgTime(MCONTACT hContact)
+{
+ for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) {
+ DBEVENTINFO dbei = { sizeof(dbei) };
+ db_event_get(hDbEvent, &dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
+ return dbei.timestamp;
+ }
+ return 0;
+}
+
+int __forceinline GetProtoIndex(char * szName)
+{
+ if ( !szName )
+ return -1;
+ else {
+ PROTOACCOUNT* pa = Proto_GetAccount( szName );
+ return ( pa == NULL ) ? -1 : pa->iOrder;
+ }
+}
+
+static int __forceinline INTSORT_CompareContacts(const struct ClcContact* c1, const struct ClcContact* c2, UINT bywhat)
+{
+ wchar_t *namea, *nameb;
+ int statusa, statusb;
+ char *szProto1, *szProto2;
+ int rc;
+
+ if (c1 == 0 || c2 == 0)
+ return 0;
+
+ szProto1 = c1->proto;
+ szProto2 = c2->proto;
+ statusa = c1->wStatus;
+ statusb = c2->wStatus;
+ // make sure, sticky contacts are always at the beginning of the group/list
+
+ if ((c1->flags & CONTACTF_STICKY) != (c2->flags & CONTACTF_STICKY))
+ return 2 * (c2->flags & CONTACTF_STICKY) - 1;
+
+ if(bywhat == SORTBY_PRIOCONTACTS) {
+ if((cfg::clcdat->exStyle & CLS_EX_DIVIDERONOFF) && ((c1->flags & CONTACTF_ONLINE) != (c2->flags & CONTACTF_ONLINE)))
+ return 0;
+ if ((c1->flags & CONTACTF_PRIORITY) != (c2->flags & CONTACTF_PRIORITY))
+ return 2 * (c2->flags & CONTACTF_PRIORITY) - 1;
+ else
+ return 0;
+ }
+
+ if (bywhat == SORTBY_STATUS) {
+ int ordera, orderb;
+
+ ordera = GetStatusModeOrdering(statusa);
+ orderb = GetStatusModeOrdering(statusb);
+ if (ordera != orderb)
+ return ordera - orderb;
+ else
+ return 0;
+ }
+
+ // separate contacts treated as "offline"
+ if ( !cfg::dat.bDontSeparateOffline && ((statusa == ID_STATUS_OFFLINE) != (statusb == ID_STATUS_OFFLINE )))
+ return 2 * (statusa == ID_STATUS_OFFLINE) - 1;
+
+ switch( bywhat ) {
+ case SORTBY_NAME:
+ namea = (wchar_t *)c1->szText;
+ nameb = (wchar_t *)c2->szText;
+ return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, namea, -1, nameb, -1) - 2;
+
+ case SORTBY_LASTMSG:
+ if(c1->extraCacheEntry >= 0 && c1->extraCacheEntry < cfg::nextCacheEntry &&
+ c2->extraCacheEntry >= 0 && c2->extraCacheEntry < cfg::nextCacheEntry)
+ return(cfg::eCache[c2->extraCacheEntry].dwLastMsgTime - cfg::eCache[c1->extraCacheEntry].dwLastMsgTime);
+ else {
+ DWORD timestamp1 = INTSORT_GetLastMsgTime(c1->hContact);
+ DWORD timestamp2 = INTSORT_GetLastMsgTime(c2->hContact);
+ return timestamp2 - timestamp1;
+ }
+
+ case SORTBY_FREQUENCY:
+ if ( c1->extraCacheEntry >= 0 && c1->extraCacheEntry < cfg::nextCacheEntry &&
+ c2->extraCacheEntry >= 0 && c2->extraCacheEntry < cfg::nextCacheEntry )
+ return(cfg::eCache[c1->extraCacheEntry].msgFrequency - cfg::eCache[c2->extraCacheEntry].msgFrequency);
+ break;
+
+ case SORTBY_PROTO:
+ if(c1->bIsMeta)
+ szProto1 = c1->metaProto ? c1->metaProto : c1->proto;
+ if(c2->bIsMeta)
+ szProto2 = c2->metaProto ? c2->metaProto : c2->proto;
+
+ rc = GetProtoIndex(szProto1) - GetProtoIndex(szProto2);
+
+ if (rc != 0 && (szProto1 != NULL && szProto2 != NULL))
+ return rc;
+ }
+ return 0;
+}
+
+int CLC::CompareContacts(const ClcContact* c1, const ClcContact* c2)
+{
+ int i, result;
+
+ result = INTSORT_CompareContacts(c1, c2, SORTBY_PRIOCONTACTS);
+ if(result)
+ return result;
+
+ for(i = 0; i <= 2; i++) {
+ if(cfg::dat.sortOrder[i]) {
+ result = INTSORT_CompareContacts(c1, c2, cfg::dat.sortOrder[i]);
+ if(result != 0)
+ return result;
+ }
+ }
+ return 0;
+}
+
+#undef SAFESTRING
+
+static int resortTimerId = 0;
+static VOID CALLBACK SortContactsTimer(HWND hwnd, UINT message, UINT idEvent, DWORD dwTime)
+{
+ KillTimer(NULL, resortTimerId);
+ resortTimerId = 0;
+ //CallService(MS_CLUI_SORTLIST, 0, 0);
+}
+
+int CLC::SetHideOffline(WPARAM wParam, LPARAM lParam)
+{
+ switch ((int) wParam) {
+ case 0:
+ cfg::writeByte("CList", "HideOffline", 0);
+ break;
+ case 1:
+ cfg::writeByte("CList", "HideOffline", 1);
+ break;
+ case -1:
+ cfg::writeByte("CList", "HideOffline", (BYTE) ! cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT)); break;
+ }
+ CLUI::setButtonStates(pcli->hwndContactList);
+ CLC::LoadContactTree();
+ return 0;
+}
diff --git a/plugins/Clist_ng/SRC/extBackg.cpp b/plugins/Clist_ng/SRC/extBackg.cpp new file mode 100644 index 0000000000..cdfdc00ebd --- /dev/null +++ b/plugins/Clist_ng/SRC/extBackg.cpp @@ -0,0 +1,714 @@ +/*
+ * 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
+ *
+ * parts (C) by pixel, written many years ago for the original
+ * clist_nicer plugin.
+ * $Id: extBackg.cpp 138 2010-11-01 10:51:15Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include "../coolsb/coolscroll.h"
+
+extern HWND g_hwndViewModeFrame;
+extern struct CluiTopButton top_buttons[];
+
+void ReloadThemedOptions();
+
+
+TStatusItem DefaultStatusItems[ID_EXTBK_LAST_D + 1] = {
+ {"Offline", ID_EXTBKOFFLINE,
+ CLCDEFAULT_GRADIENT, CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Online", ID_EXTBKONLINE,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Away", ID_EXTBKAWAY,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"DND", ID_EXTBKDND,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"NA", ID_EXTBKNA,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Occupied", ID_EXTBKOCCUPIED,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Free for chat", ID_EXTBKFREECHAT,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Invisible", ID_EXTBKINVISIBLE,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"On the phone", ID_EXTBKONTHEPHONE,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Out to lunch", ID_EXTBKOUTTOLUNCH,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Idle", ID_EXTBKIDLE,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"{-}Expanded Group", ID_EXTBKEXPANDEDGROUP,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Collapsed Group", ID_EXTBKCOLLAPSEDDGROUP,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"Empty Group", ID_EXTBKEMPTYGROUPS,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"{-}First contact of a group", ID_EXTBKFIRSTITEM,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"Single item in group", ID_EXTBKSINGLEITEM,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"Last contact of a group", ID_EXTBKLASTITEM,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"{-}First contact of NON-group", ID_EXTBKFIRSTITEM_NG,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"Single item in NON-group", ID_EXTBKSINGLEITEM_NG,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"Last contact of NON-group", ID_EXTBKLASTITEM_NG,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"{-}Even rows", ID_EXTBKEVEN_CNTCTPOS,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"Odd rows", ID_EXTBKODD_CNTCTPOS,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"{-}Selection", ID_EXTBKSELECTION,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"Hottracked", ID_EXTBKHOTTRACK,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"{-}Frame titlebars", ID_EXTBKFRAMETITLE,
+ CLCDEFAULT_GRADIENT, CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 0
+ }, {"Event area", ID_EXTBKEVTAREA,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 0
+ }, {"Status Bar", ID_EXTBKSTATUSBAR,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1
+ }, {"{-}UI Button pressed", ID_EXTBKBUTTONSPRESSED,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"UI Button normal", ID_EXTBKBUTTONSNPRESSED,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"UI Button hover", ID_EXTBKBUTTONSMOUSEOVER,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"{-}Status floater", ID_EXTBKSTATUSFLOATER,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+ }, {"{-}Frame border no titlebar", ID_EXTBKOWNEDFRAMEBORDER,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, 1,
+ 1, 1, 1, CLCDEFAULT_IGNORE, S_ITEM_IMAGE_ONLY
+ }, {"Frame border with titlebar", ID_EXTBKOWNEDFRAMEBORDERTB,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, 1,
+ CLCDEFAULT_MRGN_TOP, 1, 1, CLCDEFAULT_IGNORE, S_ITEM_IMAGE_ONLY
+ }, {"{-}Avatarframe", ID_EXTBKAVATARFRAME,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1, S_ITEM_IMAGE_ONLY
+ }, {"Avatarframe offline", ID_EXTBKAVATARFRAMEOFFLINE,
+ CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT,
+ CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1, S_ITEM_IMAGE_ONLY
+ }
+};
+
+void SetButtonToSkinned()
+{
+ int bSkinned = cfg::dat.bSkinnedButtonMode = cfg::getByte("CLCExt", "bskinned", 0);
+
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBMENU, BM_SETSKINNED, 0, bSkinned);
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBGLOBALSTATUS, BM_SETSKINNED, 0, bSkinned);
+ if(bSkinned) {
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBMENU, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBGLOBALSTATUS, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBGLOBALSTATUS, BUTTONSETASFLATBTN + 10, 0, 0);
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBMENU, BUTTONSETASFLATBTN + 10, 0, 0);
+ }
+ else {
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBMENU, BUTTONSETASFLATBTN, 0, 1);
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBGLOBALSTATUS, BUTTONSETASFLATBTN, 0, 1);
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBGLOBALSTATUS, BUTTONSETASFLATBTN + 10, 0, 1);
+ SendDlgItemMessage(pcli->hwndContactList, IDC_TBMENU, BUTTONSETASFLATBTN + 10, 0, 1);
+ }
+ SendMessage(g_hwndViewModeFrame, WM_USER + 100, 0, 0);
+}
+
+TStatusItem *GetProtocolStatusItem(const char *szProto)
+{
+ int i;
+
+ if(szProto == NULL)
+ return NULL;
+
+ for(i = ID_EXTBK_LAST_D + 1; i <= Skin::ID_EXTBK_LAST; i++) {
+ if(!strcmp(Skin::statusItems[i].szName[0] == '{' ? &Skin::statusItems[i].szName[3] : Skin::statusItems[i].szName, szProto))
+ return &Skin::statusItems[i];
+ }
+ return NULL;
+}
+
+// Save Non-StatusItems Settings
+void SaveNonStatusItemsSettings(HWND hwndDlg)
+{
+ BOOL translated;
+
+ cfg::dat.bApplyIndentToBg = IsDlgButtonChecked(hwndDlg, IDC_APPLYINDENTBG) ? 1 : 0;
+ cfg::dat.bUsePerProto = IsDlgButtonChecked(hwndDlg, IDC_USEPERPROTO) ? 1 : 0;
+ cfg::dat.bOverridePerStatusColors = IsDlgButtonChecked(hwndDlg, IDC_OVERRIDEPERSTATUSCOLOR) ? 1 : 0;
+ cfg::dat.titleBarHeight = (BYTE)GetDlgItemInt(hwndDlg, IDC_LASTITEMPADDING, &translated, FALSE);
+ cfg::dat.group_padding = GetDlgItemInt(hwndDlg, IDC_GRPTOPPADDING, &translated, FALSE);
+
+ cfg::writeByte("CLCExt", "applyindentbg", (BYTE)cfg::dat.bApplyIndentToBg);
+ cfg::writeByte("CLCExt", "useperproto", (BYTE)cfg::dat.bUsePerProto);
+ cfg::writeByte("CLCExt", "override_status", (BYTE)cfg::dat.bOverridePerStatusColors);
+ cfg::writeByte("CLCExt", "bskinned", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_SETALLBUTTONSKINNED) ? 1 : 0));
+ cfg::writeByte("CLC", "IgnoreSelforGroups", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_IGNORESELFORGROUPS));
+
+ cfg::writeDword("CLCExt", "grp_padding", cfg::dat.group_padding);
+ cfg::writeByte("CLCExt", "frame_height", cfg::dat.titleBarHeight);
+
+ SetButtonToSkinned();
+}
+
+
+void extbk_import(char *file, HWND hwndDlg)
+{
+ int n, i;
+ char buffer[255];
+ char szKey[255], szSection[255];
+ DWORD data, version = 0;
+ int oldexIconScale = cfg::dat.exIconScale;
+
+ data = 0;
+ GetPrivateProfileStructA("Global", "Version", &version, 4, file);
+ if(version >= 2) {
+ for(n = 0; n <= FONTID_LAST; n++) {
+ mir_snprintf(szSection, 255, "Font%d", n);
+
+ mir_snprintf(szKey, 255, "Font%dName", n);
+ GetPrivateProfileStringA(szSection, "Name", "Arial", buffer, sizeof(buffer), file);
+ cfg::writeString(NULL, "CLC", szKey, buffer);
+
+ mir_snprintf(szKey, 255, "Font%dSize", n);
+ data = 0;
+ GetPrivateProfileStructA(szSection, "Size", &data, 1, file);
+ cfg::writeByte("CLC", szKey, (BYTE)data);
+
+ mir_snprintf(szKey, 255, "Font%dSty", n);
+ data = 0;
+ GetPrivateProfileStructA(szSection, "Style", &data, 1, file);
+ cfg::writeByte("CLC", szKey, (BYTE)data);
+
+ mir_snprintf(szKey, 255, "Font%dSet", n);
+ data = 0;
+ GetPrivateProfileStructA(szSection, "Set", &data, 1, file);
+ cfg::writeByte("CLC", szKey, (BYTE)data);
+
+ mir_snprintf(szKey, 255, "Font%dCol", n);
+ data = 0;
+ GetPrivateProfileStructA(szSection, "Color", &data, 4, file);
+ cfg::writeDword("CLC", szKey, data);
+
+ mir_snprintf(szKey, 255, "Font%dFlags", n);
+ data = 0;
+ GetPrivateProfileStructA(szSection, "Flags", &data, 4, file);
+ cfg::writeDword("CLC", szKey, (WORD)data);
+
+ mir_snprintf(szKey, 255, "Font%dAs", n);
+ data = 0;
+ GetPrivateProfileStructA(szSection, "SameAs", &data, 2, file);
+ cfg::writeDword("CLC", szKey, (WORD)data);
+ }
+ }
+ i = 0;
+
+ ReloadThemedOptions();
+ // refresh
+ if(hwndDlg && ServiceExists(MS_CLNSE_FILLBYCURRENTSEL))
+ CallService(MS_CLNSE_FILLBYCURRENTSEL, (WPARAM)hwndDlg, 0);
+ pcli->pfnClcOptionsChanged();
+ CLUI::configureGeometry(1);
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ CLUI::Redraw();
+ if(oldexIconScale != cfg::dat.exIconScale) {
+ ImageList_SetIconSize(CLUI::hExtraImages, cfg::dat.exIconScale, cfg::dat.exIconScale);
+ IcoLibReloadIcons();
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ }
+}
+
+static void ApplyCLUISkin()
+{
+ DBVARIANT dbv = {0};
+ wchar_t tszFinalName[MAX_PATH];
+ char szFinalName[MAX_PATH];
+ if(!cfg::getTString(NULL, "CLC", "AdvancedSkin", &dbv)) {
+ Utils::pathToAbsolute(dbv.ptszVal, tszFinalName);
+ WideCharToMultiByte(CP_ACP, 0, tszFinalName, MAX_PATH, szFinalName, MAX_PATH, 0, 0);
+ if(cfg::getByte("CLUI", "skin_changed", 0)) {
+ extbk_import(szFinalName, 0);
+ //SaveCompleteStructToDB();
+ cfg::writeByte("CLUI", "skin_changed", 0);
+ }
+ //IMG_LoadItems();
+ ShowWindow(pcli->hwndContactList, SW_SHOWNORMAL);
+ SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
+ SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0);
+ RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_ERASE);
+ db_free(&dbv);
+ }
+}
+
+/**
+ * scan a single skin directory and find the .TSK file. Fill the combobox and set the
+ * relative path name as item extra data.
+ *
+ * If available, read the Name property from the [Global] section and use it in the
+ * combo box. If such property is not found, the base filename (without .tsk extension)
+ * will be used as the name of the skin.
+ *
+ */
+static int ScanSkinDir(const wchar_t* tszFolder, HWND hwndCombobox)
+{
+ WIN32_FIND_DATA fd = {0};
+ bool fValid = false;
+ wchar_t tszMask[MAX_PATH];
+
+ mir_sntprintf(tszMask, MAX_PATH, L"%s*.*", tszFolder);
+
+ HANDLE h = FindFirstFile(tszMask, &fd);
+
+ while(h != INVALID_HANDLE_VALUE) {
+ if(lstrlenW(fd.cFileName) >= 5 && !wcsncmp(fd.cFileName + lstrlenW(fd.cFileName) - 4, L".cng", 4)) {
+ fValid = true;
+ break;
+ }
+ if(FindNextFileW(h, &fd) == 0)
+ break;
+ }
+ if(h != INVALID_HANDLE_VALUE)
+ FindClose(h);
+
+ if(fValid) {
+ TCHAR tszFinalName[MAX_PATH], tszRel[MAX_PATH];
+ LRESULT lr;
+ TCHAR szBuf[255];
+
+ mir_sntprintf(tszFinalName, MAX_PATH, _T("%s%s"), tszFolder, fd.cFileName);
+
+ GetPrivateProfileStringW(L"SkinInfo", L"Name", L"None", szBuf, 500, tszFinalName);
+ if(!wcscmp(szBuf, L"None")) {
+ fd.cFileName[lstrlenW(fd.cFileName) - 4] = 0;
+ mir_sntprintf(szBuf, 255, L"%s", fd.cFileName);
+ }
+
+ Utils::pathToRelative(tszFinalName, tszRel, cfg::szProfileDir);
+ if((lr = SendMessageW(hwndCombobox, CB_INSERTSTRING, -1, (LPARAM)szBuf)) != CB_ERR) {
+ wchar_t* idata = (wchar_t *)malloc((lstrlenW(tszRel) + 1) * sizeof(wchar_t));
+
+ wcscpy(idata, tszRel);
+ SendMessageW(hwndCombobox, CB_SETITEMDATA, lr, (LPARAM)idata);
+ }
+ }
+ return(0);
+}
+
+/**
+ * scan the skin root folder for subfolder(s). Each folder is supposed to contain a single
+ * skin. This function won't dive deeper into the folder structure, so the folder
+ * structure for any VALID skin should be:
+ * $SKINS_ROOT/skin_folder/skin_name.tsk
+ *
+ * By default, $SKINS_ROOT is set to %miranda_userdata% or custom folder
+ * selected by the folders plugin.
+ */
+static int RescanSkins(HWND hwndCombobox)
+{
+ WIN32_FIND_DATA fd = {0};
+ wchar_t tszSkinRoot[MAX_PATH], tszFindMask[MAX_PATH];
+ DBVARIANT dbv = {0};
+
+
+ mir_sntprintf(tszSkinRoot, MAX_PATH, L"%sskin\\clng\\", cfg::szProfileDir);
+
+ SetDlgItemTextW(GetParent(hwndCombobox), IDC_SKINROOTFOLDER, tszSkinRoot);
+ mir_sntprintf(tszFindMask, MAX_PATH, L"%s*.*", tszSkinRoot);
+
+ SendMessageW(hwndCombobox, CB_RESETCONTENT, 0, 0);
+ SendMessageW(hwndCombobox, CB_INSERTSTRING, -1, (LPARAM)TranslateW(L"<none>"));
+
+ HANDLE h = FindFirstFileW(tszFindMask, &fd);
+ while (h != INVALID_HANDLE_VALUE) {
+ if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && fd.cFileName[0] != '.') {
+ TCHAR tszSubDir[MAX_PATH];
+ mir_sntprintf(tszSubDir, MAX_PATH, _T("%s%s\\"), tszSkinRoot, fd.cFileName);
+ ScanSkinDir(tszSubDir, hwndCombobox);
+ }
+ if(FindNextFile(h, &fd) == 0)
+ break;
+ }
+ if(h != INVALID_HANDLE_VALUE)
+ FindClose(h);
+
+
+ SendMessage(hwndCombobox, CB_SETCURSEL, 0, 0);
+ if(0 == cfg::getTString(0, SKIN_DB_MODULE, "gCurrentSkin", &dbv)) {
+ LRESULT lr = SendMessage(hwndCombobox, CB_GETCOUNT, 0, 0);
+ for(int i = 1; i < lr; i++) {
+
+ wchar_t* idata = (wchar_t *)SendMessage(hwndCombobox, CB_GETITEMDATA, i, 0);
+ if(idata && idata != (wchar_t *)CB_ERR) {
+ if(!wcsicmp(dbv.ptszVal, idata)) {
+ SendMessage(hwndCombobox, CB_SETCURSEL, i, 0);
+ break;
+ }
+ }
+ }
+ db_free(&dbv);
+ }
+ return(0);
+}
+
+/**
+ * free the item extra data (used to store the skin filenames for
+ * each entry).
+ */
+static void TSAPI FreeComboData(HWND hwndCombobox)
+{
+ LRESULT lr = SendMessage(hwndCombobox, CB_GETCOUNT, 0, 0);
+
+ for(int i = 1; i < lr; i++) {
+ void *idata = (void *)SendMessage(hwndCombobox, CB_GETITEMDATA, i, 0);
+
+ if(idata && idata != (void *)CB_ERR)
+ free(idata);
+ }
+}
+
+
+INT_PTR CALLBACK cfg::DlgProcSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ RescanSkins(GetDlgItem(hwndDlg, IDC_SKINNAME));
+
+ CheckDlgButton(hwndDlg, IDC_SETALLBUTTONSKINNED, cfg::getByte("CLCExt", "bskinned", 0));
+
+ SendDlgItemMessage(hwndDlg, IDC_GRPPADDINGSPIN, UDM_SETRANGE, 0, MAKELONG(20, 0));
+ SendDlgItemMessage(hwndDlg, IDC_GRPPADDINGSPIN, UDM_SETPOS, 0, cfg::dat.group_padding);
+
+ SendDlgItemMessage(hwndDlg, IDC_LASTITEMPADDINGSPIN, UDM_SETRANGE, 0, MAKELONG(40, 0));
+ SendDlgItemMessage(hwndDlg, IDC_LASTITEMPADDINGSPIN, UDM_SETPOS, 0, cfg::dat.titleBarHeight);
+
+ CheckDlgButton(hwndDlg, IDC_APPLYINDENTBG, cfg::dat.bApplyIndentToBg);
+ CheckDlgButton(hwndDlg, IDC_USEPERPROTO, cfg::dat.bUsePerProto);
+ CheckDlgButton(hwndDlg, IDC_OVERRIDEPERSTATUSCOLOR, cfg::dat.bOverridePerStatusColors);
+ CheckDlgButton(hwndDlg, IDC_IGNORESELFORGROUPS, cfg::getByte("CLC", "IgnoreSelforGroups", 0) ? BST_CHECKED : BST_UNCHECKED);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_UNLOAD:
+ break;
+ case IDC_RELOADSKIN: {
+ DBVARIANT dbv = {0};
+ wchar_t wszSkinName[MAX_PATH];
+
+ if(0 == cfg::getTString(0, SKIN_DB_MODULE, "gCurrentSkin", &dbv)) {
+ Utils::pathToAbsolute(dbv.ptszVal, wszSkinName, cfg::szProfileDir);
+ if(PathFileExistsW(wszSkinName)) {
+ ShowWindow(pcli->hwndContactList, SW_HIDE);
+ Skin::Unload();
+ SkinLoader *s = new SkinLoader(wszSkinName);
+ if(s->isValid())
+ s->Load();
+
+ delete s;
+ Skin::Activate();
+ ShowWindow(pcli->hwndContactList, SW_SHOW);
+ }
+ db_free(&dbv);
+ }
+ break;
+ }
+
+ case IDC_HELP_GENERAL:
+ //CallService(MS_UTILS_OPENURL, 1, (LPARAM)"http://blog.miranda.or.at/tabsrmm/skin-selection-changes/");
+ break;
+
+ case IDC_RESCANSKIN:
+ FreeComboData(GetDlgItem(hwndDlg, IDC_SKINNAME));
+ RescanSkins(GetDlgItem(hwndDlg, IDC_SKINNAME));
+ break;
+
+ case IDC_SKINNAME: {
+ if(HIWORD(wParam) == CBN_SELCHANGE) {
+ LRESULT lr = SendDlgItemMessageW(hwndDlg, IDC_SKINNAME, CB_GETCURSEL, 0 ,0);
+ if(lr != CB_ERR && lr > 0) {
+ wchar_t *tszRelPath = (TCHAR *)SendDlgItemMessageW(hwndDlg, IDC_SKINNAME, CB_GETITEMDATA, lr, 0);
+ if(tszRelPath && tszRelPath != (wchar_t *)CB_ERR)
+ cfg::writeTString(0, SKIN_DB_MODULE, "gCurrentSkin", tszRelPath);
+ SendMessageW(hwndDlg, WM_COMMAND, IDC_RELOADSKIN, 0);
+ }
+ else if(lr == 0) // selected the <no skin> entry
+ db_unset(0, SKIN_DB_MODULE, "gCurrentSkin");
+ return(0);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ SaveNonStatusItemsSettings(hwndDlg);
+ pcli->pfnClcOptionsChanged();
+ PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0);
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+INT_PTR CALLBACK cfg::SkinOptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int iInit = TRUE;
+ static HWND hwndSkinEdit = 0;
+
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TCITEM tci;
+ RECT rcClient;
+ int oPage = cfg::getByte("CLUI", "s_opage", 0);
+ SKINDESCRIPTION sd;
+
+ TranslateDialogDefault(hwnd);
+ GetClientRect(hwnd, &rcClient);
+ iInit = TRUE;
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_SKIN), hwnd, cfg::DlgProcSkinOpts);
+ tci.pszText = TranslateT("Load and apply");
+ TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 0, &tci);
+ MoveWindow((HWND)tci.lParam,5,25,rcClient.right-9,rcClient.bottom-65,1);
+ ShowWindow((HWND)tci.lParam, oPage == 0 ? SW_SHOW : SW_HIDE);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
+
+ ZeroMemory(&sd, sizeof(sd));
+ sd.cbSize = sizeof(sd);
+ sd.StatusItems = Skin::statusItems;
+ sd.hWndParent = hwnd;
+ sd.hWndTab = GetDlgItem(hwnd, IDC_OPTIONSTAB);
+ sd.pfnSaveCompleteStruct = 0; //SaveCompleteStructToDB;
+ sd.lastItem = Skin::ID_EXTBK_LAST;
+ sd.firstItem = ID_EXTBKOFFLINE;
+ sd.pfnClcOptionsChanged = pcli->pfnClcOptionsChanged;
+ sd.hwndCLUI = pcli->hwndContactList;
+ hwndSkinEdit = SkinEdit_Invoke(0, (LPARAM)&sd);
+
+ if(hwndSkinEdit) {
+ ShowWindow(hwndSkinEdit, oPage == 1 ? SW_SHOW : SW_HIDE);
+ ShowWindow(sd.hwndImageEdit, oPage == 2 ? SW_SHOW : SW_HIDE);
+ TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB), oPage);
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture(hwndSkinEdit, ETDT_ENABLETAB);
+ }
+ Utils::enableDlgControl(hwnd, IDC_EXPORT, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0);
+ Utils::enableDlgControl(hwnd, IDC_SAVEASMOD, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0);
+ iInit = FALSE;
+ return FALSE;
+ }
+
+ case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0);
+ if(!iInit)
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_EXPORT:
+ {
+ char str[MAX_PATH] = "*.cng";
+ char szBaseFolder[MAX_PATH];
+ OPENFILENAMEA ofn = {0};
+
+ if(WarningDlg::show(WarningDlg::WARN_SKIN_OVERWRITE, MB_YESNOCANCEL | MB_ICONWARNING | WarningDlg::CWF_NOALLOWHIDE, 0) != IDYES)
+ break;
+
+ WideCharToMultiByte(CP_ACP, 0, Skin::settings.wszSkinBaseFolder, -1, szBaseFolder, MAX_PATH, 0, 0);
+
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwnd;
+ ofn.hInstance = NULL;
+ ofn.lpstrFilter = "*.cng";
+ ofn.lpstrFile = str;
+ ofn.Flags = OFN_HIDEREADONLY;
+ ofn.nMaxFile = sizeof(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "cng";
+
+ ofn.lpstrInitialDir = szBaseFolder;
+ if (!GetSaveFileNameA(&ofn))
+ break;
+ Skin::exportToFile(str);
+ Skin::exportSettingsToFile(str);
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ TCITEM tci;
+ int i,count;
+ tci.mask = TCIF_PARAM;
+ count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_OPTIONSTAB));
+ for (i=0;i<count;i++)
+ {
+ TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),i,&tci);
+ SendMessage((HWND)tci.lParam,WM_NOTIFY,0,lParam);
+ }
+ }
+ break;
+ }
+ break;
+ case IDC_OPTIONSTAB:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGING:
+ {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci);
+ ShowWindow((HWND)tci.lParam,SW_HIDE);
+ }
+ break;
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci);
+ ShowWindow((HWND)tci.lParam,SW_SHOW);
+ cfg::writeByte("CLUI", "s_opage", (BYTE)TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)));
+ Utils::enableDlgControl(hwnd, IDC_EXPORT, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0);
+ Utils::enableDlgControl(hwnd, IDC_SAVEASMOD, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0);
+ }
+ break;
+ }
+ break;
+
+ }
+ break;
+ case WM_DESTROY:
+ hwndSkinEdit = 0;
+ break;
+ }
+ return FALSE;
+}
+
+int CoolSB_SetupScrollBar(HWND hwnd)
+{
+ cfg::dat.bSkinnedScrollbar = TRUE;
+
+ if(cfg::getByte("CLC", "NoVScrollBar", 0)) {
+ UninitializeCoolSB(hwnd);
+ return 0;
+ }
+ if(cfg::dat.bSkinnedScrollbar) {
+ InitializeCoolSB(hwnd);
+ CoolSB_SetStyle(hwnd, SB_VERT, CSBS_HOTTRACKED);
+ }
+ else
+ UninitializeCoolSB(hwnd);
+ return 0;
+}
diff --git a/plugins/Clist_ng/SRC/gfx.cpp b/plugins/Clist_ng/SRC/gfx.cpp new file mode 100644 index 0000000000..3055ff8ef7 --- /dev/null +++ b/plugins/Clist_ng/SRC/gfx.cpp @@ -0,0 +1,441 @@ +/*
+* 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.cpp 134 2010-10-01 10:23:10Z silvercircle $
+*
+* clist_ng low level graphics code
+*/
+
+#include <commonheaders.h>
+#include <math.h>
+
+#ifdef _USE_D2D
+ ID2D1Factory* Gfx::pD2DFactory = 0;
+#endif
+COLORREF Gfx::txtColor = 0;
+//Gdiplus::GdiplusStartupInput Gfx::gdiPlusStartupInput;
+//ULONG_PTR Gfx::gdiPlusToken;
+
+/**
+ * Create a 32bit RGBA bitmap, compatible for rendering with alpha channel.
+ * Required by anything which would render on a transparent aero surface.
+ * the image is a "bottom up" bitmap, as it has a negative
+ * height. This is a requirement for some UxTheme APIs (e.g.
+ * DrawThemeTextEx).
+ *
+ * @param rc RECT &: the rectangle describing the target area.
+ * @param dc The device context for which the bitmap should be created.
+ *
+ * @return HBITMAP: handle to the bitmap created.
+ */
+
+BYTE* Gfx::m_p = nullptr;
+size_t Gfx::m_sAllocated = 0;
+
+HBITMAP Gfx::createRGBABitmap(const LONG cx, const LONG cy)
+{
+ BITMAPINFO dib = {0};
+
+ dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dib.bmiHeader.biWidth = cx;
+ dib.bmiHeader.biHeight = -cy; // use a "topdown" bitmap (0,0 = left, top corner)
+ dib.bmiHeader.biPlanes = 1;
+ dib.bmiHeader.biBitCount = 32;
+ dib.bmiHeader.biCompression = BI_RGB;
+ return(CreateDIBSection(0, &dib, DIB_RGB_COLORS, NULL, NULL, 0 ));
+}
+
+/**
+ * initialize Direct2D, create the factory
+ */
+void Gfx::D2D_Init()
+{
+#ifdef _USE_D2D
+ HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);
+#endif
+}
+
+void Gfx::D2D_Release()
+{
+#ifdef _USE_D2D
+ pD2DFactory->Release();
+#endif
+}
+
+void Gfx::deSaturate(HBITMAP hBitmap, bool fReduceContrast)
+{
+ BITMAP bmp;
+ DWORD dwLen;
+ BYTE bMin = 255, bMax = 0, bRamp = 0, bMaxAdjust, bMinAdjust;
+
+ int x, y;
+
+ GetObject(hBitmap, sizeof(bmp), &bmp);
+
+ if (bmp.bmBitsPixel != 32)
+ return;
+
+ dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8);
+ if (dwLen > m_sAllocated) {
+ m_p = (BYTE *)realloc(m_p, dwLen);
+ m_sAllocated = dwLen;
+ }
+ memset(m_p, 0, dwLen);
+
+ GetBitmapBits(hBitmap, dwLen, m_p);
+
+ if(fReduceContrast) {
+ for (y = 0; y < bmp.bmHeight; ++y) {
+ BYTE *px = m_p + bmp.bmWidth * 4 * y;
+
+ for (x = 0; x < bmp.bmWidth; ++x) {
+ BYTE avg = (px[0] + px[1] + px[2]) / 3;
+ bMin = min(avg, bMin);
+ bMax = max(avg, bMax);
+ px += 4;
+ }
+ }
+ bRamp = (bMax + bMin) / 2;
+ bMaxAdjust = (bMax - bRamp) / 2;
+ bMinAdjust = (bRamp - bMin) / 2;
+ }
+ for (y = 0; y < bmp.bmHeight; ++y) {
+ BYTE *px = m_p + bmp.bmWidth * 4 * y;
+
+ for (x = 0; x < bmp.bmWidth; ++x) {
+ BYTE avg = (px[0] + px[1] + px[2]) / 3;
+ //if(fReduceContrast)
+ // avg = (avg < bRamp ? avg + bMinAdjust : avg - bMaxAdjust);
+ px[0] = px[1] = px[2] = avg;
+ px += 4;
+ }
+ }
+ SetBitmapBits(hBitmap, bmp.bmWidth * bmp.bmHeight * 4, m_p);
+}
+
+void Gfx::setBitmapAlpha(HBITMAP hBitmap, BYTE bAlpha)
+{
+ BITMAP bmp;
+ DWORD dwLen;
+ int x, y;
+
+ GetObject(hBitmap, sizeof(bmp), &bmp);
+
+ if (bmp.bmBitsPixel != 32)
+ return;
+
+ dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8);
+ if (dwLen > m_sAllocated) {
+ m_p = (BYTE *)realloc(m_p, dwLen);
+ m_sAllocated = dwLen;
+ }
+ memset(m_p, 0, dwLen);
+
+ GetBitmapBits(hBitmap, dwLen, m_p);
+
+ for (y = 0; y < bmp.bmHeight; ++y) {
+ BYTE *px = m_p + bmp.bmWidth * 4 * y;
+
+ for (x = 0; x < bmp.bmWidth; ++x) {
+ px[3] = bAlpha;
+ px += 4;
+ }
+ }
+ SetBitmapBits(hBitmap, bmp.bmWidth * bmp.bmHeight * 4, m_p);
+}
+
+/**
+ * render text using UxTheme (vista+) DrawTextEx() API
+ * @param hdc device context
+ * @param hTheme a valid theme handle
+ * @param szText text to draw
+ * @param rc rectangle where to draw
+ * @param dtFlags flags (same as DrawText())
+ * @param iGlowSize glow size if we want glow, if 0 use solid color
+ * @param clr color to use
+ * @param fForceAero force using composited text with glow
+ * @return return value of DrawText()
+ */
+int Gfx::renderText(HDC hdc, HANDLE hTheme, const TCHAR *szText, RECT *rc, DWORD dtFlags, const int iGlowSize, int length, bool fForceAero)
+{
+ if(hTheme || fForceAero) {
+ DTTOPTS dto = {0};
+ dto.dwSize = sizeof(dto);
+ if(iGlowSize && (cfg::isAero || fForceAero)) {
+ dto.iGlowSize = iGlowSize;
+ dto.dwFlags = DTT_COMPOSITED|DTT_GLOWSIZE;
+ }
+ else {
+ dto.dwFlags = DTT_TEXTCOLOR|DTT_COMPOSITED;//|DTT_SHADOWTYPE|DTT_SHADOWOFFSET|DTT_SHADOWCOLOR|DTT_BORDERSIZE|DTT_BORDERCOLOR;
+ dto.crText = txtColor;
+ }
+ dto.iBorderSize = 10;
+ return(Api::pfnDrawThemeTextEx(hTheme, hdc, BP_PUSHBUTTON, PBS_NORMAL, szText, length, dtFlags, rc, &dto));
+ }
+ else {
+ ::SetTextColor(hdc, txtColor);
+ return(::DrawText(hdc, szText, -1, rc, dtFlags));
+ }
+}
+
+void Gfx::preMultiply(HBITMAP hBitmap, int mode)
+{
+ DWORD dwLen;
+ int width, height, x, y;
+ BITMAP bmp;
+ BYTE alpha;
+
+ GetObject(hBitmap, sizeof(bmp), &bmp);
+ width = bmp.bmWidth;
+ height = bmp.bmHeight;
+ dwLen = width * height * 4;
+ if (dwLen > m_sAllocated) {
+ m_p = (BYTE *)realloc(m_p, dwLen);
+ m_sAllocated = dwLen;
+ }
+ if(m_p) {
+ GetBitmapBits(hBitmap, dwLen, m_p);
+ for (y = 0; y < height; ++y) {
+ BYTE *px = m_p + width * 4 * y;
+
+ for (x = 0; x < width; ++x) {
+ if(mode) {
+ alpha = px[3];
+ px[0] = px[0] * alpha/255;
+ px[1] = px[1] * alpha/255;
+ px[2] = px[2] * alpha/255;
+ }
+ else
+ px[3] = 255;
+ px += 4;
+ }
+ }
+ dwLen = SetBitmapBits(hBitmap, dwLen, m_p);
+ }
+}
+
+/**
+ * render a image item on the given target surface.
+ *
+ * @param hdc target HDC
+ * @param item image item
+ * @param rc target rectangle (client coordinates)
+ */
+void __fastcall Gfx::renderImageItem(HDC hdc, TImageItem *item, RECT *rc)
+{
+ BYTE l = item->bLeft, r = item->bRight, t = item->bTop, b = item->bBottom;
+ LONG width = rc->right - rc->left;
+ LONG height = rc->bottom - rc->top;
+ BOOL isGlyph = (item->dwFlags & IMAGE_GLYPH) && Skin::glyphItem;
+ HDC hdcSrc = isGlyph ? Skin::glyphItem->hdc : item->hdc;
+ LONG srcOrigX = isGlyph ? item->glyphMetrics[0] : 0;
+ LONG srcOrigY = isGlyph ? item->glyphMetrics[1] : 0;
+
+ if(item->dwFlags & IMAGE_FLAG_DIVIDED) {
+ // top 3 items
+
+ Api::pfnAlphaBlend(hdc, rc->left, rc->top, l, t, hdcSrc, srcOrigX, srcOrigY, l, t, item->bf);
+ Api::pfnAlphaBlend(hdc, rc->left + l, rc->top, width - l - r, t, hdcSrc, srcOrigX + l, srcOrigY, item->inner_width, t, item->bf);
+ Api::pfnAlphaBlend(hdc, rc->right - r, rc->top, r, t, hdcSrc, srcOrigX + (item->width - r), srcOrigY, r, t, item->bf);
+ // middle 3 items
+
+ Api::pfnAlphaBlend(hdc, rc->left, rc->top + t, l, height - t - b, hdcSrc, srcOrigX, srcOrigY + t, l, item->inner_height, item->bf);
+
+ if(item->dwFlags & IMAGE_FILLSOLID && item->fillBrush) {
+ RECT rcFill;
+ rcFill.left = rc->left + l; rcFill.top = rc->top +t;
+ rcFill.right = rc->right - r; rcFill.bottom = rc->bottom - b;
+ FillRect(hdc, &rcFill, item->fillBrush);
+ }
+ else
+ Api::pfnAlphaBlend(hdc, rc->left + l, rc->top + t, width - l - r, height - t - b, hdcSrc, srcOrigX + l, srcOrigY + t, item->inner_width, item->inner_height, item->bf);
+
+ Api::pfnAlphaBlend(hdc, rc->right - r, rc->top + t, r, height - t - b, hdcSrc, srcOrigX + (item->width - r), srcOrigY + t, r, item->inner_height, item->bf);
+
+ // bottom 3 items
+
+ Api::pfnAlphaBlend(hdc, rc->left, rc->bottom - b, l, b, hdcSrc, srcOrigX, srcOrigY + (item->height - b), l, b, item->bf);
+ Api::pfnAlphaBlend(hdc, rc->left + l, rc->bottom - b, width - l - r, b, hdcSrc, srcOrigX + l, srcOrigY + (item->height - b), item->inner_width, b, item->bf);
+ Api::pfnAlphaBlend(hdc, rc->right - r, rc->bottom - b, r, b, hdcSrc, srcOrigX + (item->width - r), srcOrigY + (item->height - b), r, b, item->bf);
+ }
+ else {
+ switch(item->bStretch) {
+ case IMAGE_STRETCH_H:
+ // tile image vertically, stretch to width
+ {
+ LONG top = rc->top;
+
+ do {
+ if(top + item->height <= rc->bottom) {
+ Api::pfnAlphaBlend(hdc, rc->left, top, width, item->height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf);
+ top += item->height;
+ }
+ else {
+ Api::pfnAlphaBlend(hdc, rc->left, top, width, rc->bottom - top, hdcSrc, srcOrigX, srcOrigY, item->width, rc->bottom - top, item->bf);
+ break;
+ }
+ } while (TRUE);
+ break;
+ }
+ case IMAGE_STRETCH_V:
+ // tile horizontally, stretch to height
+ {
+ LONG left = rc->left;
+
+ do {
+ if(left + item->width <= rc->right) {
+ Api::pfnAlphaBlend(hdc, left, rc->top, item->width, height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf);
+ left += item->width;
+ }
+ else {
+ Api::pfnAlphaBlend(hdc, left, rc->top, rc->right - left, height, hdcSrc, srcOrigX, srcOrigY, rc->right - left, item->height, item->bf);
+ break;
+ }
+ } while (TRUE);
+ break;
+ }
+ case IMAGE_STRETCH_B:
+ // stretch the image in both directions...
+ Api::pfnAlphaBlend(hdc, rc->left, rc->top, width, height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * colorize an image item (both standalone items with their own bitmap and glyph items).
+ *
+ * @param item image item to colorize
+ * @param clr color to use (note: BGRA format required, although, alpha is ignored)
+ * @param hue hue adjustment (in degrees, -180 .. +180
+ * @param saturation scalar value (0.0 ... 1.0)
+ * @param value scalar value (0.0 ... 1.0)
+ *
+ * note: this isn't performance critical as it only runs at skin loading time or when
+ * the user changes colorization options, never during rendering.
+ *
+ * if clr == 0, hsv transformation will be applied, otherwise it's rgb colorization.
+ */
+void Gfx::colorizeGlyph(TImageItem *item, const COLORREF clr, float hue, float saturation, float value)
+{
+ LONG stride = 0, line, pixel;
+ HBITMAP hBitmap = 0;
+ LONG x, y, x1, y1;
+ BITMAP bmp = {0};
+ DWORD dwLen;
+ BYTE* pOrig, *pLine, alpha;
+ float v_s_u = 0, v_s_w = 0, r = 0, g = 0, b = 0;
+
+ if(0 == clr) { // do hsv transformation
+ v_s_u = value * saturation * cos(hue * M_PI/180);
+ v_s_w = value * saturation * sin(hue * M_PI/180);
+ }
+ else { // rgb colorization
+ BYTE rValue = GetRValue(clr);
+ BYTE gValue = GetGValue(clr);
+ BYTE bValue = GetBValue(clr);
+
+ r = (float)rValue / 2.55;
+ g = (float)gValue / 2.55;
+ b = (float)bValue / 2.55;
+ }
+ if(item) {
+ /*
+ * colorize a rectangular glyph
+ */
+ if(item->dwFlags & IMAGE_GLYPH) {
+ hBitmap = Skin::glyphItem->hbm;
+ x = item->glyphMetrics[0];
+ y = item->glyphMetrics[1];
+ x1 = x + item->glyphMetrics[2] - 1;
+ y1 = y + item->glyphMetrics[3] - 1;
+
+ GetObject(hBitmap, sizeof(bmp), &bmp);
+
+ if (bmp.bmBitsPixel != 32)
+ return;
+
+ dwLen = bmp.bmWidth * bmp.bmHeight * 4;
+ if (dwLen > m_sAllocated) {
+ m_p = (BYTE *)realloc(m_p, dwLen);
+ dwLen = (DWORD)m_sAllocated;
+ }
+ memset(m_p, 0, dwLen);
+ pOrig = m_p;
+ GetBitmapBits(hBitmap, dwLen, m_p);
+
+ stride = bmp.bmWidthBytes;
+
+ m_p += ((y * stride) + (4 * x));
+
+ for(line = y; line <= y1; line++) {
+ pLine = m_p;
+ for(pixel = x; pixel <= x1; pixel++) {
+ alpha = m_p[3];
+ if(alpha > 0) {
+ if(0 == clr)
+ hsvTransformPixel(m_p, value, v_s_u, v_s_w, alpha);
+ else
+ rgbTransformPixel(m_p, r, g, b, alpha);
+ }
+ m_p += 4;
+ }
+ m_p = pLine + stride;
+ }
+ SetBitmapBits(hBitmap, dwLen, pOrig);
+ }
+ else if (item->hbm) {
+ GetObject(item->hbm, sizeof(bmp), &bmp);
+ if (bmp.bmBitsPixel != 32)
+ return;
+
+ dwLen = bmp.bmWidth * bmp.bmHeight * 4;
+ if (dwLen > m_sAllocated) {
+ m_p = (BYTE *)realloc(m_p, dwLen);
+ m_sAllocated = dwLen;
+ }
+ memset(m_p, 0, dwLen);
+ pOrig = m_p;
+ GetBitmapBits(item->hbm, dwLen, m_p);
+
+ for(pixel = 0; pixel < (bmp.bmWidth * bmp.bmHeight); pixel++) {
+ alpha = m_p[3];
+ if(alpha > 0) {
+ if(0 == clr)
+ hsvTransformPixel(m_p, value, v_s_u, v_s_w, alpha);
+ else
+ rgbTransformPixel(m_p, r, g, b, alpha);
+ }
+ m_p += 4;
+ }
+ SetBitmapBits(item->hbm, dwLen, pOrig);
+ }
+ }
+}
diff --git a/plugins/Clist_ng/SRC/gfx.sublime-workspace b/plugins/Clist_ng/SRC/gfx.sublime-workspace new file mode 100644 index 0000000000..0e99932ba2 --- /dev/null +++ b/plugins/Clist_ng/SRC/gfx.sublime-workspace @@ -0,0 +1,181 @@ +{ + "auto_complete": + { + "selected_items": + [ + [ + "con", + "context" + ] + ] + }, + "buffers": + [ + ], + "build_system": "", + "command_palette": + { + "height": 375.0, + "selected_items": + [ + [ + "pack", + "Package Control: Install Package" + ], + [ + "pa", + "Package Control: Remove Package" + ], + [ + "packa", + "Preferences: Browse Packages" + ] + ], + "width": 418.0 + }, + "console": + { + "height": 0.0, + "history": + [ + ] + }, + "distraction_free": + { + "menu_visible": true, + "show_minimap": false, + "show_open_files": false, + "show_tabs": false, + "side_bar_visible": false, + "status_bar_visible": false + }, + "file_history": + [ + "/D/idea12/bin/idea64.exe.vmoptions", + "/C/Users/alex/Dropbox/smf/Sources/EosSmarty.php", + "/C/Users/alex/Dropbox/smf/Sources/Calendar.php", + "/C/Users/alex/Dropbox/smf/Sources/DbPackages-mysql.php", + "/C/Users/alex/Dropbox/smf/Sources/Load.php", + "/C/Users/alex/Dropbox/smf/Sources/BoardIndex.php", + "/C/Users/alex/Dropbox/smf/Sources/Display.php", + "/C/Users/alex/Dropbox/smf/Sources/Class-Graphics.php", + "/D/NET_DATA/Dropbox/sublime/Data/Packages/BufferScroll/BufferScroll.py", + "/C/Users/Alex/Dropbox/sublime/Data/Packages/User/BufferScroll.sublime-settings", + "/C/Users/Alex/Dropbox/sublime/Data/Packages/Default/Preferences.sublime-settings", + "/C/Users/Alex/Dropbox/sublime/Data/Packages/BufferScroll/BufferScroll.sublime-settings", + "/C/Users/Alex/Dropbox/sublime/Data/Packages/User/Package Control.sublime-settings", + "/D/net_data/dropbox/sublime/Data/Packages/User/Package Control.sublime-settings" + ], + "find": + { + "height": 34.0 + }, + "find_in_files": + { + "height": 0.0, + "where_history": + [ + ] + }, + "find_state": + { + "case_sensitive": false, + "find_history": + [ + "fold" + ], + "highlight": true, + "in_selection": false, + "preserve_case": false, + "regex": false, + "replace_history": + [ + ], + "reverse": false, + "show_context": true, + "use_buffer2": true, + "whole_word": false, + "wrap": true + }, + "groups": + [ + { + "sheets": + [ + ] + } + ], + "incremental_find": + { + "height": 24.0 + }, + "input": + { + "height": 34.0 + }, + "layout": + { + "cells": + [ + [ + 0, + 0, + 1, + 1 + ] + ], + "cols": + [ + 0.0, + 1.0 + ], + "rows": + [ + 0.0, + 1.0 + ] + }, + "menu_visible": true, + "project": "gfx.sublime-project", + "replace": + { + "height": 44.0 + }, + "save_all_on_build": true, + "select_file": + { + "height": 0.0, + "selected_items": + [ + ], + "width": 0.0 + }, + "select_project": + { + "height": 0.0, + "selected_items": + [ + ], + "width": 0.0 + }, + "select_symbol": + { + "height": 0.0, + "selected_items": + [ + ], + "width": 0.0 + }, + "settings": + { + }, + "show_minimap": true, + "show_open_files": true, + "show_tabs": true, + "side_bar_visible": true, + "side_bar_width": 284.0, + "status_bar_visible": true, + "template_settings": + { + } +} diff --git a/plugins/Clist_ng/SRC/init.cpp b/plugins/Clist_ng/SRC/init.cpp new file mode 100644 index 0000000000..eacf362b0d --- /dev/null +++ b/plugins/Clist_ng/SRC/init.cpp @@ -0,0 +1,386 @@ +/*
+ * 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: init.cpp 138 2010-11-01 10:51:15Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+
+HINSTANCE g_hInst = 0;
+CLIST_INTERFACE *pcli, coreCli;
+int hLangpack;
+
+#define DEFAULT_TB_VISIBILITY (1 | 2 | 4 | 8 | 16 | 32 | 64 | 8192)
+
+wchar_t* szNoevents = L"No events...";
+extern HICON overlayicons[10];
+
+extern int Docking_ProcessWindowMessage(WPARAM wParam, LPARAM lParam);
+extern void RegisterCLUIFrameClasses();
+
+HMENU BuildGroupPopupMenu(struct ClcGroup* group);
+void ReloadThemedOptions();
+void TrayIconUpdateBase(const char *szChangedProto);
+
+void GetDefaultFontSetting(int i, LOGFONT *lf, COLORREF *colour);
+int GetWindowVisibleState(HWND hWnd, int iStepX, int iStepY);
+int ShowHide(WPARAM wParam, LPARAM lParam);
+
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 9
+#define __RELEASE_NUM 2
+#define __BUILD_NUM 4
+
+#include <stdver.h>
+
+#define __PLUGIN_NAME "Clist NG"
+#define __FILENAME "Clist_NG.dll"
+#define __DESCRIPTION "Displays contacts, event notifications, protocol status."
+#define __AUTHOR "Pixel, egoDust, cyreve, Nightwish"
+#define __AUTHOREMAIL ""
+#define __AUTHORWEB "http://miranda-ng.org/p/Clist_nicer/"
+#define __COPYRIGHT "Copyright 2000-2015 Miranda-IM project"
+
+PLUGININFOEX pluginInfo =
+{
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {8F79B4EE-EB48-4A03-873E-27BE6B7E9A25}
+ { 0xe3a15605, 0x62be, 0x4a1b, { 0xa1, 0x10, 0xf8, 0x89, 0xfa, 0x4b, 0x2f, 0x0 } }
+};
+
+int _DebugTraceW(const wchar_t *fmt, ...)
+{
+ wchar_t debug[2048];
+ int ibsize = 2047;
+ SYSTEMTIME st;
+ va_list va;
+ char tszTime[50];
+ va_start(va, fmt);
+
+ GetLocalTime(&st);
+
+ mir_snprintf(tszTime, 50, "%02d.%02d.%04d - %02d:%02d:%02d.%04d: ", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+
+
+ _vsnwprintf(debug, ibsize - 10, fmt, va);
+//#ifdef _DEBUG
+ OutputDebugStringW(debug);
+//#else
+ {
+ char szLogFileName[MAX_PATH], szDataPath[MAX_PATH];
+ FILE *f;
+
+ CallService(MS_DB_GETPROFILEPATH, MAX_PATH, (LPARAM)szDataPath);
+ mir_snprintf(szLogFileName, MAX_PATH, "%s\\%s", szDataPath, "clg_debug.log");
+ f = fopen(szLogFileName, "a+");
+ if(f) {
+ char *szDebug = Utf8EncodeW(debug);
+ fputs(tszTime, f);
+ fputs(szDebug, f);
+ fputs("\n", f);
+ fclose(f);
+ if(szDebug)
+ mir_free(szDebug);
+ }
+ }
+//#endif
+ return 0;
+}
+
+int _DebugTraceA(const char *fmt, ...)
+{
+ char debug[2048];
+ int ibsize = 2047;
+ va_list va;
+ va_start(va, fmt);
+
+ lstrcpyA(debug, "CLIST_NG: ");
+ _vsnprintf(&debug[9], ibsize - 10, fmt, va);
+#ifdef _DEBUG
+ OutputDebugStringA(debug);
+#else
+ {
+ char szLogFileName[MAX_PATH], szDataPath[MAX_PATH];
+ FILE *f;
+
+ CallService(MS_DB_GETPROFILEPATH, MAX_PATH, (LPARAM)szDataPath);
+ mir_snprintf(szLogFileName, MAX_PATH, "%s\\%s", szDataPath, "clg_debugA.log");
+ f = fopen(szLogFileName, "a+");
+ if(f) {
+ fputs(debug, f);
+ fputs("\n", f);
+ fclose(f);
+ }
+ }
+#endif
+ return 0;
+}
+
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved)
+{
+ g_hInst = hInstDLL;
+ DisableThreadLibraryCalls(g_hInst);
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_CLIST, MIID_LAST };
+
+int LoadContactListModule(void);
+int LoadCLCModule(void);
+
+static int systemModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ GetSystemTime(&cfg::dat.st);
+ SystemTimeToFileTime(&cfg::dat.st, &cfg::dat.ft);
+
+ cfg::dat.bMetaEnabled = db_mc_isEnabled();
+
+ cfg::dat.bAvatarServiceAvail = ServiceExists(MS_AV_GETAVATARBITMAP) ? TRUE : FALSE;
+ if (cfg::dat.bAvatarServiceAvail)
+ HookEvent(ME_AV_AVATARCHANGED, AvatarChanged);
+ cfg::dat.tabSRMM_Avail = ServiceExists("SRMsg_MOD/GetWindowFlags") ? TRUE : FALSE;
+
+ ZeroMemory((void *)overlayicons, sizeof(HICON) * 10);
+
+ CLN_LoadAllIcons(1);
+ return 0;
+}
+
+int CLC::fnIconFromStatusMode(const char* szProto, int status, MCONTACT hContact)
+{
+ return IconFromStatusMode(szProto, status, hContact, NULL);
+}
+
+extern "C" int __declspec(dllexport) CListInitialise()
+{
+ int rc = 0;
+ DBVARIANT dbv = {0};
+ int i;
+#ifdef _DEBUG
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+#endif
+
+ mir_getLP( &pluginInfo );
+ mir_getCLI();
+ coreCli = *pcli;
+
+ if(!SUCCEEDED(Api::onInit())) {
+ MessageBoxW(0, L"Unsupported operating system", L"Clist NG fatal", MB_OK);
+ return(1);
+ }
+ if(!SUCCEEDED(cfg::onInit())) {
+ MessageBoxW(0, L"cfg::OnInit() failed", L"Clist NG fatal", MB_OK);
+ return(1);
+ }
+ Gfx::D2D_Init();
+ LoadCLCButtonModule();
+ RegisterCLUIFrameClasses();
+ ZeroMemory((void*) &cfg::dat, sizeof(cfg::dat));
+
+ int iCount = CallService(MS_DB_CONTACT_GETCOUNT, 0, 0);
+
+ iCount += 20;
+ if(iCount < 300)
+ iCount = 300;
+
+ cfg::eCache = reinterpret_cast<TExtraCache *>(malloc(sizeof(TExtraCache) * iCount));
+ ZeroMemory(cfg::eCache, sizeof(struct TExtraCache) * iCount);
+ cfg::nextCacheEntry = 0;
+ cfg::maxCacheEntry = iCount;
+ cfg::initCache();
+
+ cfg::dat.hMenuNotify = CreatePopupMenu();
+ cfg::dat.wNextMenuID = 1;
+ cfg::dat.szNoEvents = TranslateTS(szNoevents);
+ cfg::dat.avatarBorder = (COLORREF)cfg::getDword("CLC", "avatarborder", 0);
+ cfg::dat.hBrushAvatarBorder = CreateSolidBrush(cfg::dat.avatarBorder);
+ cfg::dat.avatarSize = cfg::getWord("CList", "AvatarSize", 24);
+ cfg::dat.dualRowMode = cfg::getByte("CLC", "DualRowMode", 0);
+ cfg::dat.avatarPadding = cfg::getByte("CList", "AvatarPadding", 0);
+ cfg::dat.isTransparent = cfg::getByte("CList", "Transparent", 0);
+ cfg::dat.alpha = cfg::getByte("CList", "Alpha", SETTING_ALPHA_DEFAULT);
+ cfg::dat.autoalpha = cfg::getByte("CList", "AutoAlpha", SETTING_ALPHA_DEFAULT);
+ cfg::dat.fadeinout = cfg::getByte("CLUI", "FadeInOut", 0);
+ cfg::dat.autosize = cfg::getByte("CLUI", "AutoSize", 0);
+ cfg::dat.dwExtraImageMask = cfg::getDword("CLUI", "ximgmask", 0);
+ cfg::dat.bNoOfflineAvatars = cfg::getByte("CList", "NoOfflineAV", 1);
+ cfg::dat.bDblClkAvatars = cfg::getByte("CLC", "dblclkav", 0);
+ cfg::dat.bEqualSections = cfg::getByte("CLUI", "EqualSections", 0);
+ cfg::dat.bCenterStatusIcons = cfg::getByte("CLC", "si_centered", 1);
+ cfg::dat.boldHideOffline = -1;
+ cfg::dat.bNoTrayTips = cfg::getByte("CList", "NoTrayTips", 0);
+ cfg::dat.bShowLocalTime = cfg::getByte("CLC", "ShowLocalTime", 1);
+ cfg::dat.bShowLocalTimeSelective = cfg::getByte("CLC", "SelectiveLocalTime", 1);
+ cfg::dat.bDontSeparateOffline = cfg::getByte("CList", "DontSeparateOffline", 0);
+ cfg::dat.bFirstRun = cfg::getByte("CLUI", "firstrun", 1);
+ cfg::dat.langPackCP = Langpack_GetDefaultCodePage();
+ cfg::dat.realTimeSaving = cfg::getByte("CLUI", "save_pos_always", 0);
+
+ DWORD sortOrder = cfg::getDword("CList", "SortOrder", SORTBY_NAME);
+ cfg::dat.sortOrder[0] = LOBYTE(LOWORD(sortOrder));
+ cfg::dat.sortOrder[1] = HIBYTE(LOWORD(sortOrder));
+ cfg::dat.sortOrder[2] = LOBYTE(HIWORD(sortOrder));
+
+ if(cfg::dat.bFirstRun)
+ cfg::writeByte("CLUI", "firstrun", 0);
+
+ _tzset();
+
+ if(!cfg::getString(NULL, "CLUI", "exIconOrder", &dbv)) {
+ if(lstrlenA(dbv.pszVal) < EXICON_COUNT) {
+ for(i = 1; i <= EXICON_COUNT; i++)
+ cfg::dat.exIconOrder[i - 1] = i;
+ } else {
+ for(i = 0; i < EXICON_COUNT; i++)
+ if(dbv.pszVal[i] < EXICON_COUNT + 1 && dbv.pszVal[i] > 0)
+ cfg::dat.exIconOrder[i] = dbv.pszVal[i];
+ else
+ cfg::dat.exIconOrder[i] = i + 1;
+ }
+ db_free(&dbv);
+ } else {
+ for(i = 1; i <= EXICON_COUNT; i++)
+ cfg::dat.exIconOrder[i - 1] = i;
+ }
+ ReloadThemedOptions();
+ FLT_ReadOptions();
+
+ CLUI::hExtraImages = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 30, 2);
+ ImageList_SetIconSize(CLUI::hExtraImages, cfg::dat.exIconScale, cfg::dat.exIconScale);
+
+ cfg::dat.dwFlags = cfg::getDword("CLUI", "Frameflags", CLUI_FRAME_STATUSICONS |
+ CLUI_FRAME_SHOWBOTTOMBUTTONS | CLUI_FRAME_BUTTONSFLAT | CLUI_FRAME_CLISTSUNKEN);
+ cfg::dat.dwFlags |= (cfg::getByte("CLUI", "ShowSBar", 1) ? CLUI_FRAME_SBARSHOW : 0);
+ cfg::dat.soundsOff = cfg::getByte("CLUI", "NoSounds", 0);
+
+ if(cfg::getByte("Skin", "UseSound", 0) != cfg::dat.soundsOff)
+ cfg::writeByte("Skin", "UseSound", (BYTE)(cfg::dat.soundsOff ? 0 : 1));
+
+ // get the clist interface
+ pcli = (CLIST_INTERFACE*)CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)g_hInst);
+
+ pcli->pfnBuildGroupPopupMenu = BuildGroupPopupMenu;
+ pcli->pfnCluiProtocolStatusChanged = CluiProtocolStatusChanged;
+ pcli->pfnCompareContacts = CLC::CompareContacts;
+ pcli->pfnCreateClcContact = CLC::CreateClcContact;
+ pcli->pfnCreateEvent = CLC::fnCreateEvent;
+ pcli->pfnDocking_ProcessWindowMessage = Docking_ProcessWindowMessage;
+ pcli->pfnGetDefaultFontSetting = GetDefaultFontSetting;
+ pcli->pfnGetRowBottomY = RowHeight::getItemBottomY;
+ pcli->pfnGetRowHeight = RowHeight::getHeight;
+ pcli->pfnGetRowTopY = RowHeight::getItemTopY;
+ pcli->pfnGetRowTotalHeight = RowHeight::getTotalHeight;
+ pcli->pfnGetWindowVisibleState = GetWindowVisibleState;
+ pcli->pfnHitTest = CLC::HitTest;
+ pcli->pfnLoadContactTree = CLC::LoadContactTree;
+ pcli->pfnOnCreateClc = CLUI::loadModule;
+ pcli->pfnPaintClc = CLC::Paint;
+ pcli->pfnRebuildEntireList = CLC::RebuildEntireList;
+ pcli->pfnRowHitTest = RowHeight::hitTest;
+ pcli->pfnScrollTo = CLC::ScrollTo;
+ pcli->pfnTrayIconUpdateBase = TrayIconUpdateBase;
+ pcli->pfnSetHideOffline = CLC::SetHideOffline;
+ pcli->pfnShowHide = ShowHide;
+ pcli->pfnBeginRenameSelection = CLC::BeginRenameSelection;
+ pcli->pfnAddContactToGroup = CLC::AddContactToGroup;
+
+ pcli->pfnRemoveItemFromGroup = CLC::RemoveItemFromGroup;
+
+ pcli->pfnAddEvent = CLC::AddEvent;
+
+ pcli->pfnRemoveEvent = CLC::RemoveEvent;
+
+ pcli->pfnAddGroup = CLC::AddGroup;
+
+ pcli->pfnAddInfoItemToGroup = CLC::AddInfoItemToGroup;
+
+ CLC::saveContactListControlWndProc = pcli->pfnContactListControlWndProc;
+ pcli->pfnContactListControlWndProc = CLC::wndProc;
+
+ CLUI::saveContactListWndProc = pcli->pfnContactListWndProc;
+ pcli->pfnContactListWndProc = CLUI::wndProc;
+
+ pcli->pfnIconFromStatusMode = CLC::fnIconFromStatusMode;
+
+ pcli->pfnLoadClcOptions = CLC::LoadClcOptions;
+
+ pcli->pfnProcessExternalMessages = CLC::ProcessExternalMessages;
+
+ pcli->pfnRecalcScrollBar = CLC::RecalcScrollBar;
+
+ pcli->pfnTrayIconProcessMessage = CLC::TrayIconProcessMessage;
+
+ rc = LoadContactListModule();
+ if(rc == 0)
+ rc = CLC::loadModule();
+
+ LoadCLUIFramesModule();
+ HookEvent(ME_SYSTEM_MODULESLOADED, systemModulesLoaded);
+ return rc;
+}
+
+// a plugin loader aware of CList exports will never call this.
+extern "C" int __declspec(dllexport) Load()
+{
+ return 1;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ if(IsWindow(pcli->hwndContactList))
+ DestroyWindow(pcli->hwndContactList);
+
+ ImageList_Destroy(CLUI::hExtraImages);
+ CLC::shutDown(0, 0);
+ UnLoadCLUIFramesModule();
+ Skin::Unload();
+ Api::onUnload();
+ WarningDlg::destroyAll();
+ DeleteCriticalSection(&cfg::cachecs);
+ UnregisterClassW(L"CLCButtonClass", g_hInst);
+ free(cfg::eCache);
+ Gfx::shutDown();
+ Gfx::D2D_Release();
+ return 0;
+}
+
diff --git a/plugins/Clist_ng/SRC/rowheight_funcs.cpp b/plugins/Clist_ng/SRC/rowheight_funcs.cpp new file mode 100644 index 0000000000..23e0434360 --- /dev/null +++ b/plugins/Clist_ng/SRC/rowheight_funcs.cpp @@ -0,0 +1,302 @@ +/*
+ * 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: rowheight_funcs.cpp 133 2010-09-30 06:27:18Z silvercircle $
+ *
+ */
+
+#include <commonheaders.h>
+#include <rowheight_funcs.h>
+
+BOOL RowHeight::Init(ClcData *dat)
+{
+ dat->rowHeight = 0;
+ dat->row_heights_size = 0;
+ dat->row_heights_allocated = 0;
+ dat->row_heights = NULL;
+
+ return TRUE;
+}
+
+void RowHeight::Free(ClcData *dat)
+{
+ if (dat->row_heights != NULL) {
+ free(dat->row_heights);
+ dat->row_heights = NULL;
+ }
+ dat->row_heights_allocated = 0;
+ dat->row_heights_size = 0;
+}
+
+void RowHeight::Clear(ClcData *dat)
+{
+ dat->row_heights_size = 0;
+}
+
+BOOL RowHeight::Alloc(ClcData *dat, int size)
+{
+ if (size > dat->row_heights_size)
+ {
+ if (size > dat->row_heights_allocated) {
+ int size_grow = size;
+
+ size_grow += 100 - (size_grow % 100);
+
+ if (dat->row_heights != NULL) {
+ int *tmp = (int *)realloc((void *)dat->row_heights, sizeof(int) * size_grow);
+
+ if (tmp == NULL) {
+ Free(dat);
+ return FALSE;
+ }
+
+ dat->row_heights = tmp;
+ }
+ else {
+ dat->row_heights = (int *)malloc(sizeof(int) * size_grow);
+
+ if (dat->row_heights == NULL) {
+ Free(dat);
+ return FALSE;
+ }
+ }
+ dat->row_heights_allocated = size_grow;
+ }
+ dat->row_heights_size = size;
+ }
+ return TRUE;
+}
+
+// Calc and store max row height
+int RowHeight::getMaxRowHeight(ClcData *dat, const HWND hwnd)
+{
+ int max_height = 0, i;
+ DWORD style=GetWindowLong(hwnd,GWL_STYLE);
+
+ int contact_fonts[] = {FONTID_CONTACTS, FONTID_INVIS, FONTID_OFFLINE, FONTID_NOTONLIST, FONTID_OFFINVIS};
+ int other_fonts[] = {FONTID_GROUPS, FONTID_GROUPCOUNTS, FONTID_DIVIDERS};
+
+ // Get contact font size
+ for (i = 0 ; i < MAX_REGS(contact_fonts) ; i++) {
+ if (max_height < dat->fontInfo[contact_fonts[i]].fontHeight)
+ max_height = dat->fontInfo[contact_fonts[i]].fontHeight;
+ }
+
+ if (cfg::dat.dualRowMode == 1 && !dat->bisEmbedded)
+ max_height += dat->fontInfo[FONTID_STATUS].fontHeight;
+
+ // Get other font sizes
+ for (i = 0 ; i < MAX_REGS(other_fonts) ; i++) {
+ if (max_height < dat->fontInfo[other_fonts[i]].fontHeight)
+ max_height = dat->fontInfo[other_fonts[i]].fontHeight;
+ }
+
+ // Avatar size
+ if (cfg::dat.dwFlags & CLUI_FRAME_AVATARS && !dat->bisEmbedded)
+ max_height = max(max_height, cfg::dat.avatarSize + cfg::dat.avatarPadding);
+
+ // Checkbox size
+ if (style&CLS_CHECKBOXES || style&CLS_GROUPCHECKBOXES)
+ max_height = max(max_height, dat->checkboxSize);
+
+ //max_height += 2 * dat->row_border;
+ // Min size
+ max_height = max(max_height, dat->min_row_heigh);
+ max_height += cfg::dat.bRowSpacing;
+
+ dat->rowHeight = max_height;
+
+ return max_height;
+}
+
+// Calc and store row height for all itens in the list
+void RowHeight::calcRowHeights(ClcData *dat, HWND hwnd, CLCPaintHelper* ph)
+{
+ int indent, subindex, line_num;
+ struct ClcContact *Drawing;
+ struct ClcGroup *group;
+ DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
+
+ // Draw lines
+ group=&dat->list;
+ group->scanIndex=0;
+ indent=0;
+ //subindex=-1;
+ line_num = -1;
+
+ Clear(dat);
+
+ while(TRUE)
+ {
+ if (group->scanIndex==group->cl.count)
+ {
+ group=group->parent;
+ indent--;
+ if(group==NULL) break; // Finished list
+ group->scanIndex++;
+ continue;
+ }
+
+ // Get item to draw
+ Drawing = group->cl.items[group->scanIndex];
+ line_num++;
+
+ if(!dat->bisEmbedded) {
+ ph->fSelected = (ph->index == dat->selection && Drawing->type != CLCIT_DIVIDER);
+ CLC::iHottrackItem = dat->exStyle & CLS_EX_TRACKSELECT && Drawing->type == CLCIT_CONTACT && dat->iHotTrack == ph->index;
+ if (CLC::iHottrackItem == ph->fSelected)
+ CLC::iHottrackItem = 0;
+ if(ph->fSelected && CLC::dsp_default.dspOverride[DSP_OVR_SELECTED].fActive)
+ ph->dsp = &CLC::dsp_default.dspOverride[DSP_OVR_SELECTED];
+ else if(CLC::iHottrackItem && CLC::dsp_default.dspOverride[DSP_OVR_HOVERED].fActive)
+ ph->dsp = &CLC::dsp_default.dspOverride[DSP_OVR_HOVERED];
+ else if(ID_STATUS_OFFLINE == Drawing->wStatus)
+ ph->dsp = &CLC::dsp_default.dspOverride[DSP_OVR_OFFLINE];
+ else if(ID_STATUS_OFFLINE != Drawing->wStatus)
+ ph->dsp = &CLC::dsp_default.dspOverride[DSP_OVR_ONLINE];
+ else
+ ph->dsp = 0; // calc dsp profile
+ }
+ else
+ ph->dsp = 0;
+
+ // Calc row height
+ getRowHeight(dat, Drawing, line_num, dwStyle, ph);
+
+ if(group->cl.items[group->scanIndex]->type==CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded & 0x0000ffff)) {
+ group=group->cl.items[group->scanIndex]->group;
+ indent++;
+ group->scanIndex=0;
+ subindex=-1;
+ continue;
+ }
+ group->scanIndex++;
+ }
+}
+
+
+// Calc item top Y (using stored data)
+int RowHeight::getItemTopY(ClcData *dat, int item)
+{
+ int i;
+ int y = 0;
+
+ if (item >= dat->row_heights_size)
+ return -1;
+
+ for (i = 0 ; i < item ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+
+// Calc item bottom Y (using stored data)
+int RowHeight::getItemBottomY(ClcData *dat, int item)
+{
+ int i;
+ int y = 0;
+
+ if (item >= dat->row_heights_size)
+ return -1;
+
+ for (i = 0 ; i <= item ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+
+// Calc total height of rows (using stored data)
+int RowHeight::getTotalHeight(ClcData *dat)
+{
+ int i;
+ int y = 0;
+
+ for (i = 0 ; i < dat->row_heights_size ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+// Return the line that pos_y is at or -1 (using stored data)
+int RowHeight::hitTest(ClcData *dat, int pos_y)
+{
+ int i;
+ int y = 0;
+
+ if (pos_y < 0)
+ return -1;
+
+ for (i = 0 ; i < dat->row_heights_size ; i++)
+ {
+ y += dat->row_heights[i];
+
+ if (pos_y < y)
+ return i;
+ }
+
+ return -1;
+}
+
+int RowHeight::getHeight(ClcData *dat, int item)
+{
+ if ( dat->row_heights == 0 )
+ return 0;
+
+ return dat->row_heights[ item ];
+}
+
+int RowHeight::getFloatingRowHeight(const ClcData *dat, HWND hwnd, ClcContact *contact, DWORD dwFlags)
+{
+ int height = 0;
+
+ height = dat->fontInfo[GetBasicFontID(contact)].fontHeight;
+
+ if(!dat->bisEmbedded) {
+ if(!(dwFlags & FLT_SIMPLE)){
+ if(dwFlags & FLT_DUALROW) {
+ height += (dat->fontInfo[FONTID_STATUS].fontHeight + cfg::dat.avatarPadding);
+ }
+ // Avatar size
+ if (dwFlags & FLT_AVATARS && contact->cFlags & ECF_AVATAR && contact->type == CLCIT_CONTACT && contact->ace != NULL && !(contact->ace->dwFlags & AVS_HIDEONCLIST))
+ height = max(height, cfg::dat.avatarSize + cfg::dat.avatarPadding);
+ }
+ }
+
+ height = max(height, dat->min_row_heigh);
+ height += cfg::dat.bRowSpacing;
+
+ return height;
+}
diff --git a/plugins/Clist_ng/SRC/skin.cpp b/plugins/Clist_ng/SRC/skin.cpp new file mode 100644 index 0000000000..4137b30c87 --- /dev/null +++ b/plugins/Clist_ng/SRC/skin.cpp @@ -0,0 +1,1119 @@ +/*
+ * 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: skin.cpp 138 2010-11-01 10:51:15Z silvercircle $
+ *
+ * implement skin management, loading, applying etc.
+ *
+ * about database values:
+ *
+ * various skin-related settings may be written to the databse. the module
+ * name is CLNgSkin and the value names are the same as variable names in the
+ * TSkinSettings and TSkinMetrics data structures with the following
+ * prefixes:
+ *
+ * s - a value belonging to TSkinSettings
+ * m - a value belonging to TSkinMetrics
+ * g - a global value belonging to the Skin class - e.gl gCurrentSkin
+ * holds the name of the currently active skin.
+ *
+ */
+
+
+#include <commonheaders.h>
+
+TStatusItem* Skin::statusItems = 0;
+TImageItem* Skin::imageItems = 0;
+TImageItem* Skin::glyphItem = 0;
+TSkinMetrics Skin::metrics = {0};
+TSkinSettings Skin::settings = {0};
+
+int Skin::ID_EXTBK_LAST = ID_EXTBK_LAST_D;
+
+UINT SkinLoader::nextButtonID = IDC_TBFIRSTUID;
+
+
+
+/*
+ * TODO Refactor
+ */
+extern struct CluiTopButton top_buttons[];
+extern TStatusItem DefaultStatusItems[ID_EXTBK_LAST_D + 1];
+
+HBRUSH g_CLUISkinnedBkColor = 0;
+COLORREF g_CLUISkinnedBkColorRGB = 0;
+
+
+void Skin::setAeroMargins()
+{
+ if(cfg::isAero) {
+ MARGINS m = {-1};
+ Api::pfnDwmExtendFrameIntoClientArea(pcli->hwndContactList, &m);
+ }
+ else {
+ MARGINS m = {0};
+ Api::pfnDwmExtendFrameIntoClientArea(pcli->hwndContactList, &m);
+ }
+}
+
+void Skin::updateAeroState()
+{
+ cfg::isAero = (settings.fHaveAeroBG && settings.fUseAero && Api::sysState.isAero) ? true : false;
+}
+
+void Skin::Activate()
+{
+ CLUI::applyBorderStyle();
+ CLUI::configureGeometry(1);
+
+ ShowWindow(pcli->hwndContactList, SW_SHOWNORMAL);
+ SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
+ SendMessageW(pcli->hwndContactList, WM_SIZE, 0, 0);
+ updateAeroState();
+ setAeroMargins();
+ CLUI::Redraw();
+}
+
+/**
+ * free a single image item, release DC, delete bitmap
+ * @param item TImageItem* the item to free
+ */
+void Skin::freeImageItem(TImageItem *item)
+{
+ if(item) {
+ if(!(item->dwFlags & IMAGE_GLYPH)) {
+ SelectObject(item->hdc, item->hbmOld);
+ DeleteObject(item->hbm);
+ DeleteDC(item->hdc);
+ }
+ if(item->fillBrush)
+ DeleteObject(item->fillBrush);
+ }
+}
+
+void Skin::colorizeGlyphByName(const char* szGlyphName, const COLORREF clr, float h, float s, float v)
+{
+ if(szGlyphName) {
+ TImageItem *_t = imageItems;
+ while(_t) {
+ if(!strcmp(_t->szName, szGlyphName)) {
+ Gfx::colorizeGlyph(_t, clr, h, s, v);
+ break;
+ }
+ _t = _t->nextItem;
+ }
+ }
+}
+
+/**
+ * render a image item with the given name to the target rectangle in the target
+ * device context.
+ *
+ * @param szItemname image item name (must include the preceeding $ or @)
+ * @param rc target rectangle
+ * @param hdc target dc
+ */
+void Skin::renderNamedImageItem(const char *szItemname, RECT* rc, const HDC hdc)
+{
+ if(szItemname) {
+ TImageItem *_t = imageItems;
+ while(_t) {
+ if(_t->szName && !strcmp(_t->szName, szItemname)) {
+ Gfx::renderImageItem(hdc, _t, rc);
+ break;
+ }
+ _t = _t->nextItem;
+ }
+ }
+}
+/**
+ * free all skin items
+ * a) image items
+ * b) global image items (glyph, CLUI background)
+ * c) button items
+ */
+void Skin::Unload()
+{
+ TImageItem *pItem = imageItems, *pNextItem;
+ TButtonItem *pbItem = CLUI::buttonItems, *pbNextItem;
+
+ while(pItem) {
+ freeImageItem(pItem);
+ pNextItem = pItem->nextItem;
+ free(pItem);
+ pItem = pNextItem;
+ }
+ imageItems = NULL;
+ while(pbItem) {
+ DestroyWindow(pbItem->hWnd);
+ pbNextItem = pbItem->nextItem;
+ free(pbItem);
+ pbItem = pbNextItem;
+ }
+ CLUI::buttonItems = 0;
+
+ if(CLUI::bgImageItem) {
+ freeImageItem(CLUI::bgImageItem);
+ free(CLUI::bgImageItem);
+ }
+ CLUI::bgImageItem = 0;
+
+ if(CLUI::bgImageItem_nonAero) {
+ freeImageItem(CLUI::bgImageItem_nonAero);
+ free(CLUI::bgImageItem_nonAero);
+ }
+ CLUI::bgImageItem_nonAero = 0;
+
+ if(CLUI::bgClientItem) {
+ freeImageItem(CLUI::bgClientItem);
+ free(CLUI::bgClientItem);
+ }
+ CLUI::bgClientItem = 0;
+
+ if(glyphItem) {
+ freeImageItem(glyphItem);
+ free(glyphItem);
+ }
+ glyphItem = NULL;
+
+ if(statusItems) {
+ TStatusItem* item;
+ for(int i = 0; i <= ID_EXTBK_LAST; i++) {
+ item = &statusItems[i];
+
+ if(item->span_allocator) {
+ delete item->gradient_renderer_x;
+ delete item->gradient_renderer_y;
+ delete item->solid_renderer;
+ delete item->span_gradient_x;
+ delete item->span_gradient_y;
+ delete item->gradient_trans;
+ delete item->gradient_func_x;
+ delete item->gradient_func_y;
+ delete item->color_array;
+ delete item->span_interpolator;
+ delete item->span_allocator;
+ delete item->pixfmt;
+ delete item->rbase;
+ delete item->rect;
+ }
+ }
+ free(statusItems);
+ statusItems = 0;
+ ID_EXTBK_LAST = ID_EXTBK_LAST_D;
+ }
+}
+
+/**
+ * setup the items AGG rendering pipeline - set color values for the gradient
+ * and the rectangle shape (corners)
+ *
+ * @param item TStatusItem* - a skin item
+ */
+void Skin::setupAGGItemContext(TStatusItem* item)
+{
+ BYTE r = GetRValue(item->COLOR);
+ BYTE g = GetGValue(item->COLOR);
+ BYTE b = GetBValue(item->COLOR);
+
+ BYTE r2 = GetRValue(item->COLOR2);
+ BYTE g2 = GetGValue(item->COLOR2);
+ BYTE b2 = GetBValue(item->COLOR2);
+
+ if(0 == item->span_allocator) // do not setup for image items only (these do not have AGG objects).
+ return;
+
+ item->dwFlags &= ~(AGG_USE_GRADIENT_X_RENDERER | AGG_USE_GRADIENT_Y_RENDERER | AGG_USE_SOLID_RENDERER);
+
+ /*
+ * alpha values as read from the skin definition are in PERCENT (0-100)
+ */
+ if(item->GRADIENT & GRADIENT_ACTIVE) {
+ //agg::rgba8 r1 = agg::rgba8(r, g, b, percent_to_byte(item->ALPHA));
+ //agg::rgba8 r2 = agg::rgba8(r2, g2, b2, percent_to_byte(item->ALPHA2));
+
+ agg::rgba8 r1(r, g, b, percent_to_byte(item->ALPHA));
+ agg::rgba8 r2(r2, g2, b2, percent_to_byte(item->ALPHA2));
+
+ if(item->GRADIENT & GRADIENT_LR || item->GRADIENT & GRADIENT_TB) {
+ AGGContext::fill_color_array(*(item->color_array), r1, r2);
+ item->dwFlags |= (item->GRADIENT & GRADIENT_LR ? AGG_USE_GRADIENT_X_RENDERER : AGG_USE_GRADIENT_Y_RENDERER);
+ }
+ else {
+ item->dwFlags |= (item->GRADIENT & GRADIENT_RL ? AGG_USE_GRADIENT_X_RENDERER : AGG_USE_GRADIENT_Y_RENDERER);
+ AGGContext::fill_color_array(*(item->color_array), r2, r1);
+ }
+ }
+ else {
+ /*
+ * if no gradient is defined for this item, use a solid renderer
+ * it's faster.
+ */
+ item->solid_renderer->color(agg::rgba8(r, g, b, percent_to_byte(item->ALPHA)));
+ item->dwFlags |= AGG_USE_SOLID_RENDERER;
+ }
+
+ /*
+ * we can setup the corner radius values for our shape here. When rendering, we use
+ * item->rect->rect() to set the dimensions of the rectangle only.
+ *
+ * TODO make radius customizable
+ */
+
+ item->rect->radius(0, 0, 0, 0, 0, 0, 0, 0);
+ if(item->CORNER & CORNER_ACTIVE) {
+ double x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0;
+
+ if(item->CORNER & CORNER_TL)
+ x1 = y1 = Skin::metrics.cCornerRadius;
+ if(item->CORNER & CORNER_TR)
+ x2 = y2 = Skin::metrics.cCornerRadius;
+ if(item->CORNER & CORNER_BL)
+ x4 = y4 = Skin::metrics.cCornerRadius;
+ if(item->CORNER & CORNER_BR)
+ x3 = y3 = Skin::metrics.cCornerRadius;
+
+ item->rect->radius(x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+}
+
+/**
+ * export skin-relevant database settings to the corresponding skin settings file
+ * @param file
+ */
+void Skin::exportSettingsToFile(const char *file)
+{
+ // TODO needs work
+
+ /*
+ int i = 0;
+ DWORD data;
+ char cPrefix, szBuf[30];
+ */
+}
+/**
+ * exports all skin-relevant customization to a file
+ * @param file file name (INI format)
+ */
+void Skin::exportToFile(const char *file)
+{
+ int n;
+ char szSection[255];
+ char szKey[255];
+ DBVARIANT dbv = {0};
+ DWORD data;
+ char* szSectionName = 0, *p = 0;
+
+ for (n = 0; n <= ID_EXTBK_LAST; n++) {
+ if (statusItems[n].statusID != ID_EXTBKSEPARATOR) {
+ szSectionName = p = statusItems[n].szName;
+ if('{' == szSectionName[0])
+ p += 3;
+
+ Utils::writeProfile(p, "ColorHigh", statusItems[n].COLOR, file);
+ Utils::writeProfile(p, "ColorLow", statusItems[n].COLOR2, file);
+ Utils::writeProfile(p, "Textcolor", statusItems[n].TEXTCOLOR, file);
+ Utils::writeProfile(p, "Ignored", statusItems[n].IGNORED, file);
+ Utils::writeProfile(p, "Left", statusItems[n].MARGIN_LEFT, file);
+ Utils::writeProfile(p, "Top", statusItems[n].MARGIN_TOP, file);
+ Utils::writeProfile(p, "Right", statusItems[n].MARGIN_RIGHT, file);
+ Utils::writeProfile(p, "Bottom", statusItems[n].MARGIN_BOTTOM, file);
+ Utils::writeProfile(p, "Alpha", statusItems[n].ALPHA, file);
+ Utils::writeProfile(p, "Alpha2", statusItems[n].ALPHA2, file);
+ Utils::writeProfile(p, "Corner", statusItems[n].CORNER, file);
+ Utils::writeProfile(p, "Gradient", statusItems[n].GRADIENT, file);
+ Utils::writeProfile(p, "Flags", statusItems[n].dwFlags, file);
+ }
+ }
+ for(n = 0; n <= FONTID_LAST; n++) {
+ mir_snprintf(szSection, 255, "Font%d", n);
+
+ mir_snprintf(szKey, 255, "Font%dName", n);
+ if(!cfg::getString(NULL, "CLC", szKey, &dbv)) {
+ Utils::writeProfile(szSection, "Name", dbv.pszVal, file);
+ mir_free(dbv.pszVal);
+ }
+ mir_snprintf(szKey, 255, "Font%dSize", n);
+ data = (DWORD)cfg::getByte("CLC", szKey, 8);
+ Utils::writeProfile(szSection, "Size", data, file);
+
+ mir_snprintf(szKey, 255, "Font%dSty", n);
+ data = (DWORD)cfg::getByte("CLC", szKey, 8);
+ Utils::writeProfile(szSection, "Style", data, file);
+
+ mir_snprintf(szKey, 255, "Font%dSet", n);
+ data = (DWORD)cfg::getByte("CLC", szKey, 8);
+ Utils::writeProfile(szSection, "Set", data, file);
+
+ mir_snprintf(szKey, 255, "Font%dCol", n);
+ data = cfg::getDword("CLC", szKey, 8);
+ Utils::writeProfile(szSection, "Color", data, file);
+
+ mir_snprintf(szKey, 255, "Font%dFlags", n);
+ data = (DWORD)cfg::getDword("CLC", szKey, 8);
+ Utils::writeProfile(szSection, "Flags", data, file);
+
+ }
+}
+
+static TStatusItem default_item = {
+ "{--Contact--}", 0,
+ CLCDEFAULT_GRADIENT, CLCDEFAULT_CORNER,
+ CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, -1,
+ CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT,
+ CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE
+};
+
+void SkinLoader::readItem(TStatusItem *this_item, const char *szItem)
+{
+ TStatusItem *defaults = &default_item;
+ DWORD tmpflags;
+
+ this_item->ALPHA = (int)GetPrivateProfileIntA(szItem, "Alpha", defaults->ALPHA, m_szFilename);
+ this_item->ALPHA = min(this_item->ALPHA, 100);
+ this_item->ALPHA2 = (int)GetPrivateProfileIntA(szItem, "Alpha2", defaults->ALPHA, m_szFilename);
+ this_item->ALPHA2 = min(this_item->ALPHA2, 100);
+ this_item->COLOR = GetPrivateProfileIntA(szItem, "ColorHigh", 0, m_szFilename);
+ this_item->COLOR2 = GetPrivateProfileIntA(szItem, "ColorLow", 0, m_szFilename);
+
+ this_item->CORNER = GetPrivateProfileIntA(szItem, "Corner", 0, m_szFilename);
+
+ this_item->GRADIENT = GetPrivateProfileIntA(szItem, "Gradient", 0, m_szFilename);
+
+ this_item->MARGIN_LEFT = GetPrivateProfileIntA(szItem, "Left", defaults->MARGIN_LEFT, m_szFilename);
+ this_item->MARGIN_RIGHT = GetPrivateProfileIntA(szItem, "Right", defaults->MARGIN_RIGHT, m_szFilename);
+ this_item->MARGIN_TOP = GetPrivateProfileIntA(szItem, "Top", defaults->MARGIN_TOP, m_szFilename);
+ this_item->MARGIN_BOTTOM = GetPrivateProfileIntA(szItem, "Bottom", defaults->MARGIN_BOTTOM, m_szFilename);
+
+ this_item->TEXTCOLOR = GetPrivateProfileIntA(szItem, "Textcolor", 0, m_szFilename);
+ this_item->IGNORED = GetPrivateProfileIntA(szItem, "Ignored", 0, m_szFilename);
+ tmpflags = GetPrivateProfileIntA(szItem, "Flags", 0, m_szFilename);
+ this_item->dwFlags |= tmpflags;
+}
+
+void SkinLoader::loadBaseItems()
+{
+ int protoCount = 0, i, n;
+ PROTOACCOUNT** accs = 0;
+ char* p = 0;
+
+ Proto_EnumAccounts(&protoCount, &accs);
+
+ if(Skin::statusItems) {
+ free(Skin::statusItems);
+ Skin::statusItems = 0;
+ Skin::ID_EXTBK_LAST = ID_EXTBK_LAST_D;
+ }
+ Skin::statusItems = (TStatusItem *)malloc(sizeof(TStatusItem) * ((Skin::ID_EXTBK_LAST) + protoCount + 2));
+ CopyMemory(Skin::statusItems, DefaultStatusItems, sizeof(DefaultStatusItems));
+
+ for(i = 0; i < protoCount; i++) {
+ Skin::ID_EXTBK_LAST++;
+ CopyMemory(&Skin::statusItems[Skin::ID_EXTBK_LAST], &Skin::statusItems[0], sizeof(TStatusItem));
+ if(i == 0) {
+ lstrcpynA(Skin::statusItems[Skin::ID_EXTBK_LAST].szName, "{-}", 30);
+ strncat(Skin::statusItems[Skin::ID_EXTBK_LAST].szName, accs[i]->szModuleName, 30);
+ }
+ else
+ lstrcpynA(Skin::statusItems[Skin::ID_EXTBK_LAST].szName, accs[i]->szModuleName, 30);
+ Skin::statusItems[Skin::ID_EXTBK_LAST].statusID = Skin::ID_EXTBK_LAST;
+ }
+ for (n = 0; n <= Skin::ID_EXTBK_LAST; n++) {
+ if (Skin::statusItems[n].statusID != ID_EXTBKSEPARATOR) {
+ Skin::statusItems[n].imageItem = 0;
+ p = Skin::statusItems[n].szName;
+ if(*p == '{')
+ p += 3;
+
+ TStatusItem* item = &Skin::statusItems[n];
+
+ readItem(item, p);
+
+ if(!(item->dwFlags & S_ITEM_IMAGE_ONLY)) {
+ item->span_allocator = new span_allocator_t;
+ item->color_array = new agg::pod_auto_array<agg::rgba8, 256>();
+ item->gradient_func_x = new agg::gradient_x();
+ item->gradient_func_y = new agg::gradient_y();
+ item->gradient_trans = new agg::trans_affine();
+ item->span_interpolator = new agg::span_interpolator_linear<>(*(item->gradient_trans));
+ item->span_gradient_x = new span_gradient_x_t(*(item->span_interpolator),
+ *(item->gradient_func_x), *(item->color_array), 0, 200);
+
+ item->span_gradient_y = new span_gradient_y_t(*(item->span_interpolator),
+ *(item->gradient_func_y), *(item->color_array), 0, 200);
+
+ item->pixfmt = new agg::pixfmt_bgra32(); //*(item->rbuf));
+ item->rbase = new agg::renderer_base<agg::pixfmt_bgra32>(); //*(item->pixfmt));
+ item->gradient_renderer_x = new agg::renderer_scanline_aa<agg::renderer_base<agg::pixfmt_bgra32>, span_allocator_t, span_gradient_x_t>(*(item->rbase),
+ *(item->span_allocator), *(item->span_gradient_x));
+
+ item->gradient_renderer_y = new agg::renderer_scanline_aa<agg::renderer_base<agg::pixfmt_bgra32>, span_allocator_t, span_gradient_y_t>(*(item->rbase),
+ *(item->span_allocator), *(item->span_gradient_y));
+
+ item->solid_renderer = new agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_bgra32> >(*(item->rbase));
+
+ item->rect = new agg::rounded_rect(0, 0, 0, 0, 0);
+
+ Skin::setupAGGItemContext(item);
+ }
+ else
+ item->span_allocator = 0;
+ }
+ }
+}
+
+/**
+ * read font definitions from INI style file and write them to the
+ * database.
+ *
+ * uses m_szFilename to read from...
+ */
+void SkinLoader::loadFonts()
+{
+ int n;
+ char buffer[255];
+ char szKey[255], szSection[255];
+ DWORD data;
+
+ for(n = 0; n <= FONTID_LAST; n++) {
+ mir_snprintf(szSection, 255, "Font%d", n);
+
+ mir_snprintf(szKey, 255, "Font%dName", n);
+ GetPrivateProfileStringA(szSection, "Name", "Arial", buffer, sizeof(buffer), m_szFilename);
+ cfg::writeString(NULL, "CLC", szKey, buffer);
+
+ mir_snprintf(szKey, 255, "Font%dSize", n);
+ data = readInt(szSection, "Size", 10);
+ cfg::writeByte("CLC", szKey, (BYTE)data);
+
+ mir_snprintf(szKey, 255, "Font%dSty", n);
+ data = readInt(szSection, "Style", 0);
+ cfg::writeByte("CLC", szKey, (BYTE)data);
+
+ mir_snprintf(szKey, 255, "Font%dSet", n);
+ data = readInt(szSection, "Set", 1);
+ cfg::writeByte("CLC", szKey, (BYTE)data);
+
+ mir_snprintf(szKey, 255, "Font%dCol", n);
+ data = readInt(szSection, "Color", 0x00);
+ cfg::writeDword("CLC", szKey, data);
+
+ mir_snprintf(szKey, 255, "Font%dFlags", n);
+ data = readInt(szSection, "Flags", 0);
+ cfg::writeDword("CLC", szKey, (WORD)data);
+ }
+}
+
+/**
+ * load a skin with the given name.
+ * @param wszFilename: full path and file name of the skin
+ * definition file (.cng format)
+ *
+ * after constructing, check ::isValid() before using the Load()
+ * method.
+ */
+SkinLoader::SkinLoader(const wchar_t* wszFilename)
+{
+ wchar_t wszBase[MAX_PATH], wszRelPath[MAX_PATH];
+ m_isValid = false;
+ wchar_t wszDrive[_MAX_DRIVE], wszDir[_MAX_DIR], wszFile[_MAX_FNAME];
+
+ Skin::settings.wszSkinBaseFolder[0] = Skin::settings.wszSkinName[0] = 0;
+
+ mir_sntprintf(wszBase, MAX_PATH, L"%s%s", cfg::szProfileDir, L"skin\\clng\\base\\base.cng");
+ if(0 == wszFilename) {
+ if(PathFileExists(wszBase)) {
+ wcsncpy(m_wszFilename, wszBase, MAX_PATH);
+ m_wszFilename[MAX_PATH - 1] = 0;
+ WideCharToMultiByte(CP_ACP, 0, wszBase, MAX_PATH, m_szFilename, MAX_PATH, 0, 0);
+ m_isValid = true;
+ }
+ }
+ else {
+ if(PathFileExists(wszFilename)) {
+ WideCharToMultiByte(CP_ACP, 0, wszFilename, MAX_PATH, m_szFilename, MAX_PATH, 0, 0);
+ wcsncpy(m_wszFilename, wszFilename, MAX_PATH);
+ m_wszFilename[MAX_PATH - 1] = 0;
+ }
+ else {
+ WideCharToMultiByte(CP_ACP, 0, wszBase, MAX_PATH, m_szFilename, MAX_PATH, 0, 0);
+ wcsncpy(m_wszFilename, wszBase, MAX_PATH);
+ m_wszFilename[MAX_PATH - 1] = 0;
+ }
+ m_isValid = true;
+ }
+ Utils::pathToRelative(m_wszFilename, wszRelPath, cfg::szProfileDir);
+ cfg::writeTString(0, SKIN_DB_MODULE, "gCurrentSkin", wszRelPath);
+ _wsplitpath(m_wszFilename, wszDrive, wszDir, wszFile, 0);
+ mir_sntprintf(Skin::settings.wszSkinBaseFolder, MAX_PATH, L"%s%s", wszDrive, wszDir);
+ mir_sntprintf(Skin::settings.wszSkinName, MAX_PATH, L"%s", wszFile);
+}
+
+/**
+ * read a setting from the skin definition file
+ * the filename is in m_szFilename and was set in the ctor
+ *
+ * @param szSection INI section
+ * @param szValue key name
+ * @param dwDefault default when the entry is not found
+ * @return DWORD containing the read value (or the default)
+ */
+DWORD SkinLoader::readInt(const char* szSection, const char* szValue, DWORD dwDefault)
+{
+ if(m_isValid)
+ return(GetPrivateProfileIntA(szSection, szValue, dwDefault, m_szFilename));
+ else
+ return(0);
+}
+
+HRESULT SkinLoader::Load()
+{
+ /*
+ * load metrics and other skin data
+ */
+
+ Skin::metrics.cLeftSkinned = readInt("FramelessMetrics", "CLeft", 0);
+ Skin::metrics.cRightSkinned = readInt("FramelessMetrics", "CRight", 0);
+ Skin::metrics.cTopSkinned = readInt("FramelessMetrics", "CTop", 0);
+ Skin::metrics.cBottomSkinned = readInt("FramelessMetrics", "CBottom", 0);
+
+ Skin::metrics.cLeftFramed = readInt("Metrics", "CLeft", 0);
+ Skin::metrics.cRightFramed = readInt("Metrics", "CRight", 0);
+ Skin::metrics.cTopFramed = readInt("Metrics", "CTop", 0);
+ Skin::metrics.cBottomFramed = readInt("Metrics", "CBottom", 0);
+
+ Skin::metrics.bWindowStyle = readInt("Settings", "DefaultWindowStyle", SETTING_WINDOWSTYLE_NOBORDER);
+ Skin::metrics.cButtonHeight = readInt("Settings", "ButtonHeight", BUTTON_HEIGHT_D);
+ Skin::metrics.cFakeCaption = readInt("FramelessMetrics", "CaptionHeight", 0);
+ Skin::metrics.cFakeLeftBorder = readInt("FramelessMetrics", "LeftBorderWidth", 0);
+ Skin::metrics.cFakeRightBorder = readInt("FramelessMetrics", "RightBorderWidth", 0);
+ Skin::metrics.cFakeBtmBorder = readInt("FramelessMetrics", "BottomBorderWidth", 0);
+
+ Skin::metrics.cTopButtonset = readInt("Buttonset", "Top", 0);
+ Skin::metrics.cLeftButtonset = readInt("Buttonset", "Left", 0);
+ Skin::metrics.cRightButtonset = readInt("Buttonset", "Right", 0);
+ Skin::metrics.cBottomButtonset = readInt("Buttonset", "Bottom", 0);
+
+ Skin::metrics.cCornerRadius = readInt("Settings", "CornerRadius", 5);
+ Skin::settings.fUseAero = cfg::getByte(SKIN_DB_MODULE, "sfUseAero", 1) ? true : false;
+
+ /*
+ * read the base items and fill the structure
+ */
+ loadBaseItems();
+
+ /*
+ * load all other skin elements (images, buttons, icons)
+ */
+ if(!SUCCEEDED(loadItems()))
+ return(-S_FALSE);
+
+ /*
+ * TODO read font settings only when necessary (when skin has changed)
+ */
+
+ loadFonts();
+ cfg::FS_RegisterFonts();
+
+ /*
+ * validations (check image items, border styles and make sure everything makes
+ * sense). Protect against skin definition errors
+ */
+ Skin::settings.fHaveAeroBG = CLUI::bgImageItem ? true : false;
+ if(Skin::metrics.bWindowStyle == SETTING_WINDOWSTYLE_NOBORDER && (0 == CLUI::bgImageItem || 0 == CLUI::bgImageItem_nonAero))
+ Skin::metrics.bWindowStyle = SETTING_WINDOWSTYLE_DEFAULT;
+
+ return(S_OK);
+}
+
+HRESULT SkinLoader::loadItems()
+{
+ char* szSections = 0, *szFileName;
+ char* p;
+
+ /*
+ * TODO rewrite the skin loading in wchar_t manner
+ */
+
+ if(!PathFileExistsA(m_szFilename) || !m_isValid)
+ return(-S_FALSE);
+
+ szFileName = m_szFilename;
+
+ szSections = reinterpret_cast<char *>(malloc(3002));
+ ZeroMemory(szSections, 3002);
+ p = szSections;
+ GetPrivateProfileSectionNamesA(szSections, 3000, szFileName);
+
+ szSections[3001] = szSections[3000] = 0;
+ p = szSections;
+ while(lstrlenA(p) > 1) {
+ if(p[0] == '$' || p[0] == '@')
+ readImageItem(p, szFileName);
+ p += (lstrlenA(p) + 1);
+ }
+ nextButtonID = IDC_TBFIRSTUID;
+ p = szSections;
+ while(lstrlenA(p) > 1) {
+ if(p[0] == '!')
+ readButtonItem(p, szFileName);
+ p += (lstrlenA(p) + 1);
+ }
+ if(pcli && pcli->hwndContactList)
+ CLUI::setButtonStates(pcli->hwndContactList);
+ free(szSections);
+
+ if(CLUI::bgImageItem)
+ cfg::dat.dwFlags &= ~CLUI_FRAME_CLISTSUNKEN;
+
+ return(S_OK);
+}
+
+void SkinLoader::readImageItem(const char *itemname, const char *szFileName)
+{
+ TImageItem tmpItem, *newItem = NULL;
+ char buffer[512], szItemNr[30];
+ char szFinalName[MAX_PATH];
+ HDC hdc = GetDC(pcli->hwndContactList);
+ int i, n;
+ BOOL alloced = FALSE;
+ char szDrive[MAX_PATH], szPath[MAX_PATH];
+
+ ZeroMemory(&tmpItem, sizeof(TImageItem));
+ GetPrivateProfileStringA(itemname, "Glyph", "None", buffer, 500, szFileName);
+ if(strcmp(buffer, "None")) {
+ sscanf(buffer, "%d,%d,%d,%d", &tmpItem.glyphMetrics[0], &tmpItem.glyphMetrics[1],
+ &tmpItem.glyphMetrics[2], &tmpItem.glyphMetrics[3]);
+ if(tmpItem.glyphMetrics[2] > tmpItem.glyphMetrics[0] && tmpItem.glyphMetrics[3] > tmpItem.glyphMetrics[1]) {
+ tmpItem.dwFlags |= IMAGE_GLYPH;
+ tmpItem.glyphMetrics[2] = (tmpItem.glyphMetrics[2] - tmpItem.glyphMetrics[0]) + 1;
+ tmpItem.glyphMetrics[3] = (tmpItem.glyphMetrics[3] - tmpItem.glyphMetrics[1]) + 1;
+ goto done_with_glyph;
+ }
+ }
+ GetPrivateProfileStringA(itemname, "Image", "None", buffer, 500, szFileName);
+ if(strcmp(buffer, "None")) {
+
+done_with_glyph:
+
+ strncpy(tmpItem.szName, &itemname[0], sizeof(tmpItem.szName));
+ tmpItem.szName[sizeof(tmpItem.szName) - 1] = 0;
+ _splitpath(szFileName, szDrive, szPath, NULL, NULL);
+ mir_snprintf(szFinalName, MAX_PATH, "%s\\%s\\%s", szDrive, szPath, buffer);
+ tmpItem.alpha = GetPrivateProfileIntA(itemname, "Alpha", 100, szFileName);
+ tmpItem.alpha = min(tmpItem.alpha, 100);
+ tmpItem.alpha = (BYTE)((FLOAT)(((FLOAT) tmpItem.alpha) / 100) * 255);
+ tmpItem.bf.SourceConstantAlpha = tmpItem.alpha;
+ tmpItem.bLeft = GetPrivateProfileIntA(itemname, "Left", 0, szFileName);
+ tmpItem.bRight = GetPrivateProfileIntA(itemname, "Right", 0, szFileName);
+ tmpItem.bTop = GetPrivateProfileIntA(itemname, "Top", 0, szFileName);
+ tmpItem.bBottom = GetPrivateProfileIntA(itemname, "Bottom", 0, szFileName);
+ if(tmpItem.dwFlags & IMAGE_GLYPH) {
+ tmpItem.width = tmpItem.glyphMetrics[2];
+ tmpItem.height = tmpItem.glyphMetrics[3];
+ tmpItem.inner_height = tmpItem.glyphMetrics[3] - tmpItem.bTop - tmpItem.bBottom;
+ tmpItem.inner_width = tmpItem.glyphMetrics[2] - tmpItem.bRight - tmpItem.bLeft;
+
+ if(tmpItem.bTop && tmpItem.bBottom && tmpItem.bLeft && tmpItem.bRight)
+ tmpItem.dwFlags |= IMAGE_FLAG_DIVIDED;
+ tmpItem.bf.BlendFlags = 0;
+ tmpItem.bf.BlendOp = AC_SRC_OVER;
+ tmpItem.bf.AlphaFormat = 0;
+ tmpItem.dwFlags |= IMAGE_PERPIXEL_ALPHA;
+ tmpItem.bf.AlphaFormat = AC_SRC_ALPHA;
+ if(tmpItem.inner_height <= 0 || tmpItem.inner_width <= 0) {
+ ReleaseDC(pcli->hwndContactList, hdc);
+ return;
+ }
+ }
+ GetPrivateProfileStringA(itemname, "Fillcolor", "None", buffer, 500, szFileName);
+ if(strcmp(buffer, "None")) {
+ COLORREF fillColor = Utils::hexStringToLong(buffer);
+ tmpItem.fillBrush = CreateSolidBrush(fillColor);
+ tmpItem.dwFlags |= IMAGE_FILLSOLID;
+ }
+ else
+ tmpItem.fillBrush = 0;
+
+ GetPrivateProfileStringA(itemname, "Stretch", "None", buffer, 500, szFileName);
+ if(buffer[0] == 'B' || buffer[0] == 'b')
+ tmpItem.bStretch = IMAGE_STRETCH_B;
+ else if(buffer[0] == 'h' || buffer[0] == 'H')
+ tmpItem.bStretch = IMAGE_STRETCH_V;
+ else if(buffer[0] == 'w' || buffer[0] == 'W')
+ tmpItem.bStretch = IMAGE_STRETCH_H;
+ tmpItem.hbm = 0;
+
+ if(!_stricmp(itemname, "$glyphs")) {
+ createImageItem(&tmpItem, szFinalName, hdc);
+ if(tmpItem.hbm) {
+ newItem = reinterpret_cast<TImageItem *>(malloc(sizeof(TImageItem)));
+ ZeroMemory(newItem, sizeof(TImageItem));
+ *newItem = tmpItem;
+ Skin::glyphItem = newItem;
+ }
+ goto imgread_done;
+ }
+ if(itemname[0] == '@') {
+ if(!(tmpItem.dwFlags & IMAGE_GLYPH))
+ createImageItem(&tmpItem, szFinalName, hdc);
+ if(tmpItem.hbm || tmpItem.dwFlags & IMAGE_GLYPH) {
+
+ newItem = reinterpret_cast<TImageItem *>(malloc(sizeof(TImageItem)));
+ ZeroMemory(newItem, sizeof(TImageItem));
+ *newItem = tmpItem;
+
+ if(Skin::imageItems == NULL)
+ Skin::imageItems = newItem;
+ else {
+ TImageItem *pItem = Skin::imageItems;
+
+ while(pItem->nextItem != 0)
+ pItem = pItem->nextItem;
+ pItem->nextItem = newItem;
+ }
+ }
+ goto imgread_done;
+ }
+ for(n = 0;;n++) {
+ mir_snprintf(szItemNr, 30, "Item%d", n);
+ GetPrivateProfileStringA(itemname, szItemNr, "None", buffer, 500, szFileName);
+ if(!strcmp(buffer, "None"))
+ break;
+ if(!stricmp(buffer, "CLUI") || !stricmp(buffer, "CLUIAero") || !stricmp(buffer, "CLUIClient")) {
+ if(!(tmpItem.dwFlags & IMAGE_GLYPH))
+ createImageItem(&tmpItem, szFinalName, hdc);
+ if(tmpItem.hbm || tmpItem.dwFlags & IMAGE_GLYPH) {
+ COLORREF clr;
+
+ newItem = reinterpret_cast<TImageItem *>(malloc(sizeof(TImageItem)));
+ ZeroMemory(newItem, sizeof(TImageItem));
+ *newItem = tmpItem;
+
+ if(!stricmp(buffer, "CLUIAero"))
+ CLUI::bgImageItem = newItem;
+ else if(!stricmp(buffer, "CLUIClient"))
+ CLUI::bgClientItem = newItem;
+ else {
+ GetPrivateProfileStringA(itemname, "Colorkey", "e5e5e5", buffer, 500, szFileName);
+ clr = Utils::hexStringToLong(buffer);
+ cfg::dat.colorkey = clr;
+ cfg::writeDword("CLUI", "ColorKey", clr);
+ if(g_CLUISkinnedBkColor)
+ DeleteObject(g_CLUISkinnedBkColor);
+ g_CLUISkinnedBkColor = CreateSolidBrush(clr);
+ g_CLUISkinnedBkColorRGB = clr;
+ CLUI::bgImageItem_nonAero = newItem;
+ }
+ }
+ continue;
+ }
+ for(i = 0; i <= Skin::ID_EXTBK_LAST; i++) {
+ if(!_stricmp(Skin::statusItems[i].szName[0] == '{' ? &Skin::statusItems[i].szName[3] : Skin::statusItems[i].szName, buffer)) {
+ if(!alloced) {
+ if(!(tmpItem.dwFlags & IMAGE_GLYPH))
+ createImageItem(&tmpItem, szFinalName, hdc);
+ if(tmpItem.hbm || tmpItem.dwFlags & IMAGE_GLYPH) {
+ newItem = reinterpret_cast<TImageItem *>(malloc(sizeof(TImageItem)));
+ ZeroMemory(newItem, sizeof(TImageItem));
+ *newItem = tmpItem;
+ Skin::statusItems[i].imageItem = newItem;
+ if(Skin::imageItems == NULL)
+ Skin::imageItems = newItem;
+ else {
+ TImageItem *pItem = Skin::imageItems;
+
+ while(pItem->nextItem != 0)
+ pItem = pItem->nextItem;
+ pItem->nextItem = newItem;
+ }
+ alloced = TRUE;
+ }
+ }
+ else if(newItem != NULL)
+ Skin::statusItems[i].imageItem = newItem;
+ }
+ }
+ }
+ }
+imgread_done:
+ ReleaseDC(pcli->hwndContactList, hdc);
+
+}
+
+void SkinLoader::readButtonItem(const char *itemName, const char *file)
+{
+ TButtonItem tmpItem, *newItem;
+ char szBuffer[1024];
+ TImageItem *imgItem = Skin::imageItems;
+
+ ZeroMemory(&tmpItem, sizeof(tmpItem));
+ mir_snprintf(tmpItem.szName, sizeof(tmpItem.szName), "%s", &itemName[1]);
+ tmpItem.width = GetPrivateProfileIntA(itemName, "Width", 16, file);
+ tmpItem.height = GetPrivateProfileIntA(itemName, "Height", 16, file);
+ tmpItem.xOff = GetPrivateProfileIntA(itemName, "xoff", 0, file);
+ tmpItem.yOff = GetPrivateProfileIntA(itemName, "yoff", 0, file);
+
+ tmpItem.dwFlags |= GetPrivateProfileIntA(itemName, "toggle", 0, file) ? BUTTON_ISTOGGLE : 0;
+ tmpItem.dwFlags |= (GetPrivateProfileIntA(itemName, "FakeTitleButton", 0, file) ? (BUTTON_FRAMELESS_ONLY | BUTTON_FAKE_CAPTIONBUTTON) : 0);
+
+ GetPrivateProfileStringA(itemName, "Pressed", "None", szBuffer, 1000, file);
+ if(!_stricmp(szBuffer, "default"))
+ tmpItem.imgPressed = Skin::statusItems[ID_EXTBKBUTTONSPRESSED].imageItem;
+ else {
+ while(imgItem) {
+ if(!_stricmp(&imgItem->szName[1], szBuffer)) {
+ tmpItem.imgPressed = imgItem;
+ break;
+ }
+ imgItem = imgItem->nextItem;
+ }
+ }
+
+ imgItem = Skin::imageItems;
+ GetPrivateProfileStringA(itemName, "Normal", "None", szBuffer, 1000, file);
+ if(!_stricmp(szBuffer, "default"))
+ tmpItem.imgNormal = Skin::statusItems[ID_EXTBKBUTTONSNPRESSED].imageItem;
+ else {
+ while(imgItem) {
+ if(!_stricmp(&imgItem->szName[1], szBuffer)) {
+ tmpItem.imgNormal = imgItem;
+ break;
+ }
+ imgItem = imgItem->nextItem;
+ }
+ }
+
+ imgItem = Skin::imageItems;
+ GetPrivateProfileStringA(itemName, "Hover", "None", szBuffer, 1000, file);
+ if(!_stricmp(szBuffer, "default"))
+ tmpItem.imgHover = Skin::statusItems[ID_EXTBKBUTTONSMOUSEOVER].imageItem;
+ else {
+ while(imgItem) {
+ if(!_stricmp(&imgItem->szName[1], szBuffer)) {
+ tmpItem.imgHover = imgItem;
+ break;
+ }
+ imgItem = imgItem->nextItem;
+ }
+ }
+ GetPrivateProfileStringA(itemName, "Align", "lt", szBuffer, 1000, file);
+ if(lstrlenA(szBuffer) == 2) {
+ if(szBuffer[0] =='r' || szBuffer[0] == 'R')
+ tmpItem.dwFlags |= BUTTON_HALIGN_R;
+ if(szBuffer[1] == 'B' || szBuffer[1] == 'B')
+ tmpItem.dwFlags |= BUTTON_VALIGN_B;
+ }
+ GetPrivateProfileStringA(itemName, "NormalGlyph", "0, 0, 0, 0", szBuffer, 1000, file);
+ sscanf(szBuffer, "%d,%d,%d,%d", &tmpItem.normalGlyphMetrics[0], &tmpItem.normalGlyphMetrics[1],
+ &tmpItem.normalGlyphMetrics[2], &tmpItem.normalGlyphMetrics[3]);
+ tmpItem.normalGlyphMetrics[2] = (tmpItem.normalGlyphMetrics[2] - tmpItem.normalGlyphMetrics[0]) + 1;
+ tmpItem.normalGlyphMetrics[3] = (tmpItem.normalGlyphMetrics[3] - tmpItem.normalGlyphMetrics[1]) + 1;
+
+ GetPrivateProfileStringA(itemName, "PressedGlyph", "0, 0, 0, 0", szBuffer, 1000, file);
+ sscanf(szBuffer, "%d,%d,%d,%d", &tmpItem.pressedGlyphMetrics[0], &tmpItem.pressedGlyphMetrics[1],
+ &tmpItem.pressedGlyphMetrics[2], &tmpItem.pressedGlyphMetrics[3]);
+ tmpItem.pressedGlyphMetrics[2] = (tmpItem.pressedGlyphMetrics[2] - tmpItem.pressedGlyphMetrics[0]) + 1;
+ tmpItem.pressedGlyphMetrics[3] = (tmpItem.pressedGlyphMetrics[3] - tmpItem.pressedGlyphMetrics[1]) + 1;
+
+
+ GetPrivateProfileStringA(itemName, "HoverGlyph", "0, 0, 0, 0", szBuffer, 1000, file);
+ sscanf(szBuffer, "%d,%d,%d,%d", &tmpItem.hoverGlyphMetrics[0], &tmpItem.hoverGlyphMetrics[1],
+ &tmpItem.hoverGlyphMetrics[2], &tmpItem.hoverGlyphMetrics[3]);
+ tmpItem.hoverGlyphMetrics[2] = (tmpItem.hoverGlyphMetrics[2] - tmpItem.hoverGlyphMetrics[0]) + 1;
+ tmpItem.hoverGlyphMetrics[3] = (tmpItem.hoverGlyphMetrics[3] - tmpItem.hoverGlyphMetrics[1]) + 1;
+
+ tmpItem.uId = IDC_TBFIRSTUID - 1;
+
+ GetPrivateProfileStringA(itemName, "Action", "Custom", szBuffer, 1000, file);
+ if(!_stricmp(szBuffer, "service")) {
+ tmpItem.szService[0] = 0;
+ GetPrivateProfileStringA(itemName, "Service", "None", szBuffer, 1000, file);
+ if(_stricmp(szBuffer, "None")) {
+ mir_snprintf(tmpItem.szService, 256, "%s", szBuffer);
+ tmpItem.dwFlags |= BUTTON_ISSERVICE;
+ tmpItem.uId = nextButtonID++;
+ }
+ }
+ else if(!_stricmp(szBuffer, "protoservice")) {
+ tmpItem.szService[0] = 0;
+ GetPrivateProfileStringA(itemName, "Service", "None", szBuffer, 1000, file);
+ if(_stricmp(szBuffer, "None")) {
+ mir_snprintf(tmpItem.szService, 256, "%s", szBuffer);
+ tmpItem.dwFlags |= BUTTON_ISPROTOSERVICE;
+ tmpItem.uId = nextButtonID++;
+ }
+ }
+ else if(!_stricmp(szBuffer, "database")) {
+ int n;
+
+ GetPrivateProfileStringA(itemName, "Module", "None", szBuffer, 1000, file);
+ if(_stricmp(szBuffer, "None"))
+ mir_snprintf(tmpItem.szModule, 256, "%s", szBuffer);
+ GetPrivateProfileStringA(itemName, "Setting", "None", szBuffer, 1000, file);
+ if(_stricmp(szBuffer, "None"))
+ mir_snprintf(tmpItem.szSetting, 256, "%s", szBuffer);
+ if(GetPrivateProfileIntA(itemName, "contact", 0, file) != 0)
+ tmpItem.dwFlags |= BUTTON_DBACTIONONCONTACT;
+
+ for(n = 0; n <= 1; n++) {
+ char szKey[20];
+ BYTE *pValue;
+
+ strcpy(szKey, n == 0 ? "dbonpush" : "dbonrelease");
+ pValue = (n == 0 ? tmpItem.bValuePush : tmpItem.bValueRelease);
+
+ GetPrivateProfileStringA(itemName, szKey, "None", szBuffer, 1000, file);
+ switch(szBuffer[0]) {
+ case 'b':
+ {
+ BYTE value = (BYTE)atol(&szBuffer[1]);
+ pValue[0] = value;
+ tmpItem.type = DBVT_BYTE;
+ break;
+ }
+ case 'w':
+ {
+ WORD value = (WORD)atol(&szBuffer[1]);
+ *((WORD *)&pValue[0]) = value;
+ tmpItem.type = DBVT_WORD;
+ break;
+ }
+ case 'd':
+ {
+ DWORD value = (DWORD)atol(&szBuffer[1]);
+ *((DWORD *)&pValue[0]) = value;
+ tmpItem.type = DBVT_DWORD;
+ break;
+ }
+ case 's':
+ {
+ mir_snprintf((char *)pValue, 256, &szBuffer[1]);
+ tmpItem.type = DBVT_ASCIIZ;
+ break;
+ }
+ }
+ }
+ if(tmpItem.szModule[0] && tmpItem.szSetting[0]) {
+ tmpItem.dwFlags |= BUTTON_ISDBACTION;
+ if(tmpItem.szModule[0] == '$' && (tmpItem.szModule[1] == 'c' || tmpItem.szModule[1] == 'C'))
+ tmpItem.dwFlags |= BUTTON_ISCONTACTDBACTION;
+ tmpItem.uId = nextButtonID++;
+ }
+ }
+ else if(_stricmp(szBuffer, "Custom")) {
+ int i = 0;
+
+ while(top_buttons[i].id) {
+ if(!_stricmp(top_buttons[i].szIcoLibIcon, szBuffer)) {
+ tmpItem.uId = top_buttons[i].id;
+ tmpItem.dwFlags |= BUTTON_ISINTERNAL;
+ break;
+ }
+ i++;
+ }
+ }
+ GetPrivateProfileStringA(itemName, "PassContact", "None", szBuffer, 1000, file);
+ if(_stricmp(szBuffer, "None")) {
+ if(szBuffer[0] == 'w' || szBuffer[0] == 'W')
+ tmpItem.dwFlags |= BUTTON_PASSHCONTACTW;
+ else if(szBuffer[0] == 'l' || szBuffer[0] == 'L')
+ tmpItem.dwFlags |= BUTTON_PASSHCONTACTL;
+ }
+
+ GetPrivateProfileStringA(itemName, "Tip", "None", szBuffer, 1000, file);
+ if(strcmp(szBuffer, "None")) {
+ MultiByteToWideChar(cfg::dat.langPackCP, 0, szBuffer, -1, tmpItem.szTip, 256);
+ tmpItem.szTip[255] = 0;
+ }
+ else
+ tmpItem.szTip[0] = 0;
+
+ // create it
+
+ newItem = (TButtonItem *)malloc(sizeof(TButtonItem));
+ ZeroMemory(newItem, sizeof(TButtonItem));
+ if(CLUI::buttonItems == NULL) {
+ CLUI::buttonItems = newItem;
+ *newItem = tmpItem;
+ newItem->nextItem = 0;
+ }
+ else {
+ TButtonItem *curItem = CLUI::buttonItems;
+ while(curItem->nextItem)
+ curItem = curItem->nextItem;
+ *newItem = tmpItem;
+ newItem->nextItem = 0;
+ curItem->nextItem = newItem;
+ }
+ newItem->hWnd = CreateWindowEx(0, _T("CLCButtonClass"), _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 5, 5, pcli->hwndContactList, (HMENU)newItem->uId, g_hInst, NULL);
+
+ SendMessage(newItem->hWnd, BM_SETBTNITEM, 0, (LPARAM)newItem);
+ SendMessage(newItem->hWnd, BUTTONSETASFLATBTN, 0, 0);
+ SendMessage(newItem->hWnd, BUTTONSETASFLATBTN + 10, 0, 0);
+ if(newItem->dwFlags & BUTTON_ISTOGGLE)
+ SendMessage(newItem->hWnd, BUTTONSETASPUSHBTN, 0, 0);
+
+ if(newItem->szTip[0])
+ SendMessage(newItem->hWnd, BUTTONADDTOOLTIP, (WPARAM)newItem->szTip, 0);
+ return;
+}
+
+void SkinLoader::createImageItem(TImageItem *item, const char *fileName, HDC hdc)
+{
+ HBITMAP hbm = Gfx::loadPNG(fileName);
+ BITMAP bm;
+
+ if(hbm) {
+ item->hbm = hbm;
+ item->bf.BlendFlags = 0;
+ item->bf.BlendOp = AC_SRC_OVER;
+ item->bf.AlphaFormat = 0;
+
+ GetObject(hbm, sizeof(bm), &bm);
+ if(bm.bmBitsPixel == 32) {
+ Gfx::preMultiply(hbm, 1);
+ item->dwFlags |= IMAGE_PERPIXEL_ALPHA;
+ item->bf.AlphaFormat = AC_SRC_ALPHA;
+ }
+ item->width = bm.bmWidth;
+ item->height = bm.bmHeight;
+ item->inner_height = item->height - item->bTop - item->bBottom;
+ item->inner_width = item->width - item->bLeft - item->bRight;
+ if(item->bTop && item->bBottom && item->bLeft && item->bRight) {
+ item->dwFlags |= IMAGE_FLAG_DIVIDED;
+ if(item->inner_height <= 0 || item->inner_width <= 0) {
+ DeleteObject(hbm);
+ item->hbm = 0;
+ return;
+ }
+ }
+ item->hdc = CreateCompatibleDC(hdc);
+ item->hbmOld = reinterpret_cast<HBITMAP>(SelectObject(item->hdc, item->hbm));
+ }
+}
diff --git a/plugins/Clist_ng/SRC/statusbar.cpp b/plugins/Clist_ng/SRC/statusbar.cpp new file mode 100644 index 0000000000..c0bcbf61f6 --- /dev/null +++ b/plugins/Clist_ng/SRC/statusbar.cpp @@ -0,0 +1,202 @@ +/*
+* 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: statusbar.cpp 134 2010-10-01 10:23:10Z silvercircle $
+*
+* clist_ng status bar subclassing
+*/
+
+#include <commonheaders.h>
+
+static POINT ptMouse = {0};
+static RECT rcMouse = {0};
+static int timer_set = 0, tooltip_active = 0;
+extern HANDLE hStatusBarShowToolTipEvent, hStatusBarHideToolTipEvent;
+
+#define TIMERID_HOVER 1000
+
+LRESULT CALLBACK NewStatusBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_SETCURSOR:
+ {
+ POINT pt;
+
+ GetCursorPos(&pt);
+ SendMessage(GetParent(hwnd),msg,wParam,lParam);
+ if (pt.x == ptMouse.x && pt.y == ptMouse.y)
+ return 1;//return(TestCursorOnBorders());
+
+ ptMouse = pt;
+ if (tooltip_active){
+ KillTimer(hwnd, TIMERID_HOVER);
+ if(!NotifyEventHooks(hStatusBarHideToolTipEvent, 0, 0))
+ CallService("mToolTip/HideTip", 0, 0);
+ tooltip_active = FALSE;
+ }
+ KillTimer(hwnd, TIMERID_HOVER);
+ SetTimer(hwnd, TIMERID_HOVER, 750, 0);
+ break;
+ }
+ case WM_NCHITTEST:
+ {
+ LRESULT lr = SendMessage(GetParent(hwnd), WM_NCHITTEST, wParam, lParam);
+ if(lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT
+ || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT)
+ return HTTRANSPARENT;
+ break;
+ }
+ case WM_ERASEBKGND:
+ return(1);
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ KillTimer(hwnd, TIMERID_HOVER);
+ if(!NotifyEventHooks(hStatusBarHideToolTipEvent, 0, 0))
+ CallService("mToolTip/HideTip", 0, 0);
+ tooltip_active = FALSE;
+ break;
+
+ case WM_PAINT: {
+ if(cfg::shutDown)
+ return 0;
+
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ HDC hdcMem;
+ HANDLE hbp = 0;
+ RECT rcClient;
+ TStatusItem* item = NULL;
+ DRAWITEMSTRUCT dis = {0};
+ int nParts = 0;
+ int i;
+ HFONT hOldFont = 0;
+ HANDLE hTheme;
+ BYTE windowStyle = cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_DEFAULT);
+ LONG b_offset = (windowStyle == SETTING_WINDOWSTYLE_NOBORDER ? 2 : (windowStyle == SETTING_WINDOWSTYLE_THINBORDER ? 1 : 0));
+
+ GetClientRect(hwnd, &rcClient);
+ INIT_PAINT(hdc, rcClient, hdcMem);
+ SetBkMode(hdcMem, TRANSPARENT);
+ hOldFont = reinterpret_cast<HFONT>(SelectObject(hdcMem, GetStockObject(DEFAULT_GUI_FONT)));
+ Gfx::drawBGFromSurface(hwnd, rcClient, hdcMem);
+ item = &Skin::statusItems[ID_EXTBKSTATUSBAR];
+ if(!item->IGNORED) {
+ RECT rc = rcClient;
+ RGBQUAD* rgb = 0;
+ int iWidth;
+
+ Api::pfnGetBufferedPaintBits(hbp, &rgb, &iWidth);
+ AGGPaintHelper* ph = new AGGPaintHelper(hdcMem);
+ ph->aggctx->attach(rgb, iWidth, rc.bottom);
+ ph->current_shape = 0;
+
+ rc.left += item->MARGIN_LEFT;
+ rc.right -= item->MARGIN_RIGHT;
+ if(!Skin::metrics.fHaveFrame) {
+ rc.left += Skin::metrics.cFakeLeftBorder;
+ rc.right -= Skin::metrics.cFakeRightBorder;
+ }
+ rc.top += item->MARGIN_TOP;
+ rc.bottom -= item->MARGIN_BOTTOM;
+ Gfx::renderSkinItem(ph, item, &rc);
+ Gfx::setTextColor(item->TEXTCOLOR);
+ delete ph;
+ }else{
+ Gfx::setTextColor(GetSysColor(COLOR_BTNTEXT));
+ }
+ dis.hwndItem = hwnd;
+ dis.hDC = hdcMem;
+ dis.CtlType = 0;
+ nParts = SendMessage(hwnd, SB_GETPARTS, 0, 0);
+
+ hTheme = Api::pfnOpenThemeData(hwnd, L"BUTTON");
+ for(i = 0; i < nParts; i++) {
+ SendMessage(hwnd, SB_GETRECT, i, (LPARAM)&dis.rcItem);
+ OffsetRect(&dis.rcItem, 0, -b_offset);
+ dis.itemData = SendMessage(hwnd, SB_GETTEXTA, i, 0);
+ dis.CtlID = (UINT)hTheme;
+ SendMessage(pcli->hwndContactList, WM_DRAWITEM, 0, (LPARAM)&dis);
+ }
+ Api::pfnCloseThemeData(hTheme);
+ if(hOldFont)
+ SelectObject(hdcMem, hOldFont);
+ FINALIZE_PAINT(hbp, &rcClient, 0);
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+
+ case WM_SIZE:
+ return(DefWindowProc(hwnd, msg, wParam, lParam));
+
+ case WM_TIMER:
+ if(wParam == TIMERID_HOVER) {
+ POINT pt;
+ KillTimer(hwnd, TIMERID_HOVER);
+
+ GetCursorPos(&pt);
+ if (pt.x == ptMouse.x && pt.y == ptMouse.y) {
+ int i,nParts;
+ RECT rc;
+
+ ScreenToClient(hwnd, &pt);
+ nParts = SendMessage(hwnd, SB_GETPARTS, 0, 0);
+ for(i = 0; i < nParts; i++) {
+ SendMessage(hwnd, SB_GETRECT, i, (LPARAM)&rc);
+ if(PtInRect(&rc,pt)) {
+ ProtocolData *PD;
+ PD = (ProtocolData *)SendMessageA(hwnd, SB_GETTEXTA, i, 0);
+
+ if(PD) {
+ if(NotifyEventHooks(hStatusBarShowToolTipEvent, (WPARAM)PD->RealName, 0) > 0) // a plugin handled this event
+ tooltip_active = TRUE;
+ else if(cfg::getDword("mToolTip", "ShowStatusTip", 0)) {
+ CLCINFOTIP ti = {0};
+ BYTE isLocked = 0;
+ wchar_t szTipText[256], *szStatus = NULL;
+ WORD wStatus;
+
+ ti.cbSize = sizeof(ti);
+ ti.isTreeFocused = GetFocus() == pcli->hwndContactList ? 1 : 0;
+ wStatus = (WORD)CallProtoService(PD->RealName, PS_GETSTATUS, 0, 0);
+ isLocked = cfg::getByte(PD->RealName, "LockMainStatus", 0);
+ szStatus = pcli->pfnGetStatusModeDescription(wStatus, 0);
+ mir_snwprintf(szTipText, 256, L"<b>%s</b>: %s%s", PD->RealName, szStatus, isLocked ? L" (LOCKED)" : L"");
+ CallService("mToolTip/ShowTip", (WPARAM)szTipText, (LPARAM)&ti);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ return CallWindowProc(CLUI::OldStatusBarProc, hwnd, msg, wParam, lParam);
+}
diff --git a/plugins/Clist_ng/SRC/statusfloater.cpp b/plugins/Clist_ng/SRC/statusfloater.cpp new file mode 100644 index 0000000000..0d2353710a --- /dev/null +++ b/plugins/Clist_ng/SRC/statusfloater.cpp @@ -0,0 +1,1170 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+
+------------------------
+
+implements a simple status floater as a layered (and skinnable) window with
+a minimalistic UI (change status, access main menu). It also may hold a copy
+of the event area.
+
+Also implementes floating contacts (FLT_*() functions)
+
+*/
+
+#include <commonheaders.h>
+
+#define SNAP_SCREEN_TOLERANCE 10
+#define SNAP_FLT_TOLERANCE 10
+#define TOOLTIP_TIMER 1
+
+#define MS_TOOLTIP_SHOWTIP "mToolTip/ShowTip"
+#define MS_TOOLTIP_HIDETIP "mToolTip/HideTip"
+
+void FLT_Update(struct ClcData *dat, struct ClcContact *contact);
+void FLT_ShowHideAll(int showCmd);
+void FLT_SnapToEdges(HWND hwnd);
+void FLT_SnapToFloater(HWND hwnd);
+void PaintNotifyArea(HDC hDC, RECT *rc, HANDLE hTheme);
+
+HWND g_hwndSFL = 0;
+HDC g_SFLCachedDC = 0;
+HBITMAP g_SFLhbmOld = 0, g_SFLhbm = 0;
+struct ContactFloater *pFirstFloater = 0;
+BOOL hover = FALSE;
+BOOL tooltip = FALSE;
+int hTooltipTimer = 0;
+POINT start_pos;
+
+extern int g_padding_y;
+
+extern HWND g_hwndEventArea;
+extern HDC g_HDC;
+
+FLOATINGOPTIONS g_floatoptions;
+
+static UINT padctrlIDs[] = { IDC_FLT_PADLEFTSPIN, IDC_FLT_PADRIGHTSPIN, IDC_FLT_PADTOPSPIN,
+ IDC_FLT_PADBOTTOMSPIN, 0 };
+
+/*
+ * floating contacts support functions
+ * simple linked list of allocated ContactFloater* structs
+ */
+
+static struct ContactFloater *FLT_AddToList(struct ContactFloater *pFloater) {
+ struct ContactFloater *pCurrent = pFirstFloater;
+
+ if (!pFirstFloater) {
+ pFirstFloater = pFloater;
+ pFirstFloater->pNextFloater = NULL;
+ return pFirstFloater;
+ } else {
+ while (pCurrent->pNextFloater != 0)
+ pCurrent = pCurrent->pNextFloater;
+ pCurrent->pNextFloater = pFloater;
+ pFloater->pNextFloater = NULL;
+ return pCurrent;
+ }
+}
+
+static struct ContactFloater *FLT_RemoveFromList(struct ContactFloater *pFloater) {
+ struct ContactFloater *pCurrent = pFirstFloater;
+
+ if (pFloater == pFirstFloater) {
+ if(pFloater->pNextFloater != NULL)
+ pFirstFloater = pFloater->pNextFloater;
+ else
+ pFirstFloater = NULL;
+ return pFirstFloater;
+ }
+
+ do {
+ if (pCurrent->pNextFloater == pFloater) {
+ pCurrent->pNextFloater = pCurrent->pNextFloater->pNextFloater;
+ return 0;
+ }
+ } while (pCurrent = pCurrent->pNextFloater);
+
+ return NULL;
+}
+
+void FLT_SnapToEdges(HWND hwnd)
+{
+ RECT dr;
+ MONITORINFO monInfo;
+ RECT rcWindow;
+ HMONITOR curMonitor;
+
+ HWND onTop = g_floatoptions.dwFlags & FLT_ONTOP ? HWND_TOPMOST : HWND_NOTOPMOST;
+
+ curMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
+
+ monInfo.cbSize = sizeof(monInfo);
+ GetMonitorInfo(curMonitor, &monInfo);
+
+ dr = monInfo.rcWork;
+ GetWindowRect(hwnd, &rcWindow);
+
+ if (rcWindow.left < dr.left + SNAP_SCREEN_TOLERANCE){
+ SetWindowPos(hwnd, onTop, 0, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+ GetWindowRect(hwnd, &rcWindow);
+ }
+
+ if (rcWindow.top < dr.top + SNAP_SCREEN_TOLERANCE){
+ SetWindowPos(hwnd, onTop, rcWindow.left, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+ GetWindowRect(hwnd, &rcWindow);
+ }
+
+ if (rcWindow.right > dr.right - SNAP_SCREEN_TOLERANCE)
+ SetWindowPos(hwnd, onTop, dr.right - (rcWindow.right - rcWindow.left), rcWindow.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+
+ if (rcWindow.bottom > dr.bottom - SNAP_SCREEN_TOLERANCE)
+ SetWindowPos(hwnd, onTop, rcWindow.left, dr.bottom - (rcWindow.bottom - rcWindow.top), 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+}
+
+void FLT_SnapToFloater(HWND hwnd)
+{
+ struct ContactFloater *pCurrent = pFirstFloater;
+ RECT rcWindow, rcBase;
+ int minTop = 0xFFFFFF, minBottom = 0xFFFFFF, minRight = 0xFFFFFF, minLeft = 0xFFFFFF;
+ int posTop = 0, posBottom = 0, posRight = 0, posLeft = 0;
+ HWND onTop = g_floatoptions.dwFlags & FLT_ONTOP ? HWND_TOPMOST : HWND_NOTOPMOST;
+
+ GetWindowRect(hwnd, &rcBase);
+
+ //find the closest floater
+ while(pCurrent) {
+ GetWindowRect(pCurrent->hwnd, &rcWindow);
+ //top
+ if((rcWindow.top - rcBase.bottom > -SNAP_FLT_TOLERANCE) && (rcWindow.top - rcBase.bottom < minTop)){
+ posTop = rcWindow.top;
+ minTop = rcWindow.top - rcBase.bottom;
+ }
+ //bottom
+ if((rcBase.top - rcWindow.bottom > -SNAP_FLT_TOLERANCE) && (rcBase.top - rcWindow.bottom < minBottom)){
+ posBottom = rcWindow.bottom;
+ minBottom = rcBase.top - rcWindow.bottom;
+ }
+ //left
+ if((rcWindow.left - rcBase.right > -SNAP_FLT_TOLERANCE) && (rcWindow.left - rcBase.right < minLeft)){
+ posLeft= rcWindow.left;
+ minLeft = rcWindow.left - rcBase.right;
+ }
+ //right
+ if((rcBase.left - rcWindow.right > -SNAP_FLT_TOLERANCE) && (rcBase.left - rcWindow.right < minRight)){
+ posRight= rcWindow.right;
+ minRight = rcBase.left - rcWindow.right;
+ }
+ pCurrent = pCurrent->pNextFloater;
+ }
+
+ //snap to the closest floater if spacing is under SNAP_FLT_TOLERANCE
+ if (posTop && (rcBase.bottom > posTop - SNAP_FLT_TOLERANCE))
+ SetWindowPos(hwnd, onTop, rcBase.left, posTop - (rcBase.bottom - rcBase.top), 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+
+ if (posBottom && (rcBase.top < posBottom + SNAP_FLT_TOLERANCE))
+ SetWindowPos(hwnd, onTop, rcBase.left, posBottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+
+ if (posLeft && (rcBase.right > posLeft - SNAP_FLT_TOLERANCE))
+ SetWindowPos(hwnd, onTop, posLeft - (rcBase.right - rcBase.left), rcBase.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+
+ if (posRight && (rcBase.left < posRight + SNAP_FLT_TOLERANCE))
+ SetWindowPos(hwnd, onTop, posRight, rcBase.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+}
+
+/*
+ * dialog procedure for the floating contacts option page
+ */
+
+INT_PTR CALLBACK cfg::DlgProcFloatingContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ DWORD dwFlags = g_floatoptions.dwFlags;
+ int i = 0;
+
+ TranslateDialogDefault(hwndDlg);
+
+ CheckDlgButton(hwndDlg, IDC_FLT_ENABLED, g_floatoptions.enabled);
+ SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_ENABLED, 0);
+ CheckDlgButton(hwndDlg, IDC_FLT_SIMPLELAYOUT, dwFlags & FLT_SIMPLE);
+ SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_SIMPLELAYOUT, 0);
+ CheckDlgButton(hwndDlg, IDC_FLT_AVATARS, dwFlags & FLT_AVATARS);
+ CheckDlgButton(hwndDlg, IDC_FLT_DUALROWS, dwFlags & FLT_DUALROW);
+ CheckDlgButton(hwndDlg, IDC_FLT_EXTRAICONS, dwFlags & FLT_EXTRAICONS);
+ CheckDlgButton(hwndDlg, IDC_FLT_SYNCED, dwFlags & FLT_SYNCWITHCLIST);
+ CheckDlgButton(hwndDlg, IDC_FLT_AUTOHIDE, dwFlags & FLT_AUTOHIDE);
+ CheckDlgButton(hwndDlg, IDC_FLT_SNAP, dwFlags & FLT_SNAP);
+ CheckDlgButton(hwndDlg, IDC_FLT_BORDER, dwFlags & FLT_BORDER);
+ CheckDlgButton(hwndDlg, IDC_FLT_ONTOP, dwFlags & FLT_ONTOP);
+ SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_BORDER, 0);
+ CheckDlgButton(hwndDlg, IDC_FLT_FILLSTD, dwFlags & FLT_FILLSTDCOLOR);
+
+ if (ServiceExists(MS_TOOLTIP_SHOWTIP))
+ {
+ CheckDlgButton(hwndDlg, IDC_FLT_SHOWTOOLTIPS, dwFlags & FLT_SHOWTOOLTIPS);
+ SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_SHOWTOOLTIPS, 0);
+ CheckDlgButton(hwndDlg, IDC_FLT_DEFHOVERTIME, g_floatoptions.def_hover_time);
+ SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_DEFHOVERTIME, 0);
+ }
+ else
+ {
+ CheckDlgButton(hwndDlg, IDC_FLT_SHOWTOOLTIPS, 0);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_SHOWTOOLTIPS, 0);
+ }
+
+ for(i = 0; padctrlIDs[i] != 0; i++)
+ SendDlgItemMessage(hwndDlg, padctrlIDs[i], UDM_SETRANGE, 0, MAKELONG(20, 0));
+ SendDlgItemMessage(hwndDlg, IDC_FLT_WIDTHSPIN, UDM_SETRANGE, 0, MAKELONG(200, 50));
+ SendDlgItemMessage(hwndDlg, IDC_FLT_HOVERTIMESPIN, UDM_SETRANGE, 0, MAKELONG(5000, 1));
+
+
+ SendDlgItemMessage(hwndDlg, IDC_FLT_PADLEFTSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_left);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_PADRIGHTSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_right);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_PADTOPSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_top);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_PADBOTTOMSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_top);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_WIDTHSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.width);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_HOVERTIMESPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.hover_time);
+
+ SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_SETRANGE, FALSE, MAKELONG(1, 255));
+ SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_SETPOS, TRUE, g_floatoptions.act_trans);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_SETRANGE, FALSE, MAKELONG(1, 255));
+ SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_SETPOS, TRUE, g_floatoptions.trans);
+ SendMessage(hwndDlg, WM_HSCROLL, 0, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_FLT_BORDERCOLOUR, CPM_SETDEFAULTCOLOUR, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_BORDERCOLOUR, CPM_SETCOLOUR, 0, g_floatoptions.border_colour);
+
+ FLT_ShowHideAll(SW_SHOWNOACTIVATE);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_FLT_ENABLED:
+ {
+ int isEnabled = IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED);
+ int isSimple = IsDlgButtonChecked(hwndDlg, IDC_FLT_SIMPLELAYOUT);
+ int isBorder = IsDlgButtonChecked(hwndDlg, IDC_FLT_BORDER);
+ int isTooltip = IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS);
+ int isDefHoverTime = IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME);
+
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_SIMPLELAYOUT, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_SYNCED, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_AUTOHIDE, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_SNAP, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_ACTIVEOPACITY, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_OPACITY, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_PADLEFTSPIN, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_PADRIGHTSPIN, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_PADTOPSPIN, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_PADLEFT, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_PADRIGHT, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_PADTOP, isEnabled);
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_FLT_PADBOTTOMSPIN), isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_PADBOTTOM, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_WIDTHSPIN, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_WIDTH, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_BORDER, isEnabled);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_BORDERCOLOUR, isEnabled & isBorder);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_SHOWTOOLTIPS, isEnabled & ServiceExists(MS_TOOLTIP_SHOWTIP));
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_DEFHOVERTIME, isEnabled & isTooltip);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIME, isEnabled & isTooltip & !isDefHoverTime);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIMESPIN, isEnabled & isTooltip & !isDefHoverTime);
+
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_AVATARS, isEnabled & !isSimple);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_EXTRAICONS, isEnabled & !isSimple);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_DUALROWS, isEnabled & !isSimple);
+ }
+ break;
+ case IDC_FLT_SIMPLELAYOUT:
+ {
+ if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED)){
+ int isSimple = IsDlgButtonChecked(hwndDlg, IDC_FLT_SIMPLELAYOUT);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_AVATARS, !isSimple);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_EXTRAICONS, !isSimple);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_DUALROWS, !isSimple);
+ }
+ }
+ break;
+ case IDC_FLT_BORDER:
+ {
+ if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED)){
+ int isBorder = IsDlgButtonChecked(hwndDlg, IDC_FLT_BORDER);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_BORDERCOLOUR, isBorder);
+ }
+ }
+ break;
+ case IDC_FLT_SHOWTOOLTIPS:
+ {
+ if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED)){
+ int isTooltip = IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS);
+ int isDefHoverTime = IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_DEFHOVERTIME, isTooltip);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIME, isTooltip & !isDefHoverTime);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIMESPIN, isTooltip & !isDefHoverTime);
+ }
+ }
+ break;
+ case IDC_FLT_DEFHOVERTIME:
+ {
+ if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED) && IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS)){
+ int isDefHoverTime = IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIME, !isDefHoverTime);
+ Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIMESPIN, !isDefHoverTime);
+ }
+ }
+ break;
+
+ case IDC_FLT_PADTOP:
+ {
+ if(HIWORD(wParam) == EN_CHANGE){
+ int value = SendDlgItemMessage(hwndDlg, IDC_FLT_PADTOPSPIN, UDM_GETPOS, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_FLT_PADBOTTOMSPIN, UDM_SETPOS, 0, (LPARAM)value);
+ }
+ }
+ break;
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_HSCROLL:
+ {
+ char str[10];
+ wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_GETPOS, 0, 0) / 255);
+ SetDlgItemTextA(hwndDlg, IDC_FLT_ACTIVEOPACITYVALUE, str);
+ wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_GETPOS, 0, 0) / 255);
+ SetDlgItemTextA(hwndDlg, IDC_FLT_OPACITYVALUE, str);
+
+ if (lParam)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ g_floatoptions.enabled = IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED) ? 1 : 0;
+ g_floatoptions.dwFlags = 0;
+
+ if(IsDlgButtonChecked(hwndDlg, IDC_FLT_SIMPLELAYOUT))
+ g_floatoptions.dwFlags = FLT_SIMPLE;
+
+ g_floatoptions.dwFlags |= (IsDlgButtonChecked(hwndDlg, IDC_FLT_AVATARS) ? FLT_AVATARS : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_DUALROWS) ? FLT_DUALROW : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_EXTRAICONS) ? FLT_EXTRAICONS : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_SYNCED) ? FLT_SYNCWITHCLIST : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_AUTOHIDE) ? FLT_AUTOHIDE : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_SNAP) ? FLT_SNAP : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_BORDER) ? FLT_BORDER : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_FILLSTD) ? FLT_FILLSTDCOLOR : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_ONTOP) ? FLT_ONTOP : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS) ? FLT_SHOWTOOLTIPS : 0);
+
+ g_floatoptions.act_trans = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_GETPOS, 0, 0);
+ g_floatoptions.trans = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_GETPOS, 0, 0);
+ g_floatoptions.pad_left = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADLEFTSPIN, UDM_GETPOS, 0, 0);
+ g_floatoptions.pad_right = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADRIGHTSPIN, UDM_GETPOS, 0, 0);
+ g_floatoptions.pad_top = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADTOPSPIN, UDM_GETPOS, 0, 0);
+ g_floatoptions.pad_bottom = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADBOTTOMSPIN, UDM_GETPOS, 0, 0);
+ g_floatoptions.width = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_WIDTHSPIN, UDM_GETPOS, 0, 0);
+ g_floatoptions.border_colour = SendDlgItemMessage(hwndDlg, IDC_FLT_BORDERCOLOUR, CPM_GETCOLOUR, 0, 0);
+
+ g_floatoptions.def_hover_time= IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME) ? 1 : 0;
+ if (g_floatoptions.def_hover_time)
+ g_floatoptions.hover_time = cfg::getWord("CLC", "InfoTipHoverTime", 200);
+ else
+ g_floatoptions.hover_time = (WORD)SendDlgItemMessage(hwndDlg, IDC_FLT_HOVERTIMESPIN, UDM_GETPOS, 0, 0);
+
+ FLT_WriteOptions();
+ FLT_RefreshAll();
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void FLT_ReadOptions()
+{
+ DWORD dwPad;
+
+ ZeroMemory(&g_floatoptions, sizeof(FLOATINGOPTIONS));
+
+ g_floatoptions.enabled = cfg::getByte("CList", "flt_enabled", 0);
+ g_floatoptions.dwFlags = cfg::getDword("CList", "flt_flags", FLT_SIMPLE);
+ dwPad = cfg::getDword("CList", "flt_padding", 0);
+
+ g_floatoptions.pad_top = LOBYTE(LOWORD(dwPad));
+ g_floatoptions.pad_right = HIBYTE(LOWORD(dwPad));
+ g_floatoptions.pad_bottom = LOBYTE(HIWORD(dwPad));
+ g_floatoptions.pad_left = HIBYTE(HIWORD(dwPad));
+
+ g_floatoptions.width = cfg::getDword("CList", "flt_width", 100);
+ g_floatoptions.act_trans = cfg::getByte("CList", "flt_acttrans", 255);
+ g_floatoptions.trans = cfg::getByte("CList", "flt_trans", 255);
+ g_floatoptions.border_colour = cfg::getDword("CList", "flt_bordercolour", 0);
+ g_floatoptions.def_hover_time = cfg::getByte("CList", "flt_defhovertime", 1);
+
+ if (g_floatoptions.def_hover_time)
+ g_floatoptions.hover_time = cfg::getWord("CLC", "InfoTipHoverTime", 200);
+ else
+ g_floatoptions.hover_time = cfg::getWord("CList", "flt_hovertime", 200);
+
+}
+
+void FLT_WriteOptions()
+{
+ DWORD dwPad;
+
+ cfg::writeByte("CList", "flt_enabled", g_floatoptions.enabled);
+ cfg::writeDword("CList", "flt_flags", g_floatoptions.dwFlags);
+ dwPad = MAKELONG(MAKEWORD(g_floatoptions.pad_top, g_floatoptions.pad_right),
+ MAKEWORD(g_floatoptions.pad_bottom, g_floatoptions.pad_left));
+ cfg::writeDword("CList", "flt_padding", dwPad);
+ cfg::writeDword("CList", "flt_width", g_floatoptions.width);
+ cfg::writeByte("CList", "flt_acttrans", g_floatoptions.act_trans);
+ cfg::writeByte("CList", "flt_trans", g_floatoptions.trans);
+ cfg::writeDword("CList", "flt_bordercolour", g_floatoptions.border_colour);
+ cfg::writeByte("CList", "flt_defhovertime", g_floatoptions.def_hover_time);
+ if (!g_floatoptions.def_hover_time)
+ cfg::writeWord("CList", "flt_hovertime", g_floatoptions.hover_time);
+
+}
+
+LRESULT CALLBACK StatusFloaterClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_DESTROY:
+ Utils_SaveWindowPosition(hwnd, 0, "CLUI", "sfl");
+ if(g_SFLCachedDC) {
+ SelectObject(g_SFLCachedDC, g_SFLhbmOld);
+ DeleteObject(g_SFLhbm);
+ DeleteDC(g_SFLCachedDC);
+ g_SFLCachedDC = 0;
+ }
+ break;
+ case WM_ERASEBKGND:
+ return TRUE;
+ case WM_PAINT:
+ {
+ HDC hdc;
+ PAINTSTRUCT ps;
+
+ hdc = BeginPaint(hwnd, &ps);
+ ps.fErase = FALSE;
+ EndPaint(hwnd, &ps);
+ return TRUE;
+ }
+ case WM_LBUTTONDOWN:
+ {
+ POINT ptMouse;
+ RECT rcWindow;
+
+ GetCursorPos(&ptMouse);
+ GetWindowRect(hwnd, &rcWindow);
+ rcWindow.right = rcWindow.left + 25;
+ if(!PtInRect(&rcWindow, ptMouse))
+ return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(ptMouse.x, ptMouse.y));
+ break;
+ }
+ case WM_LBUTTONUP:
+ {
+ HMENU hmenu = Menu_GetStatusMenu();
+ RECT rcWindow;
+ POINT pt;
+
+ GetCursorPos(&pt);
+ GetWindowRect(hwnd, &rcWindow);
+ if(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS) {
+ if(pt.y > rcWindow.top + ((rcWindow.bottom - rcWindow.top) / 2))
+ SendMessage(g_hwndEventArea, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0);
+ else
+ TrackPopupMenu(hmenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, pcli->hwndContactList, NULL);
+ }
+ else
+ TrackPopupMenu(hmenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, pcli->hwndContactList, NULL);
+ return 0;
+ }
+ case WM_CONTEXTMENU:
+ {
+ HMENU hmenu = Menu_GetMainMenu();
+ RECT rcWindow;
+
+ GetWindowRect(hwnd, &rcWindow);
+ TrackPopupMenu(hmenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, pcli->hwndContactList, NULL);
+ return 0;
+ }
+
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+void CALLBACK ShowTooltip(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){
+ struct ContactFloater *pCurrent = pFirstFloater;
+ POINT pt;
+ CLCINFOTIP ti = {0};
+
+ KillTimer(hwnd, TOOLTIP_TIMER);
+ hTooltipTimer = 0;
+
+ GetCursorPos(&pt);
+ if ((abs(pt.x - start_pos.x) > 3) && (abs(pt.y - start_pos.y) > 3)) return;
+
+ while(pCurrent->hwnd != hwnd)
+ pCurrent = pCurrent->pNextFloater;
+
+ ti.cbSize = sizeof(ti);
+ ti.isGroup = 0;
+ ti.isTreeFocused = 0;
+ ti.hItem = (HANDLE)pCurrent->hContact;
+ ti.ptCursor = pt;
+ CallService(MS_TOOLTIP_SHOWTIP, 0, (LPARAM)&ti);
+ tooltip = TRUE;
+}
+
+LRESULT CALLBACK ContactFloaterClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ INT_PTR iEntry = GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ struct TExtraCache *centry = NULL;
+
+ if(iEntry >= 0 && iEntry < cfg::nextCacheEntry)
+ centry = &cfg::eCache[iEntry];
+
+ switch(msg) {
+ case WM_NCCREATE:
+ {
+ CREATESTRUCT *cs = (CREATESTRUCT *)lParam;
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams);
+ iEntry = (int)cs->lpCreateParams;
+ if(iEntry >= 0 && iEntry < cfg::nextCacheEntry)
+ centry = &cfg::eCache[iEntry];
+ return TRUE;
+ }
+ case WM_DESTROY:
+ if(centry) {
+ SelectObject(centry->floater->hdc, centry->floater->hbmOld);
+ DeleteObject(centry->floater->hbm);
+ DeleteDC(centry->floater->hdc);
+ FLT_RemoveFromList(centry->floater);
+ free(centry->floater);
+ centry->floater = 0;
+ Utils_SaveWindowPosition(hwnd, centry->hContact, "CList", "flt");
+ break;
+ }
+ case WM_ERASEBKGND:
+ return TRUE;
+ case WM_PAINT:
+ {
+ HDC hdc;
+ PAINTSTRUCT ps;
+
+ hdc = BeginPaint(hwnd, &ps);
+ ps.fErase = FALSE;
+ EndPaint(hwnd, &ps);
+ return TRUE;
+ }
+ case WM_LBUTTONDBLCLK:
+ if(centry)
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)centry->hContact, 0);
+ return 0;
+ case WM_LBUTTONDOWN:
+ {
+ POINT ptMouse;
+ RECT rcWindow;
+
+ GetCursorPos(&ptMouse);
+ GetWindowRect(hwnd, &rcWindow);
+ rcWindow.right = rcWindow.left + 25;
+ if(!PtInRect(&rcWindow, ptMouse))
+ return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(ptMouse.x, ptMouse.y));
+ break;
+ }
+ case WM_MOUSEMOVE:
+ if(!hover) {
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags = TME_HOVER | TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ tme.dwHoverTime = 5;
+ TrackMouseEvent(&tme);
+ hover = TRUE;
+ }
+ if ( ServiceExists( MS_TOOLTIP_SHOWTIP )) {
+ if ((g_floatoptions.dwFlags & FLT_SHOWTOOLTIPS) && !tooltip) {
+ GetCursorPos(&start_pos);
+ if (hTooltipTimer) KillTimer(hwnd, TOOLTIP_TIMER);
+ hTooltipTimer = SetTimer(hwnd, TOOLTIP_TIMER, g_floatoptions.hover_time, ShowTooltip);
+ }
+ }
+
+ return FALSE;
+
+ case WM_MOUSEHOVER:
+ {
+ struct ClcContact *contact = NULL;
+ struct ContactFloater *pCurrent = pFirstFloater;
+ int oldTrans = g_floatoptions.trans;
+
+ while(pCurrent->hwnd != hwnd)
+ pCurrent = pCurrent->pNextFloater;
+
+ if(CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)pCurrent->hContact, &contact, NULL, 0)){
+ g_floatoptions.trans = g_floatoptions.act_trans;
+ FLT_Update(cfg::clcdat, contact);
+ g_floatoptions.trans = oldTrans;
+ }
+
+ break;
+ }
+ case WM_MOUSELEAVE:
+ {
+ struct ClcContact *contact = NULL;
+ struct ContactFloater *pCurrent = pFirstFloater;
+
+ while(pCurrent->hwnd != hwnd)
+ pCurrent = pCurrent->pNextFloater;
+
+ if(CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)pCurrent->hContact, &contact, NULL, 0))
+ FLT_Update(cfg::clcdat, contact);
+
+ if (hTooltipTimer)
+ {
+ KillTimer(hwnd, TOOLTIP_TIMER);
+ hTooltipTimer = 0;
+ }
+
+ if (tooltip) CallService(MS_TOOLTIP_HIDETIP, 0, 0);
+
+ hover = FALSE;
+ tooltip = FALSE;
+
+
+ break;
+ }
+
+ case WM_MOVE:
+ {
+ if (g_floatoptions.dwFlags & FLT_SNAP)
+ FLT_SnapToEdges(hwnd);
+
+ if(GetKeyState(VK_CONTROL) < 0)
+ FLT_SnapToFloater(hwnd);
+
+ break;
+ }
+ case WM_MEASUREITEM:
+ return(Menu_MeasureItem((LPMEASUREITEMSTRUCT)lParam));
+ case WM_DRAWITEM:
+ return(Menu_DrawItem((LPDRAWITEMSTRUCT)lParam));
+ case WM_COMMAND:
+ return(CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKELONG(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)centry->hContact));
+ case WM_CONTEXTMENU:
+ {
+ if(centry) {
+ HMENU hContactMenu = Menu_BuildContactMenu(centry->hContact);
+ RECT rcWindow;
+
+ GetWindowRect(hwnd, &rcWindow);
+ TrackPopupMenu(hContactMenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, hwnd, NULL);
+ DestroyMenu(hContactMenu);
+ return 0;
+ }
+ break;
+ }
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+void SFL_RegisterWindowClass()
+{
+ WNDCLASS wndclass;
+
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = StatusFloaterClassProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = 0;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH) (COLOR_3DFACE);
+ wndclass.lpszMenuName = 0;
+ wndclass.lpszClassName = _T("StatusFloaterClass");
+ RegisterClass(&wndclass);
+
+ wndclass.style = CS_DBLCLKS;
+ wndclass.lpszClassName = _T("ContactFloaterClass");
+ wndclass.lpfnWndProc = ContactFloaterClassProc;
+ RegisterClass(&wndclass);
+}
+
+void SFL_UnregisterWindowClass()
+{
+ UnregisterClass(_T("StatusFloaterClass"), g_hInst);
+ UnregisterClass(_T("ContactFloaterClass"), g_hInst);
+}
+
+void SFL_Destroy()
+{
+ if(g_hwndSFL)
+ DestroyWindow(g_hwndSFL);
+ g_hwndSFL = 0;
+}
+
+static HICON sfl_hIcon = (HICON)-1;
+static int sfl_iIcon = -1;
+static wchar_t sfl_statustext[100] = _T("");
+
+void SFL_Update(HICON hIcon, int iIcon, HIMAGELIST hIml, const wchar_t *szText, BOOL refresh)
+{
+ RECT rcClient, rcWindow;
+ POINT ptDest, ptSrc = {0};
+ SIZE szDest, szT;
+ BLENDFUNCTION bf = {0};
+ HFONT hOldFont;
+ TStatusItem *item = &Skin::statusItems[ID_EXTBKSTATUSFLOATER];
+ RECT rcStatusArea;
+ LONG cy;
+
+ if(g_hwndSFL == 0)
+ return;
+
+ GetClientRect(g_hwndSFL, &rcClient);
+ GetWindowRect(g_hwndSFL, &rcWindow);
+
+ ptDest.x = rcWindow.left;
+ ptDest.y = rcWindow.top;
+ szDest.cx = rcWindow.right - rcWindow.left;
+ szDest.cy = rcWindow.bottom - rcWindow.top;
+
+ if(item->IGNORED)
+ Gfx::setTextColor(GetSysColor(COLOR_BTNTEXT));
+ else {
+ FillRect(g_SFLCachedDC, &rcClient, GetSysColorBrush(COLOR_3DFACE));
+ Gfx::renderSkinItem(g_SFLCachedDC, &rcClient, item->imageItem);
+ Gfx::setTextColor(item->TEXTCOLOR);
+ }
+ bf.BlendOp = AC_SRC_OVER;
+ bf.AlphaFormat = AC_SRC_ALPHA;
+ bf.SourceConstantAlpha = item->IGNORED ? 255 : percent_to_byte(item->ALPHA);
+
+ rcStatusArea = rcClient;
+
+ if(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS)
+ rcStatusArea.bottom = 20;
+
+ cy = rcStatusArea.bottom - rcStatusArea.top;
+
+ if(szText != NULL && refresh) {
+ _tcsncpy(sfl_statustext, szText, 100);
+ sfl_statustext[99] = 0;
+ }
+
+ if(!hIcon) {
+ HICON p_hIcon;
+
+ if(refresh)
+ sfl_iIcon = iIcon;
+ if(sfl_iIcon != -1) {
+ p_hIcon = ImageList_ExtractIcon(0, CLC::hClistImages, sfl_iIcon);
+ DrawIconEx(g_SFLCachedDC, 5, (cy - 16) / 2, p_hIcon, 16, 16, 0, 0, DI_NORMAL);
+ DestroyIcon(p_hIcon);
+ }
+ }
+ else {
+ if(refresh)
+ sfl_hIcon = hIcon;
+ if(sfl_hIcon != (HICON)-1)
+ DrawIconEx(g_SFLCachedDC, 5, (cy - 16) / 2, sfl_hIcon, 16, 16, 0, 0, DI_NORMAL);
+ }
+
+ hOldFont = reinterpret_cast<HFONT>(SelectObject(g_SFLCachedDC, GetStockObject(DEFAULT_GUI_FONT)));
+ SetBkMode(g_SFLCachedDC, TRANSPARENT);
+ GetTextExtentPoint32(g_SFLCachedDC, sfl_statustext, lstrlen(sfl_statustext), &szT);
+ TextOut(g_SFLCachedDC, 24, (cy - szT.cy) / 2, sfl_statustext, lstrlen(sfl_statustext));
+
+ if(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS) {
+ RECT rcNA = rcClient;
+
+ rcNA.top = 18;
+ PaintNotifyArea(g_SFLCachedDC, &rcNA, 0);
+ }
+
+ SelectObject(g_SFLCachedDC, hOldFont);
+ UpdateLayeredWindow(g_hwndSFL, 0, &ptDest, &szDest, g_SFLCachedDC, &ptSrc, 0, &bf, ULW_ALPHA);
+}
+
+/*
+ * set the floater
+ * mode = 0/1 forced hide/show
+ * OR -1 to set it depending on the clist state (visible/hidden) (this is actually reversed, because the function
+ * is called *before* the clist is shown or hidden)
+ */
+
+void SFL_SetState(int uMode)
+{
+ BYTE bClistState;
+
+ if(g_hwndSFL == 0 || !(cfg::dat.bUseFloater & CLUI_USE_FLOATER))
+ return;
+
+ if(uMode == -1) {
+ if(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE) {
+ bClistState = cfg::getByte("CList", "State", SETTING_STATE_NORMAL);
+ ShowWindow(g_hwndSFL, bClistState == SETTING_STATE_NORMAL ? SW_SHOW : SW_HIDE);
+ }
+ else
+ ShowWindow(g_hwndSFL, SW_SHOW);
+ }
+ else
+ ShowWindow(g_hwndSFL, uMode ? SW_SHOW : SW_HIDE);
+}
+
+// XXX improve size calculations for the floater window.
+
+void SFL_SetSize()
+{
+ HDC hdc;
+ LONG lWidth;
+ RECT rcWindow;
+ SIZE sz = {0};
+ wchar_t *szStatusMode;
+ HFONT oldFont;
+ int i;
+
+ GetWindowRect(g_hwndSFL, &rcWindow);
+ lWidth = rcWindow.right - rcWindow.left;
+
+ hdc = GetDC(g_hwndSFL);
+ oldFont = reinterpret_cast<HFONT>(SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)));
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ szStatusMode = TranslateTS(pcli->pfnGetStatusModeDescription(i, 0));
+ GetTextExtentPoint32W(hdc, szStatusMode, lstrlenW(szStatusMode), &sz);
+ lWidth = max(lWidth, sz.cx + 16 + 8);
+ }
+ SetWindowPos(g_hwndSFL, g_floatoptions.dwFlags & FLT_ONTOP ? HWND_TOPMOST : HWND_NOTOPMOST, rcWindow.left, rcWindow.top, lWidth, max(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS ? 36 : 20, sz.cy + 4), SWP_SHOWWINDOW);
+ GetWindowRect(g_hwndSFL, &rcWindow);
+
+ if(g_SFLCachedDC) {
+ SelectObject(g_SFLCachedDC, g_SFLhbmOld);
+ DeleteObject(g_SFLhbm);
+ DeleteDC(g_SFLCachedDC);
+ g_SFLCachedDC = 0;
+ }
+
+ g_SFLCachedDC = CreateCompatibleDC(hdc);
+ g_SFLhbm = Gfx::createRGBABitmap(lWidth, rcWindow.bottom - rcWindow.top);
+ g_SFLhbmOld = reinterpret_cast<HBITMAP>(SelectObject(g_SFLCachedDC, g_SFLhbm));
+
+ ReleaseDC(g_hwndSFL, hdc);
+ CluiProtocolStatusChanged(0, 0);
+}
+
+void SFL_Create()
+{
+ if(g_hwndSFL == 0 && cfg::dat.bUseFloater & CLUI_USE_FLOATER)
+ g_hwndSFL = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, _T("StatusFloaterClass"), _T("sfl"), WS_VISIBLE, 0, 0, 0, 0, 0, 0, g_hInst, 0);
+ else
+ return;
+
+ SetWindowLong(g_hwndSFL, GWL_STYLE, GetWindowLong(g_hwndSFL, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW));
+
+ Utils_RestoreWindowPosition(g_hwndSFL, 0, "CLUI", "sfl");
+ SFL_SetSize();
+}
+
+void FLT_SetSize(struct TExtraCache *centry, LONG width, LONG height)
+{
+ HDC hdc;
+ RECT rcWindow;
+ HFONT oldFont;
+ int flags = SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOACTIVATE;
+
+ int iVis = pcli->pfnGetWindowVisibleState(pcli->hwndContactList, 0, 0);
+ if((g_floatoptions.dwFlags & FLT_AUTOHIDE) && (iVis == 2 || iVis == 4)) //2 = GWVS_VISIBLE, 4 = GWVS_PARTIALLY_COVERED
+ flags = SWP_NOMOVE | SWP_NOACTIVATE;
+
+ if(centry->floater) {
+ hdc = GetDC(centry->floater->hwnd);
+ oldFont = reinterpret_cast<HFONT>(SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)));
+
+ SetWindowPos(centry->floater->hwnd, g_floatoptions.dwFlags & FLT_ONTOP ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, width, height, flags);
+ GetWindowRect(centry->floater->hwnd, &rcWindow);
+
+ if(centry->floater->hdc) {
+ SelectObject(centry->floater->hdc, centry->floater->hbmOld);
+ DeleteObject(centry->floater->hbm);
+ DeleteDC(centry->floater->hdc);
+ centry->floater->hdc = 0;
+ }
+
+ centry->floater->hdc = CreateCompatibleDC(hdc);
+ centry->floater->hbm = Gfx::createRGBABitmap(width, rcWindow.bottom - rcWindow.top);
+ centry->floater->hbmOld= reinterpret_cast<HBITMAP>(SelectObject(centry->floater->hdc, centry->floater->hbm));
+
+ ReleaseDC(centry->floater->hwnd, hdc);
+ }
+}
+
+void FLT_Create(int iEntry)
+{
+ struct TExtraCache *centry = NULL;
+
+ if(iEntry >= 0 && iEntry < cfg::nextCacheEntry) {
+ struct ClcContact *contact = NULL;
+ struct ClcGroup *group = NULL;
+ centry = &cfg::eCache[iEntry];
+ if(centry->floater == 0) {
+ centry->floater = (struct ContactFloater *)malloc(sizeof(struct ContactFloater));
+ if(centry->floater == NULL)
+ return;
+ FLT_AddToList(centry->floater);
+ centry->floater->hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, _T("ContactFloaterClass"), _T("sfl"), WS_VISIBLE, 0, 0, 0, 0, 0, 0, g_hInst, (LPVOID)iEntry);
+ centry->floater->hContact = centry->hContact;
+ }
+ else if(centry->floater != NULL) {
+ ShowWindow(centry->floater->hwnd, SW_SHOWNOACTIVATE);
+ return;
+ }
+
+ SetWindowLong(centry->floater->hwnd, GWL_STYLE, GetWindowLong(centry->floater->hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW));
+
+ if(Utils_RestoreWindowPosition(centry->floater->hwnd, centry->hContact, "CList", "flt"))
+ if(Utils_RestoreWindowPositionNoMove(centry->floater->hwnd, centry->hContact, "CList", "flt"))
+ SetWindowPos(centry->floater->hwnd, 0, 50, 50, 150, 30, SWP_NOZORDER | SWP_NOACTIVATE);
+
+ //FLT_SetSize(centry, 100, 20);
+ ShowWindow(centry->floater->hwnd, SW_SHOWNOACTIVATE);
+ if(CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)centry->hContact, &contact, &group, 0)) {
+ if(contact)
+ FLT_Update(cfg::clcdat, contact);
+ }
+ }
+}
+
+extern HDC hdcTempAV;
+extern HBITMAP hbmTempAV, hbmTempOldAV;
+extern LONG g_maxAV_X, g_maxAV_Y;
+
+void FLT_Update(struct ClcData *dat, struct ClcContact *contact)
+{
+ RECT rcClient, rcWindow;
+ POINT ptDest, ptSrc = {0};
+ SIZE szDest;
+ BLENDFUNCTION bf = {0};
+ HWND hwnd;
+ HDC hdc;
+ ClcGroup *group = NULL;
+ ClcContact *newContact = NULL;
+ HBRUSH hbrBorder;
+ float greyLevel;
+
+ if(contact == NULL || dat == NULL)
+ return;
+
+ if(contact->extraCacheEntry < 0 || contact->extraCacheEntry >= cfg::nextCacheEntry)
+ return;
+
+ if(cfg::eCache[contact->extraCacheEntry].floater == NULL)
+ return;
+
+ FLT_SetSize(&cfg::eCache[contact->extraCacheEntry], g_floatoptions.width, RowHeight::getFloatingRowHeight(dat, pcli->hwndContactTree, contact, g_floatoptions.dwFlags) + (2*g_floatoptions.pad_top));
+
+ hwnd = cfg::eCache[contact->extraCacheEntry].floater->hwnd;
+ hdc = cfg::eCache[contact->extraCacheEntry].floater->hdc;
+
+ if(hwnd == 0)
+ return;
+
+ GetClientRect(hwnd, &rcClient);
+ GetWindowRect(hwnd, &rcWindow);
+
+ ptDest.x = rcWindow.left;
+ ptDest.y = rcWindow.top;
+ szDest.cx = rcWindow.right - rcWindow.left;
+ szDest.cy = rcWindow.bottom - rcWindow.top;
+
+ /*
+ * fill with a DESATURATED representation of the clist bg color and use this later as a color key
+ */
+
+ greyLevel = (float)(GetRValue(cfg::clcdat->bkColour) * 0.299 + GetGValue(cfg::clcdat->bkColour) * 0.587 + GetBValue(cfg::clcdat->bkColour) * 0.144);
+ if (greyLevel > 255)
+ greyLevel = 255;
+
+ SetBkMode(hdc, TRANSPARENT);
+
+ if(CLC::findItem(pcli->hwndContactTree, dat, (HANDLE)contact->hContact, &newContact, &group, 0)) {
+ DWORD oldFlags = cfg::dat.dwFlags;
+ BYTE oldPadding = cfg::dat.avatarPadding;
+ DWORD oldExtraImageMask = cfg::eCache[contact->extraCacheEntry].dwXMask;
+
+ int oldLeftMargin = dat->leftMargin;
+ int oldRightMargin = dat->rightMargin;
+
+ dat->leftMargin = g_floatoptions.pad_left;
+ dat->rightMargin = g_floatoptions.pad_right;
+
+ g_HDC = hdc;
+
+ hdcTempAV = CreateCompatibleDC(g_HDC);
+ hbmTempAV = CreateCompatibleBitmap(g_HDC, g_maxAV_X, g_maxAV_Y);
+ hbmTempOldAV = reinterpret_cast<HBITMAP>(SelectObject(hdcTempAV, hbmTempAV));
+
+ g_padding_y = g_floatoptions.pad_top;
+
+ CLCPaintHelper ph(pcli->hwndContactTree, dat, 0, &rcClient, 0, 0, -4);
+ ph.setHDC(hdc);
+
+ if(g_floatoptions.dwFlags & FLT_SIMPLE) {
+ ph.fAvatar = ph.fSecondLine = false;
+ cfg::dat.dwFlags &= ~(CLUI_SHOWCLIENTICONS | CLUI_SHOWVISI);
+ cfg::eCache[contact->extraCacheEntry].dwXMask = 0;
+ }
+ else{
+ ph.fAvatar = g_floatoptions.dwFlags & FLT_AVATARS ? true : false;
+ ph.fSecondLine = g_floatoptions.dwFlags & FLT_DUALROW ? true : false;
+ if(!(g_floatoptions.dwFlags & FLT_EXTRAICONS)) {
+ cfg::dat.dwFlags &= ~(CLUI_SHOWCLIENTICONS | CLUI_SHOWVISI);
+ cfg::eCache[contact->extraCacheEntry].dwXMask = 0;
+ }
+ }
+
+ ph.aggctx->attach(cfg::eCache[contact->extraCacheEntry].floater->hbm);
+ ph.current_shape = 0;
+ Gfx::renderSkinItem(&ph, &Skin::statusItems[ID_EXTBKSTATUSFLOATER], &rcClient);
+
+ ph.setFloater();
+ ph.hTheme = Api::pfnOpenThemeData(hwnd, L"BUTTON");
+
+ ph.Paint(group, contact, rcClient.bottom - rcClient.top);
+
+ Api::pfnCloseThemeData(ph.hTheme);
+
+ g_padding_y = 0;
+
+ SelectObject(hdcTempAV, hbmTempOldAV);
+ DeleteObject(hbmTempAV);
+ DeleteDC(hdcTempAV);
+
+ cfg::dat.dwFlags = oldFlags;
+ cfg::dat.avatarPadding = oldPadding;
+ cfg::eCache[contact->extraCacheEntry].dwXMask = oldExtraImageMask;
+
+ dat->leftMargin = oldLeftMargin;
+ dat->rightMargin = oldRightMargin;
+ }
+
+ if(g_floatoptions.dwFlags & FLT_BORDER){
+ hbrBorder = CreateSolidBrush(g_floatoptions.border_colour);
+ FrameRect(hdc, &rcClient, hbrBorder);
+ DeleteObject(hbrBorder);
+ }
+
+ bf.BlendOp = AC_SRC_OVER;
+ bf.AlphaFormat = AC_SRC_ALPHA;
+ bf.SourceConstantAlpha = g_floatoptions.trans;
+
+ UpdateLayeredWindow(hwnd, 0, &ptDest, &szDest, hdc, &ptSrc, 0, &bf, ULW_ALPHA);
+}
+
+/*
+ * syncs the floating contacts with clist contact visibility.
+ * will hide all floating contacts which are not visible on the list
+ * needed after a list rebuild
+ */
+
+void FLT_SyncWithClist()
+{
+ struct ClcContact *contact;
+ struct ContactFloater *pCurrent = pFirstFloater;
+ HWND hwnd;
+ int iVis = pcli->pfnGetWindowVisibleState(pcli->hwndContactList, 0, 0);
+
+ if(g_floatoptions.dwFlags & FLT_SYNCWITHCLIST){
+ while(pCurrent) {
+ hwnd = pCurrent->hwnd;
+ if(hwnd && IsWindow(hwnd)){
+ if(CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)pCurrent->hContact, &contact, NULL, 0)) {
+ FLT_Update(cfg::clcdat, contact);
+ if(((g_floatoptions.dwFlags & FLT_AUTOHIDE) && (iVis == 2 || iVis == 4)) || !(g_floatoptions.dwFlags & FLT_AUTOHIDE))
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+ else
+ ShowWindow(hwnd, SW_HIDE);
+ }
+ else
+ ShowWindow(hwnd, SW_HIDE);
+ }
+ pCurrent = pCurrent->pNextFloater;
+ }
+ }
+}
+
+/*
+ * quickly show or hide all floating contacts
+ * used by autohide/show feature
+ */
+
+void FLT_ShowHideAll(int showCmd)
+{
+ struct ClcContact *contact;
+ struct ContactFloater *pCurrent = pFirstFloater;
+ HWND hwnd;
+
+ if(g_floatoptions.dwFlags & FLT_AUTOHIDE){
+ while(pCurrent) {
+ hwnd = pCurrent->hwnd;
+ if(hwnd && IsWindow(hwnd)){
+ if(showCmd == SW_SHOWNOACTIVATE && CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)pCurrent->hContact, &contact, NULL, 0))
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+ else if(showCmd != SW_SHOWNOACTIVATE)
+ ShowWindow(hwnd, showCmd);
+ }
+ pCurrent = pCurrent->pNextFloater;
+ }
+ }
+}
+
+/*
+ * update/repaint all contact floaters
+ */
+
+void FLT_RefreshAll()
+{
+ struct ClcContact *contact = NULL;
+ struct ContactFloater *pCurrent = pFirstFloater;
+
+ while(pCurrent) {
+ if(CLC::findItem(pcli->hwndContactTree, cfg::clcdat, (HANDLE)pCurrent->hContact, &contact, NULL, 0)) {
+ HWND hwnd = pCurrent->hwnd;
+ if(hwnd && IsWindow(hwnd))
+ FLT_Update(cfg::clcdat, contact);
+ }
+ pCurrent = pCurrent->pNextFloater;
+ }
+}
+
diff --git a/plugins/Clist_ng/SRC/utils.cpp b/plugins/Clist_ng/SRC/utils.cpp new file mode 100644 index 0000000000..99c33d9bcc --- /dev/null +++ b/plugins/Clist_ng/SRC/utils.cpp @@ -0,0 +1,615 @@ +/*
+ * 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: utils.cpp 137 2010-10-16 21:03:23Z silvercircle $
+ *
+ * utility functions for clist_ng.
+ */
+
+#include <commonheaders.h>
+
+#define RTF_DEFAULT_HEADER _T("{\\rtf1\\ansi\\deff0\\pard\\li%u\\fi-%u\\ri%u\\tx%u")
+
+wchar_t* WarningDlg::m_warnings[WarningDlg::WARN_LAST] = {
+ LPGENT("Notes|release notes"),
+ LPGENT("Skin loading error|The skin cannot be loaded"),
+ LPGENT("Overwrite skin file|You are about to save your customized settings to the \\b1 original skin file.\\b0 This could cause problems and may require to reinstall the skin.\nYou should use \\b1 Save as user modification\\b0 to keep the original skin untouched.\n\nContinue?")
+};
+
+MWindowList WarningDlg::hWindowList = 0;
+
+/**
+ * ensure that a path name ends on a trailing backslash
+ * @param szPathname - pathname to check
+ */
+void Utils::ensureTralingBackslash(wchar_t *szPathname)
+{
+ if(szPathname[lstrlenW(szPathname) - 1] != '\\')
+ wcscat(szPathname, L"\\");
+}
+
+void Utils::extractResource(const HMODULE h, const UINT uID, const wchar_t* tszName, const wchar_t* tszPath,
+ const wchar_t* tszFilename, bool fForceOverwrite)
+{
+ HRSRC hRes;
+ HGLOBAL hResource;
+ wchar_t szFilename[MAX_PATH];
+
+ hRes = FindResourceW(h, MAKEINTRESOURCE(uID), tszName);
+
+ if(hRes) {
+ hResource = LoadResource(h, hRes);
+ if(hResource) {
+ HANDLE hFile;
+ char *pData = (char *)LockResource(hResource);
+ DWORD dwSize = SizeofResource(g_hInst, hRes), written = 0;
+ mir_sntprintf(szFilename, MAX_PATH, _T("%s%s"), tszPath, tszFilename);
+ if(!fForceOverwrite) {
+ if(PathFileExistsW(szFilename))
+ return;
+ }
+ if((hFile = CreateFileW(szFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
+ WriteFile(hFile, (void *)pData, dwSize, &written, NULL);
+ CloseHandle(hFile);
+ }
+ else {
+ wchar_t wszTemp[512];
+ mir_sntprintf(wszTemp, 512, L"%s - (WIN32 Error: %d)", szFilename, GetLastError());
+ throw(CRTException("Error while extracting base skin.", wszTemp));
+ }
+ }
+ }
+}
+
+/**
+ * enable or disable a dialog control
+ */
+void TSAPI Utils::enableDlgControl(const HWND hwnd, UINT id, BOOL fEnable)
+{
+ ::EnableWindow(::GetDlgItem(hwnd, id), fEnable);
+}
+
+/**
+ * show or hide a dialog control
+ */
+void TSAPI Utils::showDlgControl(const HWND hwnd, UINT id, int showCmd)
+{
+ ::ShowWindow(::GetDlgItem(hwnd, id), showCmd);
+}
+
+/**
+ * load a system library from the Windows system path and return its module
+ * handle.
+ *
+ * return 0 and throw an exception if something goes wrong.
+ */
+HMODULE Utils::loadSystemLibrary(const wchar_t* szFilename, bool useGetHandle)
+{
+ wchar_t sysPathName[MAX_PATH + 2];
+ HMODULE _h = 0;
+
+ try {
+ if(0 == ::GetSystemDirectoryW(sysPathName, MAX_PATH))
+ throw(CRTException("Error while loading system library", szFilename));
+
+ sysPathName[MAX_PATH - 1] = 0;
+ if(wcslen(sysPathName) + wcslen(szFilename) >= MAX_PATH)
+ throw(CRTException("Error while loading system library", szFilename));
+
+ lstrcatW(sysPathName, szFilename);
+ if(useGetHandle)
+ _h = ::GetModuleHandle(sysPathName);
+ else
+ _h = LoadLibraryW(sysPathName);
+ if(0 == _h)
+ throw(CRTException("Error while loading system library", szFilename));
+ }
+ catch(CRTException& ex) {
+ ex.display();
+ return(0);
+ }
+ return(_h);
+}
+
+DWORD __fastcall Utils::hexStringToLong(const char *szSource)
+{
+ char *stopped;
+ COLORREF clr = strtol(szSource, &stopped, 16);
+ if(clr == -1)
+ return clr;
+ return(RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)));
+}
+
+/**
+ * Case insensitive _tcsstr
+ *
+ * @param szString TCHAR *: String to be searched
+ * @param szSearchFor
+ * TCHAR *: String that should be found in szString
+ *
+ * @return TCHAR *: found position of szSearchFor in szString. 0 if szSearchFor was not found
+ */
+const wchar_t* Utils::striStr(const wchar_t* szString, const wchar_t* szSearchFor)
+{
+ if(szString && *szString) {
+ if (0 == szSearchFor || 0 == *szSearchFor)
+ return(szString);
+
+ for(; *szString; ++szString) {
+ if(towupper(*szString) == towupper(*szSearchFor)) {
+ const wchar_t* h, *n;
+ for(h = szString, n = szSearchFor; *h && *n; ++h, ++n) {
+ if(towupper(*h) != towupper(*n))
+ break;
+ }
+ if(!*n)
+ return(szString);
+ }
+ }
+ return(0);
+ }
+ else
+ return(0);
+}
+
+int Utils::pathIsAbsolute(const wchar_t* path)
+{
+ if (!path || !(lstrlenW(path) > 2))
+ return 0;
+ if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
+ return 1;
+ return 0;
+}
+
+size_t Utils::pathToRelative(const wchar_t* pSrc, wchar_t* pOut, const wchar_t* szBase)
+{
+ const wchar_t* tszBase = szBase ? szBase : cfg::szProfileDir;
+
+ pOut[0] = 0;
+ if (!pSrc || !lstrlenW(pSrc) || lstrlenW(pSrc) > MAX_PATH)
+ return 0;
+ if (!pathIsAbsolute(pSrc)) {
+ mir_sntprintf(pOut, MAX_PATH, L"%s", pSrc);
+ return lstrlenW(pOut);
+ } else {
+ wchar_t szTmp[MAX_PATH];
+
+ mir_sntprintf(szTmp, _countof(szTmp), L"%s", pSrc);
+ if (striStr(szTmp, tszBase)) {
+ if(tszBase[lstrlenW(tszBase) - 1] == '\\')
+ mir_sntprintf(pOut, MAX_PATH, L"%s", pSrc + lstrlenW(tszBase));
+ else {
+ mir_sntprintf(pOut, MAX_PATH, L"%s", pSrc + lstrlenW(tszBase) + 1 );
+ //pOut[0]='.';
+ }
+ return(lstrlenW(pOut));
+ } else {
+ mir_sntprintf(pOut, MAX_PATH, L"%s", pSrc);
+ return(lstrlenW(pOut));
+ }
+ }
+}
+
+/**
+ * Translate a relativ path to an absolute, using the current profile
+ * data directory.
+ *
+ * @param pSrc TCHAR *: input path + filename (relative)
+ * @param pOut TCHAR *: the result
+ * @param szBase TCHAR *: (OPTIONAL) base path for the translation. Can be 0 in which case
+ * the function will use m_szProfilePath (usually \tabSRMM below %miranda_userdata%
+ *
+ * @return
+ */
+size_t Utils::pathToAbsolute(const wchar_t* pSrc, wchar_t* pOut, const wchar_t* szBase)
+{
+ const wchar_t* tszBase = szBase ? szBase : cfg::szProfileDir;
+ const wchar_t* wszFmt = (tszBase[lstrlenW(tszBase) - 1] == '\\' ? L"%s%s" : L"%s\\%s");
+
+ pOut[0] = 0;
+ if (!pSrc || !lstrlenW(pSrc) || lstrlenW(pSrc) > MAX_PATH)
+ return 0;
+ if (pathIsAbsolute(pSrc) && pSrc[0]!='.')
+ mir_sntprintf(pOut, MAX_PATH, L"%s", pSrc);
+ else if (pSrc[0]=='.')
+ mir_sntprintf(pOut, MAX_PATH, wszFmt, tszBase, pSrc + 1);
+ else
+ mir_sntprintf(pOut, MAX_PATH, wszFmt, tszBase, pSrc);
+
+ return lstrlenW(pOut);
+}
+
+/**
+ * extract the clicked URL from a rich edit control. Return the URL as TCHAR*
+ * caller MUST mir_free() the returned string
+ * @param hwndRich - rich edit window handle
+ * @return wchar_t* extracted URL
+ */
+const wchar_t* Utils::extractURLFromRichEdit(const ENLINK* _e, const HWND hwndRich)
+{
+ TEXTRANGEW tr = {0};
+ CHARRANGE sel = {0};
+
+ ::SendMessageW(hwndRich, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin != sel.cpMax)
+ return(0);
+
+ tr.chrg = _e->chrg;
+ tr.lpstrText = (wchar_t *)mir_alloc(2 * (tr.chrg.cpMax - tr.chrg.cpMin + 8));
+ ::SendMessageW(hwndRich, EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+ if (wcschr(tr.lpstrText, '@') != NULL && wcschr(tr.lpstrText, ':') == NULL && wcschr(tr.lpstrText, '/') == NULL) {
+ ::MoveMemory(tr.lpstrText + 7, tr.lpstrText, sizeof(TCHAR) * (tr.chrg.cpMax - tr.chrg.cpMin + 1));
+ ::CopyMemory(tr.lpstrText, L"mailto:", 7);
+ }
+ return(tr.lpstrText);
+}
+
+/**
+ * implementation of the CWarning class
+ */
+WarningDlg::WarningDlg(const wchar_t *tszTitle, const wchar_t *tszText, const UINT uId, const DWORD dwFlags)
+{
+ m_pszTitle = pSmartWstring(new std::basic_string<wchar_t>(tszTitle));
+ m_pszText = pSmartWstring(new std::basic_string<wchar_t>(tszText));
+
+ m_uId = uId;
+ m_hFontCaption = 0;
+ m_dwFlags = dwFlags;
+
+ m_fIsModal = ((m_dwFlags & MB_YESNO || m_dwFlags & MB_YESNOCANCEL) ? true : false);
+}
+
+WarningDlg::~WarningDlg()
+{
+ if(m_hFontCaption)
+ ::DeleteObject(m_hFontCaption);
+
+#if defined(__LOGDEBUG_)
+ _DebugTraceW(L"destroy object");
+#endif
+}
+
+LRESULT WarningDlg::ShowDialog() const
+{
+ if(!m_fIsModal) {
+ ::CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_WARNING), 0, stubDlgProc, reinterpret_cast<LPARAM>(this));
+ return(0);
+ }
+ else {
+ LRESULT res = ::DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_WARNING), 0, stubDlgProc, reinterpret_cast<LPARAM>(this));
+ return(res);
+ }
+}
+
+__int64 WarningDlg::getMask()
+{
+ __int64 mask = 0;
+
+ DWORD dwLow = cfg::getDword("CList", "cWarningsL", 0);
+ DWORD dwHigh = cfg::getDword("CList", "cWarningsH", 0);
+
+ mask = ((((__int64)dwHigh) << 32) & 0xffffffff00000000) | dwLow;
+
+ return(mask);
+}
+
+/**
+ * send cancel message to all open warning dialogs so they are destroyed
+ * before plugin is unloaded.
+ *
+ * called by the OkToExit handler in globals.cpp
+ */
+void WarningDlg::destroyAll()
+{
+ if(hWindowList)
+ WindowList_Broadcast(hWindowList, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), 0);
+}
+/**
+ * show a CWarning dialog using the id value. Check whether the user has chosen to
+ * not show this message again. This has room for 64 different warning dialogs, which
+ * should be enough in the first place. Extending it should not be too hard though.
+ */
+LRESULT WarningDlg::show(const int uId, DWORD dwFlags, const wchar_t* tszTxt)
+{
+ wchar_t* separator_pos = 0;
+ __int64 mask = 0, val = 0;
+ LRESULT result = 0;
+ wchar_t* _s = 0;
+
+ if (0 == hWindowList)
+ hWindowList = WindowList_Create();
+
+ /*
+ * don't open new warnings when shutdown was initiated (modal ones will otherwise
+ * block the shutdown)
+ */
+ if(cfg::shutDown)
+ return(-1);
+
+ if(uId >= 0) {
+ mask = getMask();
+ val = ((__int64)1L) << uId;
+ }
+ else
+ mask = val = 0;
+
+ if(!(0 == (mask & val) || dwFlags & CWF_NOALLOWHIDE))
+ return(-1);
+
+ if(tszTxt)
+ _s = const_cast<wchar_t *>(tszTxt);
+ else {
+ if(uId != -1) {
+ if(dwFlags & CWF_UNTRANSLATED)
+ _s = const_cast<wchar_t *>(m_warnings[uId]);
+ else {
+ /*
+ * revert to untranslated warning when the translated message
+ * is not well-formatted.
+ */
+ _s = const_cast<wchar_t *>(TranslateW(m_warnings[uId]));
+
+ if(wcslen(_s) < 3 || 0 == wcschr(_s, '|'))
+ _s = const_cast<wchar_t *>(m_warnings[uId]);
+ }
+ }
+ else if(-1 == uId && tszTxt) {
+ dwFlags |= CWF_NOALLOWHIDE;
+ _s = (dwFlags & CWF_UNTRANSLATED ? const_cast<wchar_t *>(tszTxt) : TranslateW(tszTxt));
+ }
+ else
+ return(-1);
+ }
+
+ if((wcslen(_s) > 3) && ((separator_pos = wcschr(_s, '|')) != 0)) {
+
+ wchar_t *s = reinterpret_cast<wchar_t *>(mir_alloc((wcslen(_s) + 1) * 2));
+ wcscpy(s, _s);
+ separator_pos = wcschr(s, '|');
+
+ if(separator_pos) {
+ separator_pos[0] = 0;
+
+ WarningDlg *w = new WarningDlg(s, &separator_pos[1], uId, dwFlags);
+ if(!(dwFlags & MB_YESNO || dwFlags & MB_YESNOCANCEL)) {
+ w->ShowDialog();
+ mir_free(s);
+ }
+ else {
+ result = w->ShowDialog();
+ mir_free(s);
+ return(result);
+ }
+ }
+ else
+ mir_free(s);
+ }
+ return(-1);
+}
+
+/**
+ * stub dlg procedure. Just register the object pointer in WM_INITDIALOG
+ */
+INT_PTR CALLBACK WarningDlg::stubDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WarningDlg *w = reinterpret_cast<WarningDlg *>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
+ if(w)
+ return(w->dlgProc(hwnd, msg, wParam, lParam));
+
+ switch(msg) {
+ case WM_INITDIALOG: {
+ w = reinterpret_cast<WarningDlg *>(lParam);
+ if(w) {
+ ::SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
+ return(w->dlgProc(hwnd, msg, wParam, lParam));
+ }
+ break;
+ }
+
+#if defined(__LOGDEBUG_)
+ case WM_NCDESTROY:
+ _DebugTraceW(L"window destroyed");
+ break;
+#endif
+
+ default:
+ break;
+ }
+ return(FALSE);
+}
+
+/**
+ * dialog procedure for the warning dialog box
+ */
+INT_PTR CALLBACK WarningDlg::dlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ HICON hIcon = 0;
+ UINT uResId = 0;
+ TCHAR temp[1024];
+ SETTEXTEX stx = {ST_SELECTION, CP_UTF8};
+ size_t pos = 0;
+
+ m_hwnd = hwnd;
+
+ ::SetWindowTextW(hwnd, L"Clist NG warning");
+ ::SendMessage(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(Skin_LoadIcon(SKINICON_OTHER_MIRANDA, true)));
+ ::SendMessage(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(Skin_LoadIcon(SKINICON_OTHER_MIRANDA)));
+ ::SendDlgItemMessage(hwnd, IDC_WARNTEXT, EM_AUTOURLDETECT, (WPARAM) TRUE, 0);
+ ::SendDlgItemMessage(hwnd, IDC_WARNTEXT, EM_SETEVENTMASK, 0, ENM_LINK);
+
+ mir_sntprintf(temp, 1024, RTF_DEFAULT_HEADER, 0, 0, 0, 30*15);
+ std::basic_string<wchar_t> *str = new std::basic_string<wchar_t>(temp);
+
+ str->append((*m_pszText).c_str());
+ str->append(L"}");
+
+ TranslateDialogDefault(hwnd);
+
+ /*
+ * convert normal line breaks to rtf
+ */
+ while((pos = str->find(L"\n")) != str->npos) {
+ str->erase(pos, 1);
+ str->insert(pos, L"\\line ");
+ }
+
+ char *utf8 = Utf8EncodeW(str->c_str());
+ ::SendDlgItemMessage(hwnd, IDC_WARNTEXT, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)utf8);
+ mir_free(utf8);
+ delete str;
+
+ ::SetDlgItemTextW(hwnd, IDC_CAPTION, (*m_pszTitle).c_str());
+
+ if(m_dwFlags & CWF_NOALLOWHIDE)
+ Utils::showDlgControl(hwnd, IDC_DONTSHOWAGAIN, SW_HIDE);
+ if(m_dwFlags & MB_YESNO || m_dwFlags & MB_YESNOCANCEL) {
+ Utils::showDlgControl(hwnd, IDOK, SW_HIDE);
+ ::SetFocus(::GetDlgItem(hwnd, IDCANCEL));
+ }
+ else {
+ Utils::showDlgControl(hwnd, IDCANCEL, SW_HIDE);
+ Utils::showDlgControl(hwnd, IDYES, SW_HIDE);
+ Utils::showDlgControl(hwnd, IDNO, SW_HIDE);
+ ::SetFocus(::GetDlgItem(hwnd, IDOK));
+ }
+ if(m_dwFlags & MB_ICONERROR || m_dwFlags & MB_ICONHAND)
+ uResId = 32513;
+ else if(m_dwFlags & MB_ICONEXCLAMATION || m_dwFlags & MB_ICONWARNING)
+ uResId = 32515;
+ else if(m_dwFlags & MB_ICONASTERISK || m_dwFlags & MB_ICONINFORMATION)
+ uResId = 32516;
+ else if(m_dwFlags & MB_ICONQUESTION)
+ uResId = 32514;
+
+ if(uResId)
+ hIcon = reinterpret_cast<HICON>(::LoadImage(0, MAKEINTRESOURCE(uResId), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
+ else
+ hIcon = Skin_LoadIcon(SKINICON_EVENT_MESSAGE, true);
+
+ ::SendDlgItemMessageW(hwnd, IDC_WARNICON, STM_SETICON, reinterpret_cast<WPARAM>(hIcon), 0);
+ if(!(m_dwFlags & MB_YESNO || m_dwFlags & MB_YESNOCANCEL))
+ ::ShowWindow(hwnd, SW_SHOWNORMAL);
+
+ WindowList_Add(hWindowList, hwnd, (MCONTACT)hwnd);
+ return(TRUE);
+ }
+
+ case WM_CTLCOLORSTATIC: {
+ HWND hwndChild = reinterpret_cast<HWND>(lParam);
+ UINT id = ::GetDlgCtrlID(hwndChild);
+ if(0 == m_hFontCaption) {
+ HFONT hFont = reinterpret_cast<HFONT>(::SendDlgItemMessage(hwnd, IDC_CAPTION, WM_GETFONT, 0, 0));
+ LOGFONT lf = {0};
+
+ ::GetObject(hFont, sizeof(lf), &lf);
+ lf.lfHeight = (int)((double)lf.lfHeight * 1.7f);
+ m_hFontCaption = ::CreateFontIndirect(&lf);
+ ::SendDlgItemMessage(hwnd, IDC_CAPTION, WM_SETFONT, (WPARAM)m_hFontCaption, FALSE);
+ }
+
+ if(IDC_CAPTION == id) {
+ ::SetTextColor(reinterpret_cast<HDC>(wParam), ::GetSysColor(COLOR_HIGHLIGHT));
+ ::SendMessage(hwndChild, WM_SETFONT, (WPARAM)m_hFontCaption, FALSE);
+ }
+
+ if(IDC_WARNGROUP != id && IDC_DONTSHOWAGAIN != id) {
+ ::SetBkColor((HDC)wParam, ::GetSysColor(COLOR_WINDOW));
+ return reinterpret_cast<INT_PTR>(::GetSysColorBrush(COLOR_WINDOW));
+ }
+ break;
+ }
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDOK:
+ case IDCANCEL:
+ case IDYES:
+ case IDNO:
+ if(!m_fIsModal && (IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam))) { // modeless dialogs can receive a IDCANCEL from destroyAll()
+ ::SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+ delete this;
+ WindowList_Remove(hWindowList, hwnd);
+ ::DestroyWindow(hwnd);
+ }
+ else {
+ ::SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+ delete this;
+ WindowList_Remove(hWindowList, hwnd);
+ ::EndDialog(hwnd, LOWORD(wParam));
+ }
+ break;
+
+ case IDC_DONTSHOWAGAIN: {
+ __int64 mask = getMask(), val64 = ((__int64)1L << m_uId), newVal = 0;
+
+ newVal = mask | val64;
+
+ if(::IsDlgButtonChecked(hwnd, IDC_DONTSHOWAGAIN)) {
+ DWORD val = (DWORD)(newVal & 0x00000000ffffffff);
+ cfg::writeDword("CList", "cWarningsL", val);
+ val = (DWORD)((newVal >> 32) & 0x00000000ffffffff);
+ cfg::writeDword("CList", "cWarningsH", val);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case WM_NOTIFY: {
+ switch (((NMHDR *) lParam)->code) {
+ case EN_LINK:
+ switch (((ENLINK *) lParam)->msg) {
+ case WM_LBUTTONUP: {
+ ENLINK* e = reinterpret_cast<ENLINK *>(lParam);
+
+ const wchar_t* wszUrl = Utils::extractURLFromRichEdit(e, ::GetDlgItem(hwnd, IDC_WARNTEXT));
+ if(wszUrl) {
+ char* szUrl = mir_t2a(wszUrl);
+
+ Utils_OpenUrl(szUrl);
+ mir_free(szUrl);
+ mir_free(const_cast<TCHAR *>(wszUrl));
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return(FALSE);
+}
diff --git a/plugins/Clist_ng/SRC/viewmodes.cpp b/plugins/Clist_ng/SRC/viewmodes.cpp new file mode 100644 index 0000000000..34142bb736 --- /dev/null +++ b/plugins/Clist_ng/SRC/viewmodes.cpp @@ -0,0 +1,1249 @@ +/*
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+
+contact list view modes (CLVM)
+
+$Id: viewmodes.cpp 131 2010-09-29 04:50:58Z silvercircle $
+
+*/
+
+#include <commonheaders.h>
+
+#define TIMERID_VIEWMODEEXPIRE 100
+
+extern HPEN g_hPenCLUIFrames;
+extern FRAMEWND *wndFrameViewMode;
+
+typedef int (__cdecl *pfnEnumCallback)(char *szName);
+static HWND clvmHwnd = 0;
+static int clvm_curItem = 0;
+HMENU hViewModeMenu = 0;
+
+static HWND hwndSelector = 0;
+static HIMAGELIST himlViewModes = 0;
+static HANDLE hInfoItem = 0;
+static int nullImage;
+static DWORD stickyStatusMask = 0;
+static char g_szModename[2048];
+
+static int g_ViewModeOptDlg = FALSE;
+
+static UINT _page1Controls[] = {IDC_STATIC1, IDC_STATIC2, IDC_STATIC3, IDC_STATIC5, IDC_STATIC4,
+ IDC_STATIC8, IDC_ADDVIEWMODE, IDC_DELETEVIEWMODE, IDC_NEWVIEMODE, IDC_GROUPS, IDC_PROTOCOLS,
+ IDC_VIEWMODES, IDC_STATUSMODES, IDC_STATIC12, IDC_STATIC13, IDC_STATIC14, IDC_PROTOGROUPOP, IDC_GROUPSTATUSOP,
+ IDC_AUTOCLEAR, IDC_AUTOCLEARVAL, IDC_AUTOCLEARSPIN, IDC_STATIC15, IDC_STATIC16,
+ IDC_LASTMESSAGEOP, IDC_LASTMESSAGEUNIT, IDC_LASTMSG, IDC_LASTMSGVALUE, 0};
+
+static UINT _page2Controls[] = {IDC_CLIST, IDC_STATIC9, IDC_STATIC8, IDC_CLEARALL, IDC_CURVIEWMODE2, 0};
+
+
+/*
+ * enumerate all view modes, call the callback function with the mode name
+ * useful for filling lists, menus and so on..
+ */
+
+int CLVM_EnumProc(const char *szSetting, LPARAM lParam)
+{
+ pfnEnumCallback EnumCallback = (pfnEnumCallback)lParam;
+ if (szSetting != NULL)
+ EnumCallback((char *)szSetting);
+ return(0);
+}
+
+void CLVM_EnumModes(pfnEnumCallback EnumCallback)
+{
+ DBCONTACTENUMSETTINGS dbces;
+
+ dbces.pfnEnumProc = CLVM_EnumProc;
+ dbces.szModule = CLVM_MODULE;
+ dbces.ofsSettings=0;
+ dbces.lParam = (LPARAM)EnumCallback;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+}
+
+int FillModes(char *szsetting)
+{
+ if(szsetting[0] == 'ö')
+ return 1;
+ SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)szsetting);
+ return 1;
+}
+
+static void ShowPage(HWND hwnd, int page)
+{
+ int i = 0;
+ int pageChange = 0;
+
+ if(page == 0 && IsWindowVisible(GetDlgItem(hwnd, _page2Controls[0])))
+ pageChange = 1;
+
+ if(page == 1 && IsWindowVisible(GetDlgItem(hwnd, _page1Controls[0])))
+ pageChange = 1;
+
+ if(pageChange)
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ switch(page) {
+ case 0:
+ while(_page1Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_SHOW);
+ i = 0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_HIDE);
+ break;
+ case 1:
+ while(_page1Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_HIDE);
+ i = 0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_SHOW);
+ break;
+ }
+ if(pageChange) {
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
+ }
+}
+
+static int UpdateClistItem(HANDLE hContact, DWORD mask)
+{
+ int i;
+
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hContact, MAKELONG(i - ID_STATUS_OFFLINE,
+ (1 << (i - ID_STATUS_OFFLINE)) & mask ? i - ID_STATUS_OFFLINE : nullImage));
+
+ return 0;
+}
+
+static DWORD GetMaskForItem(HANDLE hItem)
+{
+ int i;
+ DWORD dwMask = 0;
+
+ for(i = 0; i <= ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE; i++)
+ dwMask |= (SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i) == nullImage ? 0 : 1 << i);
+
+ return dwMask;
+}
+
+static void UpdateStickies()
+{
+ MCONTACT hContact = db_find_first();
+ HANDLE hItem;
+ DWORD localMask;
+ int i;
+
+ while(hContact) {
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, cfg::getByte(hContact, "CLVM", g_szModename, 0) ? 1 : 0);
+ localMask = HIWORD(cfg::getDword(hContact, "CLVM", g_szModename, 0));
+ UpdateClistItem(hItem, (localMask == 0 || localMask == stickyStatusMask) ? stickyStatusMask : localMask);
+ hContact = db_find_next(hContact);
+ }
+
+ {
+ HANDLE hItem;
+
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hInfoItem, MAKELONG(i - ID_STATUS_OFFLINE, (1 << (i - ID_STATUS_OFFLINE)) & stickyStatusMask ? i - ID_STATUS_OFFLINE : ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1));
+
+ hItem=(HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETNEXTITEM,CLGN_ROOT,0);
+ hItem=(HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP, (LPARAM)hItem);
+ while(hItem) {
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELONG(i - ID_STATUS_OFFLINE, nullImage));
+ hItem=(HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ ShowPage(clvmHwnd, 0);
+ }
+}
+
+static int FillDialog(HWND hwnd)
+{
+ LVCOLUMN lvc = {0};
+ HWND hwndList = GetDlgItem(hwnd, IDC_PROTOCOLS);
+ LVITEMA item = {0};
+ int protoCount = 0, i, newItem;
+ PROTOACCOUNT **accs = 0;
+
+ CLVM_EnumModes(FillModes);
+ ListView_SetExtendedListViewStyle(GetDlgItem(hwnd, IDC_PROTOCOLS), LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(GetDlgItem(hwnd, IDC_PROTOCOLS), 0, &lvc);
+
+ // fill protocols...
+
+ Proto_EnumAccounts( &protoCount, &accs );
+ item.mask = LVIF_TEXT;
+ item.iItem = 1000;
+ for (i = 0; i < protoCount; i++) {
+ item.pszText = accs[i]->szModuleName;
+ newItem = SendMessageA(hwndList, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ }
+
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+
+ // fill groups
+ {
+ LVITEM item = {0};
+ char buf[20];
+ DBVARIANT dbv = {0};
+
+ hwndList = GetDlgItem(hwnd, IDC_GROUPS);
+
+ ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(hwndList, 0, &lvc);
+
+ item.mask = LVIF_TEXT;
+ item.iItem = 1000;
+
+ item.pszText = TranslateT("Ungrouped contacts");
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+
+ for(i = 0;;i++) {
+ mir_snprintf(buf, 20, "%d", i);
+ if(cfg::getTString(NULL, "CListGroups", buf, &dbv))
+ break;
+
+ item.pszText = &dbv.ptszVal[1];
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+ db_free(&dbv);
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+ }
+ hwndList = GetDlgItem(hwnd, IDC_STATUSMODES);
+ ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(hwndList, 0, &lvc);
+ {
+ LVITEMW item = { 0 };
+ item.mask = LVIF_TEXT;
+ item.iItem = 1000;
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ item.pszText = TranslateTS(pcli->pfnGetStatusModeDescription(i, 0));
+ item.iItem = i - ID_STATUS_OFFLINE;
+ newItem = SendMessageA(hwndList, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ }
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+
+ SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And"));
+ SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or"));
+ SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And"));
+ SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or"));
+
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Older than"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Newer than"));
+
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Minutes"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Hours"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Days"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, 0, 0);
+ SetDlgItemInt(hwnd, IDC_LASTMSGVALUE, 0, 0);
+ return 0;
+}
+
+static void SetAllChildIcons(HWND hwndList,HANDLE hFirstItem,int iColumn,int iImage)
+{
+ int typeOfFirst,iOldIcon;
+ HANDLE hItem,hChildItem;
+
+ typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0);
+ //check groups
+ if(typeOfFirst==CLCIT_GROUP) hItem=hFirstItem;
+ else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem);
+ while(hItem) {
+ hChildItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if(hChildItem)
+ SetAllChildIcons(hwndList,hChildItem,iColumn,iImage);
+ hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ //check contacts
+ if(typeOfFirst==CLCIT_CONTACT) hItem=hFirstItem;
+ else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem);
+ while(hItem) {
+ iOldIcon=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if(iOldIcon!=0xFF && iOldIcon!=iImage) SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem);
+ }
+}
+
+static void SetIconsForColumn(HWND hwndList,HANDLE hItem,HANDLE hItemAll,int iColumn,int iImage)
+{
+ int itemType;
+
+ itemType=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hItem,0);
+ if(itemType==CLCIT_CONTACT) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage!=0xFF&&oldiImage!=iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ }
+ else if(itemType==CLCIT_INFO) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage!=0xFF&&oldiImage!=iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ if(hItem == hItemAll)
+ SetAllChildIcons(hwndList,hItem,iColumn,iImage);
+ else
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); //hItemUnknown
+ }
+ else if(itemType==CLCIT_GROUP) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage!=0xFF&&oldiImage!=iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if(hItem)
+ SetAllChildIcons(hwndList,hItem,iColumn,iImage);
+ }
+}
+
+void SaveViewMode(const char *name, const wchar_t *szGroupFilter, const char *szProtoFilter, DWORD statusMask, DWORD stickyStatusMask, unsigned int options,
+ unsigned int stickies, unsigned int operators, unsigned int lmdat)
+{
+ char szSetting[512];
+
+ mir_snprintf(szSetting, 512, "%c%s_PF", 246, name);
+ cfg::writeString(NULL, CLVM_MODULE, szSetting, szProtoFilter);
+ mir_snprintf(szSetting, 512, "%c%s_GF", 246, name);
+ cfg::writeTString(NULL, CLVM_MODULE, szSetting, szGroupFilter);
+ mir_snprintf(szSetting, 512, "%c%s_SM", 246, name);
+ cfg::writeDword(CLVM_MODULE, szSetting, statusMask);
+ mir_snprintf(szSetting, 512, "%c%s_SSM", 246, name);
+ cfg::writeDword(CLVM_MODULE, szSetting, stickyStatusMask);
+ mir_snprintf(szSetting, 512, "%c%s_OPT", 246, name);
+ cfg::writeDword(CLVM_MODULE, szSetting, options);
+ mir_snprintf(szSetting, 512, "%c%s_LM", 246, name);
+ cfg::writeDword(CLVM_MODULE, szSetting, lmdat);
+
+ cfg::writeDword(CLVM_MODULE, name, MAKELONG((unsigned short)operators, (unsigned short)stickies));
+}
+
+/*
+ * saves the state of the filter definitions for the current item
+ */
+
+void SaveState()
+{
+ wchar_t newGroupFilter[2048] = _T("|");
+ char newProtoFilter[2048] = "|";
+ int i, iLen;
+ HWND hwndList;
+ char *szModeName = NULL;
+ DWORD statusMask = 0;
+ MCONTACT hContact;
+ HANDLE hItem;
+ DWORD operators = 0;
+
+ if(clvm_curItem == -1)
+ return;
+
+ {
+ LVITEMA item = {0};
+ char szTemp[256];
+
+ hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS);
+ for(i = 0; i < ListView_GetItemCount(hwndList); i++) {
+ if(ListView_GetCheckState(hwndList, i)) {
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+ item.iItem = i;
+ SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item);
+ strncat(newProtoFilter, szTemp, 2048);
+ strncat(newProtoFilter, "|", 2048);
+ newProtoFilter[2047] = 0;
+ }
+ }
+ }
+
+ {
+ LVITEM item = {0};
+ wchar_t szTemp[256];
+
+ hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS);
+
+ operators |= ListView_GetCheckState(hwndList, 0) ? CLVM_INCLUDED_UNGROUPED : 0;
+
+ for(i = 0; i < ListView_GetItemCount(hwndList); i++) {
+ if(ListView_GetCheckState(hwndList, i)) {
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+ item.iItem = i;
+ SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item);
+ _tcsncat(newGroupFilter, szTemp, 2048);
+ _tcsncat(newGroupFilter, _T("|"), 2048);
+ newGroupFilter[2047] = 0;
+ }
+ }
+ }
+ hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES);
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if(ListView_GetCheckState(hwndList, i - ID_STATUS_OFFLINE))
+ statusMask |= (1 << (i - ID_STATUS_OFFLINE));
+ }
+ iLen = SendMessageA(GetDlgItem(clvmHwnd, IDC_VIEWMODES), LB_GETTEXTLEN, clvm_curItem, 0);
+ if(iLen) {
+ unsigned int stickies = 0;
+ DWORD dwGlobalMask, dwLocalMask;
+ BOOL translated;
+
+ szModeName = ( char* )malloc(iLen + 1);
+ if(szModeName) {
+ DWORD options, lmdat;
+ //char *vastring = NULL;
+ //int len = GetWindowTextLengthA(GetDlgItem(clvmHwnd, IDC_VARIABLES)) + 1;
+
+ //vastring = (char *)malloc(len);
+ //if(vastring)
+ // GetDlgItemTextA(clvmHwnd, IDC_VARIABLES, vastring, len);
+ SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szModeName);
+ dwGlobalMask = GetMaskForItem(hInfoItem);
+ hContact = db_find_first();
+ while(hContact) {
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem) {
+ if(SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM)hItem, 0)) {
+ dwLocalMask = GetMaskForItem(hItem);
+ cfg::writeDword(hContact, "CLVM", szModeName, MAKELONG(1, (unsigned short)dwLocalMask));
+ stickies++;
+ }
+ else {
+ if(cfg::getDword(hContact, "CLVM", szModeName, 0))
+ cfg::writeDword(hContact, "CLVM", szModeName, 0);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ operators |= ((SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_PROTOGROUP_OP : 0) |
+ (SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_GROUPSTATUS_OP : 0) |
+ (IsDlgButtonChecked(clvmHwnd, IDC_AUTOCLEAR) ? CLVM_AUTOCLEAR : 0) |
+ (IsDlgButtonChecked(clvmHwnd, IDC_LASTMSG) ? CLVM_USELASTMSG : 0));
+
+ options = SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_GETPOS, 0, 0);
+
+ lmdat = MAKELONG(GetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, &translated, FALSE),
+ MAKEWORD(SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_GETCURSEL, 0, 0),
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_GETCURSEL, 0, 0)));
+
+ SaveViewMode(szModeName, newGroupFilter, newProtoFilter, statusMask, dwGlobalMask, options,
+ stickies, operators, lmdat);
+ //free(vastring);
+ free(szModeName);
+ }
+ }
+ Utils::enableDlgControl(clvmHwnd, IDC_APPLY, FALSE);
+}
+
+
+/*
+ * updates the filter list boxes with the data taken from the filtering string
+ */
+
+void UpdateFilters()
+{
+ DBVARIANT dbv_pf = {0};
+ DBVARIANT dbv_gf = {0};
+ char szSetting[128];
+ char *szBuf = NULL;
+ int iLen;
+ DWORD statusMask = 0;
+ DWORD dwFlags;
+ DWORD opt;
+ char szTemp[100];
+
+ if(clvm_curItem == LB_ERR)
+ return;
+
+ iLen = SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXTLEN, clvm_curItem, 0);
+
+ if(iLen == 0)
+ return;
+
+ szBuf = (char *)malloc(iLen + 1);
+ SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szBuf);
+ strncpy(g_szModename, szBuf, sizeof(g_szModename));
+ g_szModename[sizeof(g_szModename) - 1] = 0;
+ mir_snprintf(szTemp, 100, Translate("Current view mode: %s"), g_szModename);
+ SetDlgItemTextA(clvmHwnd, IDC_CURVIEWMODE2, szTemp);
+ mir_snprintf(szSetting, 128, "%c%s_PF", 246, szBuf);
+ if(db_get(NULL, CLVM_MODULE, szSetting, &dbv_pf))
+ goto cleanup;
+ mir_snprintf(szSetting, 128, "%c%s_GF", 246, szBuf);
+ if(cfg::getTString(NULL, CLVM_MODULE, szSetting, &dbv_gf))
+ goto cleanup;
+ mir_snprintf(szSetting, 128, "%c%s_OPT", 246, szBuf);
+ if((opt = cfg::getDword(NULL, CLVM_MODULE, szSetting, -1)) != -1) {
+ SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_SETPOS, 0, MAKELONG(LOWORD(opt), 0));
+ }
+ mir_snprintf(szSetting, 128, "%c%s_SM", 246, szBuf);
+ statusMask = cfg::getDword(CLVM_MODULE, szSetting, -1);
+ mir_snprintf(szSetting, 128, "%c%s_SSM", 246, szBuf);
+ stickyStatusMask = cfg::getDword(CLVM_MODULE, szSetting, -1);
+ dwFlags = cfg::getDword(CLVM_MODULE, szBuf, 0);
+ {
+ LVITEMA item = {0};
+ char szTemp[256];
+ char szMask[256];
+ int i;
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+
+ for(i = 0; i < ListView_GetItemCount(hwndList); i++) {
+ item.iItem = i;
+ SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item);
+ mir_snprintf(szMask, 256, "%s|", szTemp);
+ if(dbv_pf.pszVal && strstr(dbv_pf.pszVal, szMask))
+ ListView_SetCheckState(hwndList, i, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i, FALSE);
+ }
+ }
+ {
+ LVITEM item = {0};
+ wchar_t szTemp[256];
+ wchar_t szMask[256];
+ int i;
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+
+ ListView_SetCheckState(hwndList, 0, dwFlags & CLVM_INCLUDED_UNGROUPED ? TRUE : FALSE);
+
+ for(i = 1; i < ListView_GetItemCount(hwndList); i++) {
+ item.iItem = i;
+ SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item);
+ _sntprintf(szMask, 256, _T("%s|"), szTemp);
+ if(dbv_gf.ptszVal && _tcsstr(dbv_gf.ptszVal, szMask))
+ ListView_SetCheckState(hwndList, i, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i, FALSE);
+ }
+ }
+ {
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES);
+ int i;
+
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if((1 << (i - ID_STATUS_OFFLINE)) & statusMask)
+ ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, FALSE);
+ }
+ }
+ SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_SETCURSEL, dwFlags & CLVM_PROTOGROUP_OP ? 1 : 0, 0);
+ SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_SETCURSEL, dwFlags & CLVM_GROUPSTATUS_OP ? 1 : 0, 0);
+ CheckDlgButton(clvmHwnd, IDC_AUTOCLEAR, dwFlags & CLVM_AUTOCLEAR ? 1 : 0);
+ UpdateStickies();
+
+ {
+ int useLastMsg = dwFlags & CLVM_USELASTMSG;
+ DWORD lmdat;
+ BYTE bTmp;
+
+ CheckDlgButton(clvmHwnd, IDC_LASTMSG, useLastMsg);
+ Utils::enableDlgControl(clvmHwnd, IDC_LASTMESSAGEOP, useLastMsg);
+ Utils::enableDlgControl(clvmHwnd, IDC_LASTMSGVALUE, useLastMsg);
+ Utils::enableDlgControl(clvmHwnd, IDC_LASTMESSAGEUNIT, useLastMsg);
+
+ mir_snprintf(szSetting, 128, "%c%s_LM", 246, szBuf);
+ lmdat = cfg::getDword(CLVM_MODULE, szSetting, 0);
+
+ SetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, LOWORD(lmdat), FALSE);
+ bTmp = LOBYTE(HIWORD(lmdat));
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, bTmp, 0);
+ bTmp = HIBYTE(HIWORD(lmdat));
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, bTmp, 0);
+ }
+
+ ShowPage(clvmHwnd, 0);
+cleanup:
+ db_free(&dbv_pf);
+ db_free(&dbv_gf);
+ free(szBuf);
+}
+
+INT_PTR CALLBACK DlgProcViewModesSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ clvmHwnd = hwndDlg;
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ int i = 0;
+ TCITEMA tci;
+ RECT rcClient;
+ CLCINFOITEM cii = {0};
+ HICON hIcon;
+
+ if(IS_THEMED)
+ Api::pfnEnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
+
+ himlViewModes = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 12, 0);
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ ImageList_AddIcon(himlViewModes, Skin_LoadProtoIcon(NULL, i));
+
+ hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_MINIMIZE), IMAGE_ICON, 16, 16, 0);
+ nullImage = ImageList_AddIcon(himlViewModes, hIcon);
+ DestroyIcon(hIcon);
+ GetClientRect(hwndDlg, &rcClient);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.lParam = 0;
+ tci.pszText = Translate("Sticky contacts");
+ SendMessageA(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEMA, (WPARAM)0, (LPARAM)&tci);
+
+ tci.pszText = Translate("Filtering");
+ SendMessageA(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEMA, (WPARAM)0, (LPARAM)&tci);
+
+ TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), 0);
+
+ TranslateDialogDefault(hwndDlg);
+ FillDialog(hwndDlg);
+ Utils::enableDlgControl(hwndDlg, IDC_ADDVIEWMODE, FALSE);
+
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)himlViewModes);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRACOLUMNS, ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE, 0);
+ cii.cbSize = sizeof(cii);
+ cii.hParentGroup = 0;
+ cii.pszText = _T("*** All contacts ***");
+ hInfoItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0);
+ if(SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, 0, 0) != LB_ERR) {
+ clvm_curItem = 0;
+ UpdateFilters();
+ }
+ else
+ clvm_curItem = -1;
+ g_ViewModeOptDlg = TRUE;
+ i = 0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwndDlg, _page2Controls[i++]), SW_HIDE);
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ Utils::enableDlgControl(hwndDlg, IDC_APPLY, FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_AUTOCLEARSPIN, UDM_SETRANGE, 0, MAKELONG(1000, 0));
+ SetWindowText(hwndDlg, TranslateT("Configure view modes"));
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_PROTOGROUPOP:
+ case IDC_GROUPSTATUSOP:
+ case IDC_LASTMESSAGEUNIT:
+ case IDC_LASTMESSAGEOP:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE);
+ break;
+ case IDC_AUTOCLEAR:
+ Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE);
+ break;
+ case IDC_LASTMSG:
+ {
+ int bUseLastMsg = IsDlgButtonChecked(hwndDlg, IDC_LASTMSG);
+ Utils::enableDlgControl(hwndDlg, IDC_LASTMESSAGEOP, bUseLastMsg);
+ Utils::enableDlgControl(hwndDlg, IDC_LASTMESSAGEUNIT, bUseLastMsg);
+ Utils::enableDlgControl(hwndDlg, IDC_LASTMSGVALUE, bUseLastMsg);
+ Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE);
+ break;
+ }
+ case IDC_AUTOCLEARVAL:
+ case IDC_LASTMSGVALUE:
+ if(HIWORD(wParam) == EN_CHANGE && GetFocus() == (HWND)lParam)
+ Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE);
+ break;
+ case IDC_DELETEVIEWMODE:
+ {
+ if(MessageBoxA(0, Translate("Really delete this view mode? This cannot be undone"), Translate("Delete a view mode"), MB_YESNO | MB_ICONQUESTION) == IDYES) {
+ char szSetting[256];
+ int iLen = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETTEXTLEN, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0);
+ if(iLen) {
+ char *szBuf = ( char* )malloc(iLen + 1);
+ if(szBuf) {
+ MCONTACT hContact;
+
+ SendDlgItemMessageA(hwndDlg, IDC_VIEWMODES, LB_GETTEXT, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), (LPARAM)szBuf);
+ mir_snprintf(szSetting, 256, "%c%s_PF", 246, szBuf);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_GF", 246, szBuf);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_SM", 246, szBuf);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_VA", 246, szBuf);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_SSM", 246, szBuf);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ db_unset(NULL, CLVM_MODULE, szBuf);
+ if(!strcmp(cfg::dat.current_viewmode, szBuf) && lstrlenA(szBuf) == lstrlenA(cfg::dat.current_viewmode)) {
+ cfg::dat.bFilterEffective = 0;
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ SetWindowTextA(hwndSelector, Translate("No view mode"));
+ }
+ hContact = db_find_first();
+ while(hContact) {
+ if(cfg::getDword(hContact, "CLVM", szBuf, -1) != -1)
+ cfg::writeDword(hContact, "CLVM", szBuf, 0);
+ hContact = db_find_next(hContact);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_DELETESTRING, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0);
+ if(SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, 0, 0) != LB_ERR) {
+ clvm_curItem = 0;
+ UpdateFilters();
+ }
+ else
+ clvm_curItem = -1;
+ free(szBuf);
+ }
+ }
+ }
+ break;
+ }
+ case IDC_ADDVIEWMODE:
+ {
+ char szBuf[256];
+
+ szBuf[0] = 0;
+ GetDlgItemTextA(hwndDlg, IDC_NEWVIEMODE, szBuf, 256);
+ szBuf[255] = 0;
+
+ if(lstrlenA(szBuf) > 2) {
+ if(cfg::getDword(CLVM_MODULE, szBuf, -1) != -1)
+ MessageBox(0, TranslateT("A view mode with this name does alredy exist"), TranslateT("Duplicate name"), MB_OK);
+ else {
+ int iNewItem = SendDlgItemMessageA(hwndDlg, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)szBuf);
+ if(iNewItem != LB_ERR) {
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, (WPARAM)iNewItem, 0);
+ SaveViewMode(szBuf, _T(""), "", -1, -1, 0, 0, 0, 0);
+ clvm_curItem = iNewItem;
+ UpdateStickies();
+ SendDlgItemMessage(hwndDlg, IDC_PROTOGROUPOP, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUPSTATUSOP, CB_SETCURSEL, 0, 0);
+ }
+ }
+ SetDlgItemTextA(hwndDlg, IDC_NEWVIEMODE, "");
+ }
+ Utils::enableDlgControl(hwndDlg, IDC_ADDVIEWMODE, FALSE);
+ break;
+ }
+ case IDC_CLEARALL:
+ {
+ HANDLE hItem;
+ MCONTACT hContact = db_find_first();
+
+ while(hContact) {
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem)
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, 0);
+ hContact = db_find_next(hContact);
+ }
+ }
+ case IDOK:
+ case IDC_APPLY:
+ SaveState();
+ if(cfg::dat.bFilterEffective)
+ ApplyViewMode(cfg::dat.current_viewmode);
+ if(LOWORD(wParam) == IDOK)
+ DestroyWindow(hwndDlg);
+ break;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ if(LOWORD(wParam) == IDC_NEWVIEMODE && HIWORD(wParam) == EN_CHANGE)
+ Utils::enableDlgControl(hwndDlg, IDC_ADDVIEWMODE, TRUE);
+ if(LOWORD(wParam) == IDC_VIEWMODES && HIWORD(wParam) == LBN_SELCHANGE) {
+ SaveState();
+ clvm_curItem = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0);
+ UpdateFilters();
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case IDC_GROUPS:
+ case IDC_STATUSMODES:
+ case IDC_PROTOCOLS:
+ case IDC_CLIST:
+ if (((LPNMHDR) lParam)->code == NM_CLICK || ((LPNMHDR) lParam)->code == CLN_CHECKCHANGED)
+ Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE);
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ //SetAllContactIcons(GetDlgItem(hwndDlg,IDC_CLIST));
+ //fall through
+ /*
+ case CLN_CONTACTMOVED:
+ SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL);
+ break;
+ case CLN_OPTIONSCHANGED:
+ ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST));
+ break;
+ case CLN_CHECKCHANGED:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam;
+ int typeOfItem = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETITEMTYPE,(WPARAM)nm->hItem, 0);
+ break;
+ }*/
+ case NM_CLICK:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam;
+ DWORD hitFlags;
+ int iImage;
+
+ if(nm->iColumn==-1)
+ break;
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(nm->pt.x,nm->pt.y));
+ if(hItem==NULL) break;
+ if(!(hitFlags&CLCHT_ONITEMEXTRA))
+ break;
+ iImage = SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn,0));
+ if(iImage == nullImage)
+ iImage = nm->iColumn;
+ else if(iImage!=0xFF)
+ iImage = nullImage;
+ SetIconsForColumn(GetDlgItem(hwndDlg,IDC_CLIST),hItem,hInfoItem,nm->iColumn,iImage);
+ //SetListGroupIcons(GetDlgItem(hwndDlg,IDC_CLIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hInfoItem,NULL);
+ break;
+ }
+ }
+ break;
+ case IDC_TAB:
+ if (((LPNMHDR) lParam)->code == TCN_SELCHANGE) {
+ int id = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB));
+ if(id == 0)
+ ShowPage(hwndDlg, 0);
+ else
+ ShowPage(hwndDlg, 1);
+ break;
+ }
+
+ }
+ break;
+ }
+ case WM_DESTROY:
+ ImageList_RemoveAll(himlViewModes);
+ ImageList_Destroy(himlViewModes);
+ g_ViewModeOptDlg = FALSE;
+ break;
+ }
+ return FALSE;
+}
+
+static int menuCounter = 0;
+
+static int FillMenuCallback(char *szSetting)
+{
+ if(szSetting[0] == 246)
+ return 1;
+
+ AppendMenuA(hViewModeMenu, MF_STRING, menuCounter++, szSetting);
+ return 1;
+}
+
+void BuildViewModeMenu()
+{
+ if(hViewModeMenu)
+ DestroyMenu(hViewModeMenu);
+
+ menuCounter = 100;
+ hViewModeMenu = CreatePopupMenu();
+ CLVM_EnumModes(FillMenuCallback);
+
+ if(GetMenuItemCount(hViewModeMenu) > 0)
+ AppendMenuA(hViewModeMenu, MF_SEPARATOR, 0, NULL);
+
+ AppendMenuA(hViewModeMenu, MF_STRING, 10001, Translate("Setup View Modes..."));
+ AppendMenuA(hViewModeMenu, MF_STRING, 10002, Translate("Clear current View Mode"));
+
+}
+
+static UINT _buttons[] = {IDC_RESETMODES, IDC_SELECTMODE, IDC_CONFIGUREMODES, 0};
+
+LRESULT CALLBACK ViewModeFrameWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_CREATE:
+ {
+ HWND hwndButton;
+
+ hwndSelector = CreateWindowEx(0, _T("CLCButtonClass"), _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_SELECTMODE, g_hInst, NULL);
+ SendMessage(hwndSelector, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Select a view mode"), 0);
+ SendMessage(hwndSelector, BM_SETASMENUACTION, 1, 0);
+ hwndButton = CreateWindowEx(0, _T("CLCButtonClass"), _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_CONFIGUREMODES, g_hInst, NULL);
+ SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Setup view modes"), 0);
+ hwndButton = CreateWindowEx(0, _T("CLCButtonClass"), _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_RESETMODES, g_hInst, NULL);
+ SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Clear view mode and return to default display"), 0);
+ SendMessage(hwnd, WM_USER + 100, 0, 0);
+ return FALSE;
+ }
+ case WM_NCCALCSIZE:
+ {
+ BOOL hasTitleBar = wndFrameViewMode ? wndFrameViewMode->TitleBar.ShowTitleBar : 0;
+ return FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam, hasTitleBar);
+ }
+ case WM_NCPAINT:
+ {
+ BOOL hasTitleBar = wndFrameViewMode ? wndFrameViewMode->TitleBar.ShowTitleBar : 0;
+ return FrameNCPaint(hwnd, DefWindowProc, wParam, lParam, hasTitleBar);
+ }
+ case WM_SIZE:
+ {
+ RECT rcCLVMFrame;
+ HDWP PosBatch = BeginDeferWindowPos(3);
+ GetClientRect(hwnd, &rcCLVMFrame);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_RESETMODES), 0,
+ rcCLVMFrame.right - 23, 1, 22, 22, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_CONFIGUREMODES), 0,
+ rcCLVMFrame.right - 46, 1, 22, 22, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_SELECTMODE), 0,
+ 1, 1, rcCLVMFrame.right - 48, 22, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ EndDeferWindowPos(PosBatch);
+ break;
+ }
+ case WM_USER + 100:
+ SendMessage(GetDlgItem(hwnd, IDC_RESETMODES), BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon("core_main_15"));
+ SendMessage(GetDlgItem(hwnd, IDC_CONFIGUREMODES), BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon("core_main_32"));
+ SendMessage(GetDlgItem(hwnd, IDC_SELECTMODE), BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon("core_main_11"));
+ {
+ int bSkinned = cfg::getByte("CLCExt", "bskinned", 0);
+ int i = 0;
+
+ while(_buttons[i] != 0) {
+ SendMessage(GetDlgItem(hwnd, _buttons[i]), BM_SETSKINNED, 0, bSkinned);
+ if(bSkinned) {
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN + 10, 0, 0);
+ }
+ else {
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN, 0, 1);
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN + 10, 0, 1);
+ }
+ i++;
+ }
+ }
+ if(cfg::dat.bFilterEffective)
+ SetWindowTextA(GetDlgItem(hwnd, IDC_SELECTMODE), cfg::dat.current_viewmode);
+ else
+ SetWindowText(GetDlgItem(hwnd, IDC_SELECTMODE), TranslateT("No view mode"));
+ break;
+
+ case WM_ERASEBKGND:
+ return(1);
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ RECT rc;
+ HDC hdcMem;
+ HANDLE hbp = 0;
+
+ GetClientRect(hwnd, &rc);
+ INIT_PAINT(hdc, rc, hdcMem);
+
+ Gfx::drawBGFromSurface(hwnd, rc, hdcMem);
+ FINALIZE_PAINT(hbp, &rc, 0);
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+ case WM_TIMER:
+ {
+ switch(wParam) {
+ case TIMERID_VIEWMODEEXPIRE:
+ {
+ POINT pt;
+ RECT rcCLUI;
+
+ GetWindowRect(pcli->hwndContactList, &rcCLUI);
+ GetCursorPos(&pt);
+ if(PtInRect(&rcCLUI, pt))
+ break;
+
+ KillTimer(hwnd, wParam);
+ if(!cfg::dat.old_viewmode[0])
+ SendMessage(hwnd, WM_COMMAND, IDC_RESETMODES, 0);
+ else
+ ApplyViewMode((const char *)cfg::dat.old_viewmode);
+ break;
+ } }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam)) {
+ case IDC_SELECTMODE:
+ {
+ RECT rc;
+ POINT pt;
+ int selection;
+ MENUITEMINFOA mii = {0};
+ char szTemp[256];
+
+ BuildViewModeMenu();
+ //GetWindowRect(GetDlgItem(hwnd, IDC_SELECTMODE), &rc);
+ GetWindowRect((HWND)lParam, &rc);
+ pt.x = rc.left;
+ pt.y = rc.bottom;
+ selection = TrackPopupMenu(hViewModeMenu,TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL);
+ if(selection) {
+
+ if(selection == 10001)
+ goto clvm_config_command;
+ else if(selection == 10002)
+ goto clvm_reset_command;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STRING;
+ mii.dwTypeData = szTemp;
+ mii.cch = 256;
+ GetMenuItemInfoA(hViewModeMenu, selection, FALSE, &mii);
+ ApplyViewMode(szTemp);
+ }
+ break;
+ }
+ case IDC_RESETMODES:
+clvm_reset_command:
+ cfg::dat.bFilterEffective = 0;
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ SetWindowTextA(GetDlgItem(hwnd, IDC_SELECTMODE), Translate("No view mode"));
+ CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)cfg::dat.boldHideOffline, 0);
+ cfg::dat.boldHideOffline = (BYTE)-1;
+ CLUI::setButtonStates(pcli->hwndContactList);
+ cfg::dat.current_viewmode[0] = 0;
+ cfg::dat.old_viewmode[0] = 0;
+ cfg::writeString(NULL, "CList", "LastViewMode", "");
+ break;
+ case IDC_CONFIGUREMODES:
+clvm_config_command:
+ if(!g_ViewModeOptDlg)
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_OPT_VIEWMODES), 0, DlgProcViewModesSetup, 0);
+ break;
+ }
+ break;
+ }
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
+
+static HWND hCLVMFrame;
+HWND g_hwndViewModeFrame;
+
+void CreateViewModeFrame()
+{
+ CLISTFrame frame = {0};
+ WNDCLASS wndclass = {0};
+
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ViewModeFrameWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = 0;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH) (COLOR_3DFACE);
+ wndclass.lpszMenuName = 0;
+ wndclass.lpszClassName = _T("CLVMFrameWindow");
+
+ RegisterClass(&wndclass);
+
+ ZeroMemory(&frame, sizeof(frame));
+ frame.cbSize = sizeof(frame);
+ frame.tname = _T("View modes");
+ frame.TBtname = TranslateT("View Modes");
+ frame.hIcon = 0;
+ frame.height = 22;
+ frame.Flags=F_VISIBLE|F_SHOWTBTIP|F_NOBORDER|F_TCHAR;
+ frame.align = alBottom;
+ frame.hWnd = CreateWindowEx(0, _T("CLVMFrameWindow"), _T("CLVM"), WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_CLIPCHILDREN, 0, 0, 20, 20, pcli->hwndContactList, (HMENU) 0, g_hInst, NULL);
+ g_hwndViewModeFrame = frame.hWnd;
+ hCLVMFrame = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&frame,(LPARAM)0);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)hCLVMFrame, FU_FMPOS);
+}
+
+const char *MakeVariablesString(const char *src, const char *UIN);
+
+void ApplyViewMode(const char *name)
+{
+ char szSetting[256];
+ DBVARIANT dbv = {0};
+
+ cfg::dat.bFilterEffective = 0;
+
+ mir_snprintf(szSetting, 256, "%c%s_PF", 246, name);
+ if(!cfg::getString(NULL, CLVM_MODULE, szSetting, &dbv)) {
+ if(lstrlenA(dbv.pszVal) >= 2) {
+ strncpy(cfg::dat.protoFilter, dbv.pszVal, sizeof(cfg::dat.protoFilter));
+ cfg::dat.protoFilter[sizeof(cfg::dat.protoFilter) - 1] = 0;
+ cfg::dat.bFilterEffective |= CLVM_FILTER_PROTOS;
+ }
+ mir_free(dbv.pszVal);
+ }
+ mir_snprintf(szSetting, 256, "%c%s_GF", 246, name);
+ if(!cfg::getTString(NULL, CLVM_MODULE, szSetting, &dbv)) {
+ if(lstrlen(dbv.ptszVal) >= 2) {
+ _tcsncpy(cfg::dat.groupFilter, dbv.ptszVal, safe_sizeof(cfg::dat.groupFilter));
+ cfg::dat.groupFilter[safe_sizeof(cfg::dat.groupFilter) - 1] = 0;
+ cfg::dat.bFilterEffective |= CLVM_FILTER_GROUPS;
+ }
+ mir_free(dbv.ptszVal);
+ }
+ mir_snprintf(szSetting, 256, "%c%s_SM", 246, name);
+ cfg::dat.statusMaskFilter = cfg::getDword(CLVM_MODULE, szSetting, -1);
+ if(cfg::dat.statusMaskFilter >= 1)
+ cfg::dat.bFilterEffective |= CLVM_FILTER_STATUS;
+
+ mir_snprintf(szSetting, 256, "%c%s_SSM", 246, name);
+ cfg::dat.stickyMaskFilter = cfg::getDword(CLVM_MODULE, szSetting, -1);
+ if(cfg::dat.stickyMaskFilter != -1)
+ cfg::dat.bFilterEffective |= CLVM_FILTER_STICKYSTATUS;
+
+ /*
+ mir_snprintf(szSetting, 256, "%c%s_VA", 246, name);
+ if(!DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv)) {
+ strncpy(g_CluiData.varFilter, dbv.pszVal, sizeof(g_CluiData.varFilter));
+ g_CluiData.varFilter[sizeof(g_CluiData.varFilter) - 1] = 0;
+ if(lstrlenA(g_CluiData.varFilter) > 10 && ServiceExists(MS_VARS_FORMATSTRING))
+ g_CluiData.bFilterEffective |= CLVM_FILTER_VARIABLES;
+ mir_free(dbv.ptszVal);
+ if(g_CluiData.bFilterEffective & CLVM_FILTER_VARIABLES) {
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ char UIN[256];
+ char *id, *szProto;
+ const char *varstring;
+ char *temp;
+ FORMATINFO fi;
+
+ while(hContact) {
+ szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if(szProto) {
+ id = (char*) CallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ if(id) {
+ if(!DBGetContactSetting(hContact, szProto, id, &dbv)) {
+ if(dbv.type == DBVT_ASCIIZ) {
+ mir_snprintf(UIN, 256, "<%s:%s>", szProto, dbv.pszVal);
+ }
+ else {
+ mir_snprintf(UIN, 256, "<%s:%d>", szProto, dbv.dVal);
+ }
+ varstring = MakeVariablesString(g_CluiData.varFilter, UIN);
+ ZeroMemory(&fi, sizeof(fi));
+ fi.cbSize = sizeof(fi);
+ fi.szFormat = varstring;
+ fi.szSource = "";
+ fi.hContact = 0;
+ temp = (char *)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0);
+ if(temp && atol(temp) > 0)
+ _DebugPopup(hContact, "%s, %d, %d, %d", temp, temp, fi.pCount, fi.eCount);
+ variables_free(temp);
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ }
+ }*/
+
+ cfg::dat.filterFlags = cfg::getDword(CLVM_MODULE, name, 0);
+
+ KillTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE);
+
+ if(cfg::dat.filterFlags & CLVM_AUTOCLEAR) {
+ DWORD timerexpire;
+ mir_snprintf(szSetting, 256, "%c%s_OPT", 246, name);
+ timerexpire = LOWORD(cfg::getDword(CLVM_MODULE, szSetting, 0));
+ strncpy(cfg::dat.old_viewmode, cfg::dat.current_viewmode, 256);
+ cfg::dat.old_viewmode[255] = 0;
+ SetTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE, timerexpire * 1000, NULL);
+ }
+ strncpy(cfg::dat.current_viewmode, name, 256);
+ cfg::dat.current_viewmode[255] = 0;
+
+ if(cfg::dat.filterFlags & CLVM_USELASTMSG) {
+ DWORD unit;
+ int i;
+ BYTE bSaved = cfg::dat.sortOrder[0];
+
+ cfg::dat.sortOrder[0] = SORTBY_LASTMSG;
+ for(i = 0; i < cfg::nextCacheEntry; i++)
+ cfg::eCache[i].dwLastMsgTime = INTSORT_GetLastMsgTime(cfg::eCache[i].hContact);
+
+ cfg::dat.sortOrder[0] = bSaved;
+
+ cfg::dat.bFilterEffective |= CLVM_FILTER_LASTMSG;
+ mir_snprintf(szSetting, 256, "%c%s_LM", 246, name);
+ cfg::dat.lastMsgFilter = cfg::getDword(CLVM_MODULE, szSetting, 0);
+ if(LOBYTE(HIWORD(cfg::dat.lastMsgFilter)))
+ cfg::dat.bFilterEffective |= CLVM_FILTER_LASTMSG_NEWERTHAN;
+ else
+ cfg::dat.bFilterEffective |= CLVM_FILTER_LASTMSG_OLDERTHAN;
+ unit = LOWORD(cfg::dat.lastMsgFilter);
+ switch(HIBYTE(HIWORD(cfg::dat.lastMsgFilter))) {
+ case 0:
+ unit *= 60;
+ break;
+ case 1:
+ unit *= 3600;
+ break;
+ case 2:
+ unit *= 86400;
+ break;
+ }
+ cfg::dat.lastMsgFilter = unit;
+ }
+
+ if(HIWORD(cfg::dat.filterFlags) > 0)
+ cfg::dat.bFilterEffective |= CLVM_STICKY_CONTACTS;
+
+ if(cfg::dat.boldHideOffline == (BYTE)-1)
+ cfg::dat.boldHideOffline = cfg::getByte("CList", "HideOffline", 0);
+
+ CallService(MS_CLIST_SETHIDEOFFLINE, 0, 0);
+ SetWindowTextA(hwndSelector, name);
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ CLUI::setButtonStates(pcli->hwndContactList);
+
+ cfg::writeString(NULL, "CList", "LastViewMode", cfg::dat.current_viewmode);
+}
+
+
diff --git a/plugins/Clist_ng/clist.mak b/plugins/Clist_ng/clist.mak new file mode 100644 index 0000000000..71bf718cae --- /dev/null +++ b/plugins/Clist_ng/clist.mak @@ -0,0 +1,878 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on clist.dsp
+!IF "$(CFG)" == ""
+CFG=clist_nicer - Win32 Release Unicode
+!MESSAGE No configuration specified. Defaulting to clist_nicer - Win32 Release Unicode.
+!ENDIF
+
+!IF "$(CFG)" != "clist_nicer - Win32 Release" && "$(CFG)" != "clist_nicer - Win32 Debug" && "$(CFG)" != "clist_nicer - Win32 Release Unicode" && "$(CFG)" != "clist_nicer - Win32 Debug Unicode"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "clist.mak" CFG="clist_nicer - Win32 Debug Unicode"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "clist_nicer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "clist_nicer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "clist_nicer - Win32 Release Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "clist_nicer - Win32 Debug Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "clist_nicer - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\bin\release\plugins\clist_nicer.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\alphablend.obj"
+ -@erase "$(INTDIR)\clc.obj"
+ -@erase "$(INTDIR)\CLCButton.obj"
+ -@erase "$(INTDIR)\clcidents.obj"
+ -@erase "$(INTDIR)\clcitems.obj"
+ -@erase "$(INTDIR)\clcmsgs.obj"
+ -@erase "$(INTDIR)\clcopts.obj"
+ -@erase "$(INTDIR)\clcpaint.obj"
+ -@erase "$(INTDIR)\clcutils.obj"
+ -@erase "$(INTDIR)\clist.pch"
+ -@erase "$(INTDIR)\clistevents.obj"
+ -@erase "$(INTDIR)\clistmenus.obj"
+ -@erase "$(INTDIR)\clistmod.obj"
+ -@erase "$(INTDIR)\clistopts.obj"
+ -@erase "$(INTDIR)\clistsettings.obj"
+ -@erase "$(INTDIR)\clisttray.obj"
+ -@erase "$(INTDIR)\clnplus.obj"
+ -@erase "$(INTDIR)\clui.obj"
+ -@erase "$(INTDIR)\cluiframes.obj"
+ -@erase "$(INTDIR)\cluiopts.obj"
+ -@erase "$(INTDIR)\cluiservices.obj"
+ -@erase "$(INTDIR)\commonheaders.obj"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\contact.obj"
+ -@erase "$(INTDIR)\coolsblib.obj"
+ -@erase "$(INTDIR)\coolscroll.obj"
+ -@erase "$(INTDIR)\Docking.obj"
+ -@erase "$(INTDIR)\extBackg.obj"
+ -@erase "$(INTDIR)\framesmenu.obj"
+ -@erase "$(INTDIR)\groupmenu.obj"
+ -@erase "$(INTDIR)\init.obj"
+ -@erase "$(INTDIR)\movetogroup.obj"
+ -@erase "$(INTDIR)\resource.res"
+ -@erase "$(INTDIR)\rowheight_funcs.obj"
+ -@erase "$(INTDIR)\statusbar.obj"
+ -@erase "$(INTDIR)\statusfloater.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\viewmodes.obj"
+ -@erase "$(INTDIR)\wallpaper.obj"
+ -@erase "$(OUTDIR)\clist_nicer.exp"
+ -@erase "$(OUTDIR)\clist_nicer.map"
+ -@erase "$(OUTDIR)\clist_nicer.pdb"
+ -@erase "..\..\bin\release\plugins\clist_nicer.dll"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O1 /I "../../include" /I "./include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CLIST_EXPORTS" /Fp"$(INTDIR)\clist.pch" /Yu"commonheaders.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\resource.res" /i "../../include" /i "./include" /d "NDEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\clist.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comctl32.lib shell32.lib ole32.lib comdlg32.lib msimg32.lib advapi32.lib shlwapi.lib /nologo /base:"0x6590000" /dll /incremental:no /pdb:"$(OUTDIR)\clist_nicer.pdb" /map:"$(INTDIR)\clist_nicer.map" /debug /machine:I386 /out:"../../bin/release/plugins/clist_nicer.dll" /implib:"$(OUTDIR)\clist_nicer.lib" /OPT:NOWIN98
+LINK32_OBJS= \
+ "$(INTDIR)\cluiframes.obj" \
+ "$(INTDIR)\framesmenu.obj" \
+ "$(INTDIR)\groupmenu.obj" \
+ "$(INTDIR)\movetogroup.obj" \
+ "$(INTDIR)\alphablend.obj" \
+ "$(INTDIR)\clc.obj" \
+ "$(INTDIR)\CLCButton.obj" \
+ "$(INTDIR)\clcidents.obj" \
+ "$(INTDIR)\clcitems.obj" \
+ "$(INTDIR)\clcmsgs.obj" \
+ "$(INTDIR)\clcopts.obj" \
+ "$(INTDIR)\clcpaint.obj" \
+ "$(INTDIR)\clcutils.obj" \
+ "$(INTDIR)\clistevents.obj" \
+ "$(INTDIR)\clistmenus.obj" \
+ "$(INTDIR)\clistmod.obj" \
+ "$(INTDIR)\clistopts.obj" \
+ "$(INTDIR)\clistsettings.obj" \
+ "$(INTDIR)\clisttray.obj" \
+ "$(INTDIR)\clnplus.obj" \
+ "$(INTDIR)\clui.obj" \
+ "$(INTDIR)\cluiopts.obj" \
+ "$(INTDIR)\cluiservices.obj" \
+ "$(INTDIR)\commonheaders.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\contact.obj" \
+ "$(INTDIR)\Docking.obj" \
+ "$(INTDIR)\extBackg.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\rowheight_funcs.obj" \
+ "$(INTDIR)\statusbar.obj" \
+ "$(INTDIR)\statusfloater.obj" \
+ "$(INTDIR)\viewmodes.obj" \
+ "$(INTDIR)\wallpaper.obj" \
+ "$(INTDIR)\coolsblib.obj" \
+ "$(INTDIR)\coolscroll.obj" \
+ "$(INTDIR)\resource.res"
+
+"..\..\bin\release\plugins\clist_nicer.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "clist_nicer - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : "..\..\bin\debug\plugins\clist_nicer.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\alphablend.obj"
+ -@erase "$(INTDIR)\clc.obj"
+ -@erase "$(INTDIR)\CLCButton.obj"
+ -@erase "$(INTDIR)\clcidents.obj"
+ -@erase "$(INTDIR)\clcitems.obj"
+ -@erase "$(INTDIR)\clcmsgs.obj"
+ -@erase "$(INTDIR)\clcopts.obj"
+ -@erase "$(INTDIR)\clcpaint.obj"
+ -@erase "$(INTDIR)\clcutils.obj"
+ -@erase "$(INTDIR)\clistevents.obj"
+ -@erase "$(INTDIR)\clistmenus.obj"
+ -@erase "$(INTDIR)\clistmod.obj"
+ -@erase "$(INTDIR)\clistopts.obj"
+ -@erase "$(INTDIR)\clistsettings.obj"
+ -@erase "$(INTDIR)\clisttray.obj"
+ -@erase "$(INTDIR)\clnplus.obj"
+ -@erase "$(INTDIR)\clui.obj"
+ -@erase "$(INTDIR)\cluiframes.obj"
+ -@erase "$(INTDIR)\cluiopts.obj"
+ -@erase "$(INTDIR)\cluiservices.obj"
+ -@erase "$(INTDIR)\commonheaders.obj"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\contact.obj"
+ -@erase "$(INTDIR)\coolsblib.obj"
+ -@erase "$(INTDIR)\coolscroll.obj"
+ -@erase "$(INTDIR)\Docking.obj"
+ -@erase "$(INTDIR)\extBackg.obj"
+ -@erase "$(INTDIR)\framesmenu.obj"
+ -@erase "$(INTDIR)\groupmenu.obj"
+ -@erase "$(INTDIR)\init.obj"
+ -@erase "$(INTDIR)\movetogroup.obj"
+ -@erase "$(INTDIR)\resource.res"
+ -@erase "$(INTDIR)\rowheight_funcs.obj"
+ -@erase "$(INTDIR)\statusbar.obj"
+ -@erase "$(INTDIR)\statusfloater.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\viewmodes.obj"
+ -@erase "$(INTDIR)\wallpaper.obj"
+ -@erase "$(OUTDIR)\clist_nicer.exp"
+ -@erase "$(OUTDIR)\clist_nicer.pdb"
+ -@erase "..\..\bin\debug\plugins\clist_nicer.dll"
+ -@erase "..\..\bin\debug\plugins\clist_nicer.ilk"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "./include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CLIST_EXPORTS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\resource.res" /i "../../include" /i "./include" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\clist.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comctl32.lib shell32.lib ole32.lib comdlg32.lib msimg32.lib advapi32.lib delayimp.lib shlwapi.lib /nologo /base:"0x6590000" /dll /incremental:yes /pdb:"$(OUTDIR)\clist_nicer.pdb" /debug /machine:I386 /out:"../../bin/debug/plugins/clist_nicer.dll" /implib:"$(OUTDIR)\clist_nicer.lib" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\cluiframes.obj" \
+ "$(INTDIR)\framesmenu.obj" \
+ "$(INTDIR)\groupmenu.obj" \
+ "$(INTDIR)\movetogroup.obj" \
+ "$(INTDIR)\alphablend.obj" \
+ "$(INTDIR)\clc.obj" \
+ "$(INTDIR)\CLCButton.obj" \
+ "$(INTDIR)\clcidents.obj" \
+ "$(INTDIR)\clcitems.obj" \
+ "$(INTDIR)\clcmsgs.obj" \
+ "$(INTDIR)\clcopts.obj" \
+ "$(INTDIR)\clcpaint.obj" \
+ "$(INTDIR)\clcutils.obj" \
+ "$(INTDIR)\clistevents.obj" \
+ "$(INTDIR)\clistmenus.obj" \
+ "$(INTDIR)\clistmod.obj" \
+ "$(INTDIR)\clistopts.obj" \
+ "$(INTDIR)\clistsettings.obj" \
+ "$(INTDIR)\clisttray.obj" \
+ "$(INTDIR)\clnplus.obj" \
+ "$(INTDIR)\clui.obj" \
+ "$(INTDIR)\cluiopts.obj" \
+ "$(INTDIR)\cluiservices.obj" \
+ "$(INTDIR)\commonheaders.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\contact.obj" \
+ "$(INTDIR)\Docking.obj" \
+ "$(INTDIR)\extBackg.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\rowheight_funcs.obj" \
+ "$(INTDIR)\statusbar.obj" \
+ "$(INTDIR)\statusfloater.obj" \
+ "$(INTDIR)\viewmodes.obj" \
+ "$(INTDIR)\wallpaper.obj" \
+ "$(INTDIR)\coolsblib.obj" \
+ "$(INTDIR)\coolscroll.obj" \
+ "$(INTDIR)\resource.res"
+
+"..\..\bin\debug\plugins\clist_nicer.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "clist_nicer - Win32 Release Unicode"
+
+OUTDIR=.\Release_Unicode
+INTDIR=.\Release_Unicode
+
+ALL : "..\..\bin\Release Unicode\plugins\clist_nicer.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\alphablend.obj"
+ -@erase "$(INTDIR)\clc.obj"
+ -@erase "$(INTDIR)\CLCButton.obj"
+ -@erase "$(INTDIR)\clcidents.obj"
+ -@erase "$(INTDIR)\clcitems.obj"
+ -@erase "$(INTDIR)\clcmsgs.obj"
+ -@erase "$(INTDIR)\clcopts.obj"
+ -@erase "$(INTDIR)\clcpaint.obj"
+ -@erase "$(INTDIR)\clcutils.obj"
+ -@erase "$(INTDIR)\clist.pch"
+ -@erase "$(INTDIR)\clistevents.obj"
+ -@erase "$(INTDIR)\clistmenus.obj"
+ -@erase "$(INTDIR)\clistmod.obj"
+ -@erase "$(INTDIR)\clistopts.obj"
+ -@erase "$(INTDIR)\clistsettings.obj"
+ -@erase "$(INTDIR)\clisttray.obj"
+ -@erase "$(INTDIR)\clnplus.obj"
+ -@erase "$(INTDIR)\clui.obj"
+ -@erase "$(INTDIR)\cluiframes.obj"
+ -@erase "$(INTDIR)\cluiopts.obj"
+ -@erase "$(INTDIR)\cluiservices.obj"
+ -@erase "$(INTDIR)\commonheaders.obj"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\contact.obj"
+ -@erase "$(INTDIR)\coolsblib.obj"
+ -@erase "$(INTDIR)\coolscroll.obj"
+ -@erase "$(INTDIR)\Docking.obj"
+ -@erase "$(INTDIR)\extBackg.obj"
+ -@erase "$(INTDIR)\framesmenu.obj"
+ -@erase "$(INTDIR)\groupmenu.obj"
+ -@erase "$(INTDIR)\init.obj"
+ -@erase "$(INTDIR)\movetogroup.obj"
+ -@erase "$(INTDIR)\resource.res"
+ -@erase "$(INTDIR)\rowheight_funcs.obj"
+ -@erase "$(INTDIR)\statusbar.obj"
+ -@erase "$(INTDIR)\statusfloater.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\viewmodes.obj"
+ -@erase "$(INTDIR)\wallpaper.obj"
+ -@erase "$(OUTDIR)\clist_nicer.exp"
+ -@erase "$(OUTDIR)\clist_nicer.map"
+ -@erase "$(OUTDIR)\clist_nicer.pdb"
+ -@erase "..\..\bin\Release Unicode\plugins\clist_nicer.dll"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O1 /Oy /I "../../include" /I "./include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /D "_USRDLL" /D "CLIST_EXPORTS" /Fp"$(INTDIR)\clist.pch" /Yu"commonheaders.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\resource.res" /i "../../include" /i "./include" /d "NDEBUG" /d "UNICODE"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\clist.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comctl32.lib shell32.lib ole32.lib comdlg32.lib msimg32.lib advapi32.lib shlwapi.lib /nologo /base:"0x6590000" /dll /incremental:no /pdb:"$(OUTDIR)\clist_nicer.pdb" /map:"$(INTDIR)\clist_nicer.map" /debug /machine:I386 /out:"../../bin/Release Unicode/plugins/clist_nicer.dll" /implib:"$(OUTDIR)\clist_nicer.lib" /OPT:NOWIN98
+LINK32_OBJS= \
+ "$(INTDIR)\cluiframes.obj" \
+ "$(INTDIR)\framesmenu.obj" \
+ "$(INTDIR)\groupmenu.obj" \
+ "$(INTDIR)\movetogroup.obj" \
+ "$(INTDIR)\alphablend.obj" \
+ "$(INTDIR)\clc.obj" \
+ "$(INTDIR)\CLCButton.obj" \
+ "$(INTDIR)\clcidents.obj" \
+ "$(INTDIR)\clcitems.obj" \
+ "$(INTDIR)\clcmsgs.obj" \
+ "$(INTDIR)\clcopts.obj" \
+ "$(INTDIR)\clcpaint.obj" \
+ "$(INTDIR)\clcutils.obj" \
+ "$(INTDIR)\clistevents.obj" \
+ "$(INTDIR)\clistmenus.obj" \
+ "$(INTDIR)\clistmod.obj" \
+ "$(INTDIR)\clistopts.obj" \
+ "$(INTDIR)\clistsettings.obj" \
+ "$(INTDIR)\clisttray.obj" \
+ "$(INTDIR)\clnplus.obj" \
+ "$(INTDIR)\clui.obj" \
+ "$(INTDIR)\cluiopts.obj" \
+ "$(INTDIR)\cluiservices.obj" \
+ "$(INTDIR)\commonheaders.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\contact.obj" \
+ "$(INTDIR)\Docking.obj" \
+ "$(INTDIR)\extBackg.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\rowheight_funcs.obj" \
+ "$(INTDIR)\statusbar.obj" \
+ "$(INTDIR)\statusfloater.obj" \
+ "$(INTDIR)\viewmodes.obj" \
+ "$(INTDIR)\wallpaper.obj" \
+ "$(INTDIR)\coolsblib.obj" \
+ "$(INTDIR)\coolscroll.obj" \
+ "$(INTDIR)\resource.res"
+
+"..\..\bin\Release Unicode\plugins\clist_nicer.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "clist_nicer - Win32 Debug Unicode"
+
+OUTDIR=.\Debug_Unicode
+INTDIR=.\Debug_Unicode
+
+ALL : "..\..\bin\Debug Unicode\plugins\clist_nicer.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\alphablend.obj"
+ -@erase "$(INTDIR)\clc.obj"
+ -@erase "$(INTDIR)\CLCButton.obj"
+ -@erase "$(INTDIR)\clcidents.obj"
+ -@erase "$(INTDIR)\clcitems.obj"
+ -@erase "$(INTDIR)\clcmsgs.obj"
+ -@erase "$(INTDIR)\clcopts.obj"
+ -@erase "$(INTDIR)\clcpaint.obj"
+ -@erase "$(INTDIR)\clcutils.obj"
+ -@erase "$(INTDIR)\clistevents.obj"
+ -@erase "$(INTDIR)\clistmenus.obj"
+ -@erase "$(INTDIR)\clistmod.obj"
+ -@erase "$(INTDIR)\clistopts.obj"
+ -@erase "$(INTDIR)\clistsettings.obj"
+ -@erase "$(INTDIR)\clisttray.obj"
+ -@erase "$(INTDIR)\clnplus.obj"
+ -@erase "$(INTDIR)\clui.obj"
+ -@erase "$(INTDIR)\cluiframes.obj"
+ -@erase "$(INTDIR)\cluiopts.obj"
+ -@erase "$(INTDIR)\cluiservices.obj"
+ -@erase "$(INTDIR)\commonheaders.obj"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\contact.obj"
+ -@erase "$(INTDIR)\coolsblib.obj"
+ -@erase "$(INTDIR)\coolscroll.obj"
+ -@erase "$(INTDIR)\Docking.obj"
+ -@erase "$(INTDIR)\extBackg.obj"
+ -@erase "$(INTDIR)\framesmenu.obj"
+ -@erase "$(INTDIR)\groupmenu.obj"
+ -@erase "$(INTDIR)\init.obj"
+ -@erase "$(INTDIR)\movetogroup.obj"
+ -@erase "$(INTDIR)\resource.res"
+ -@erase "$(INTDIR)\rowheight_funcs.obj"
+ -@erase "$(INTDIR)\statusbar.obj"
+ -@erase "$(INTDIR)\statusfloater.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\viewmodes.obj"
+ -@erase "$(INTDIR)\wallpaper.obj"
+ -@erase "$(OUTDIR)\clist_nicer.exp"
+ -@erase "$(OUTDIR)\clist_nicer.pdb"
+ -@erase "..\..\bin\Debug Unicode\plugins\clist_nicer.dll"
+ -@erase "..\..\bin\Debug Unicode\plugins\clist_nicer.ilk"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "./include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "UNICODE" /D "_USRDLL" /D "CLIST_EXPORTS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\resource.res" /i "../../include" /i "./include" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\clist.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comctl32.lib shell32.lib ole32.lib comdlg32.lib msimg32.lib advapi32.lib delayimp.lib shlwapi.lib /nologo /base:"0x6590000" /dll /incremental:yes /pdb:"$(OUTDIR)\clist_nicer.pdb" /debug /machine:I386 /out:"../../bin/Debug Unicode/plugins/clist_nicer.dll" /implib:"$(OUTDIR)\clist_nicer.lib" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\cluiframes.obj" \
+ "$(INTDIR)\framesmenu.obj" \
+ "$(INTDIR)\groupmenu.obj" \
+ "$(INTDIR)\movetogroup.obj" \
+ "$(INTDIR)\alphablend.obj" \
+ "$(INTDIR)\clc.obj" \
+ "$(INTDIR)\CLCButton.obj" \
+ "$(INTDIR)\clcidents.obj" \
+ "$(INTDIR)\clcitems.obj" \
+ "$(INTDIR)\clcmsgs.obj" \
+ "$(INTDIR)\clcopts.obj" \
+ "$(INTDIR)\clcpaint.obj" \
+ "$(INTDIR)\clcutils.obj" \
+ "$(INTDIR)\clistevents.obj" \
+ "$(INTDIR)\clistmenus.obj" \
+ "$(INTDIR)\clistmod.obj" \
+ "$(INTDIR)\clistopts.obj" \
+ "$(INTDIR)\clistsettings.obj" \
+ "$(INTDIR)\clisttray.obj" \
+ "$(INTDIR)\clnplus.obj" \
+ "$(INTDIR)\clui.obj" \
+ "$(INTDIR)\cluiopts.obj" \
+ "$(INTDIR)\cluiservices.obj" \
+ "$(INTDIR)\commonheaders.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\contact.obj" \
+ "$(INTDIR)\Docking.obj" \
+ "$(INTDIR)\extBackg.obj" \
+ "$(INTDIR)\init.obj" \
+ "$(INTDIR)\rowheight_funcs.obj" \
+ "$(INTDIR)\statusbar.obj" \
+ "$(INTDIR)\statusfloater.obj" \
+ "$(INTDIR)\viewmodes.obj" \
+ "$(INTDIR)\wallpaper.obj" \
+ "$(INTDIR)\coolsblib.obj" \
+ "$(INTDIR)\coolscroll.obj" \
+ "$(INTDIR)\resource.res"
+
+"..\..\bin\Debug Unicode\plugins\clist_nicer.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("clist.dep")
+!INCLUDE "clist.dep"
+!ELSE
+!MESSAGE Warning: cannot find "clist.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "clist_nicer - Win32 Release" || "$(CFG)" == "clist_nicer - Win32 Debug" || "$(CFG)" == "clist_nicer - Win32 Release Unicode" || "$(CFG)" == "clist_nicer - Win32 Debug Unicode"
+SOURCE=.\CLUIFrames\cluiframes.cpp
+
+"$(INTDIR)\cluiframes.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\CLUIFrames\framesmenu.cpp
+
+"$(INTDIR)\framesmenu.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\CLUIFrames\groupmenu.cpp
+
+"$(INTDIR)\groupmenu.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\CLUIFrames\movetogroup.cpp
+
+"$(INTDIR)\movetogroup.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\alphablend.cpp
+
+"$(INTDIR)\alphablend.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clc.cpp
+
+"$(INTDIR)\clc.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\CLCButton.cpp
+
+"$(INTDIR)\CLCButton.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clcidents.cpp
+
+"$(INTDIR)\clcidents.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clcitems.cpp
+
+"$(INTDIR)\clcitems.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clcmsgs.cpp
+
+"$(INTDIR)\clcmsgs.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clcopts.cpp
+
+"$(INTDIR)\clcopts.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clcpaint.cpp
+
+"$(INTDIR)\clcpaint.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clcutils.cpp
+
+"$(INTDIR)\clcutils.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clistevents.cpp
+
+"$(INTDIR)\clistevents.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clistmenus.cpp
+
+"$(INTDIR)\clistmenus.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clistmod.cpp
+
+"$(INTDIR)\clistmod.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clistopts.cpp
+
+"$(INTDIR)\clistopts.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clistsettings.cpp
+
+"$(INTDIR)\clistsettings.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clisttray.cpp
+
+"$(INTDIR)\clisttray.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clnplus.cpp
+
+"$(INTDIR)\clnplus.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\clui.cpp
+
+"$(INTDIR)\clui.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\cluiopts.cpp
+
+"$(INTDIR)\cluiopts.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\cluiservices.cpp
+
+"$(INTDIR)\cluiservices.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\commonheaders.cpp
+
+!IF "$(CFG)" == "clist_nicer - Win32 Release"
+
+CPP_SWITCHES=/nologo /MD /W3 /Zi /O1 /I "../../include" /I "./include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CLIST_EXPORTS" /Fp"$(INTDIR)\clist.pch" /Yc"commonheaders.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\commonheaders.obj" "$(INTDIR)\clist.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "clist_nicer - Win32 Debug"
+
+CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "./include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CLIST_EXPORTS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\commonheaders.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "clist_nicer - Win32 Release Unicode"
+
+CPP_SWITCHES=/nologo /MD /W3 /Zi /O1 /Oy /I "../../include" /I "./include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /D "_USRDLL" /D "CLIST_EXPORTS" /Fp"$(INTDIR)\clist.pch" /Yc"commonheaders.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\commonheaders.obj" "$(INTDIR)\clist.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "clist_nicer - Win32 Debug Unicode"
+
+CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "./include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "UNICODE" /D "_USRDLL" /D "CLIST_EXPORTS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\commonheaders.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\SRC\config.cpp
+
+"$(INTDIR)\config.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\contact.cpp
+
+"$(INTDIR)\contact.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\Docking.cpp
+
+"$(INTDIR)\Docking.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\extBackg.cpp
+
+"$(INTDIR)\extBackg.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\init.cpp
+
+"$(INTDIR)\init.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\rowheight_funcs.cpp
+
+"$(INTDIR)\rowheight_funcs.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\statusbar.cpp
+
+"$(INTDIR)\statusbar.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\statusfloater.cpp
+
+"$(INTDIR)\statusfloater.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\viewmodes.cpp
+
+"$(INTDIR)\viewmodes.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\SRC\wallpaper.cpp
+
+"$(INTDIR)\wallpaper.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\resource.rc
+
+"$(INTDIR)\resource.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+SOURCE=.\coolsb\coolsblib.cpp
+
+"$(INTDIR)\coolsblib.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\coolsb\coolscroll.cpp
+
+"$(INTDIR)\coolscroll.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\clist.pch"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
diff --git a/plugins/Clist_ng/clist_ng_10.vcxproj b/plugins/Clist_ng/clist_ng_10.vcxproj new file mode 100644 index 0000000000..1bedfc6465 --- /dev/null +++ b/plugins/Clist_ng/clist_ng_10.vcxproj @@ -0,0 +1,682 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>clist_NG</ProjectName>
+ <ProjectGuid>{A7FED55C-53E1-44B9-B4D6-3A9015839856}</ProjectGuid>
+ <RootNamespace>clist_nicer</RootNamespace>
+ <SccProjectName>
+ </SccProjectName>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccProvider>
+ </SccProvider>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/clist.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\plugins\ExternalAPI;..\..\include;.\agg\include;.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4100;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <MinimalRebuild>true</MinimalRebuild>
+ <SmallerTypeCheck>false</SmallerTypeCheck>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;./include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;gdiplus.lib;d2d1.lib;delayimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <BaseAddress>0x6590000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/clist.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>..\..\plugins\ExternalAPI;..\..\include;.\agg\include;.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <WarningLevel>Level4</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4100;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <OmitFramePointers>true</OmitFramePointers>
+ <MinimalRebuild>true</MinimalRebuild>
+ <SmallerTypeCheck>false</SmallerTypeCheck>
+ <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;./include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;gdiplus.lib;d2d1.lib;delayimp.lib;d2d1.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27X86%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <BaseAddress>0x6c540000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\plugins\ExternalAPI;..\..\include;.\agg\include;.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Optimization>Disabled</Optimization>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>true</MinimalRebuild>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <SmallerTypeCheck>false</SmallerTypeCheck>
+ <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PreprocessorDefinitions>_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>4100;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../include;./include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN64;_AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;gdiplus.lib;d2d1.lib;delayimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <DelayLoadDLLs>gdiplus.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\plugins\ExternalAPI;..\..\include;.\agg\include;.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Optimization>Full</Optimization>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>true</MinimalRebuild>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <SmallerTypeCheck>false</SmallerTypeCheck>
+ <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <PreprocessorDefinitions>_WIN64;NDEBUG;WIN32;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>4100;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../include;./include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN64;_AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;gdiplus.lib;d2d1.lib;d2d1.lib;delayimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="AGG\src\agg_arc.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_arrowhead.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_bezier_arc.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_bspline.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_curves.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_font_win32_tt.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_gsv_text.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_image_filters.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_line_aa_basics.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_line_profile_aa.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_rounded_rect.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_sqrt_tables.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_trans_affine.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_trans_double_path.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_trans_single_path.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_trans_warp_magnifier.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vcgen_bspline.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vcgen_contour.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vcgen_dash.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vcgen_markers_term.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vcgen_smooth_poly1.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vcgen_stroke.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vpgen_clip_polygon.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vpgen_clip_polyline.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\agg_vpgen_segmentator.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="AGG\src\platform\win32\agg_win32_bmp.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
+ <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
+ </ClCompile>
+ <ClCompile Include="CLUIFrames\cluiframes.cpp" />
+ <ClCompile Include="CLUIFrames\movetogroup.cpp" />
+ <ClCompile Include="coolsb\coolsblib.cpp" />
+ <ClCompile Include="coolsb\coolscroll.cpp" />
+ <ClCompile Include="skineditor\skinedit.cpp" />
+ <ClCompile Include="SRC\clc.cpp" />
+ <ClCompile Include="SRC\CLCButton.cpp" />
+ <ClCompile Include="SRC\clcitems.cpp" />
+ <ClCompile Include="SRC\clcmsgs.cpp" />
+ <ClCompile Include="SRC\clcopts.cpp" />
+ <ClCompile Include="SRC\clcpaint.cpp" />
+ <ClCompile Include="SRC\clcutils.cpp" />
+ <ClCompile Include="SRC\clistevents.cpp" />
+ <ClCompile Include="SRC\clistmenus.cpp" />
+ <ClCompile Include="SRC\clistmod.cpp" />
+ <ClCompile Include="SRC\clistopts.cpp" />
+ <ClCompile Include="SRC\clisttray.cpp" />
+ <ClCompile Include="SRC\clui.cpp" />
+ <ClCompile Include="SRC\cluiopts.cpp" />
+ <ClCompile Include="SRC\cluiservices.cpp" />
+ <ClCompile Include="SRC\commonheaders.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\config.cpp" />
+ <ClCompile Include="SRC\contact.cpp" />
+ <ClCompile Include="SRC\Docking.cpp" />
+ <ClCompile Include="SRC\extBackg.cpp" />
+ <ClCompile Include="SRC\gfx.cpp" />
+ <ClCompile Include="SRC\init.cpp" />
+ <ClCompile Include="SRC\rowheight_funcs.cpp" />
+ <ClCompile Include="SRC\skin.cpp" />
+ <ClCompile Include="SRC\statusbar.cpp" />
+ <ClCompile Include="SRC\statusfloater.cpp" />
+ <ClCompile Include="SRC\utils.cpp" />
+ <ClCompile Include="SRC\viewmodes.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="AGG\include\agg_alpha_mask_u8.h" />
+ <ClInclude Include="AGG\include\agg_arc.h" />
+ <ClInclude Include="AGG\include\agg_array.h" />
+ <ClInclude Include="AGG\include\agg_arrowhead.h" />
+ <ClInclude Include="AGG\include\agg_basics.h" />
+ <ClInclude Include="AGG\include\agg_bezier_arc.h" />
+ <ClInclude Include="AGG\include\agg_bitset_iterator.h" />
+ <ClInclude Include="AGG\include\agg_blur.h" />
+ <ClInclude Include="AGG\include\agg_bounding_rect.h" />
+ <ClInclude Include="AGG\include\agg_bspline.h" />
+ <ClInclude Include="AGG\include\agg_clip_liang_barsky.h" />
+ <ClInclude Include="AGG\include\agg_color_gray.h" />
+ <ClInclude Include="AGG\include\agg_color_rgba.h" />
+ <ClInclude Include="AGG\include\agg_config.h" />
+ <ClInclude Include="AGG\include\agg_conv_adaptor_vcgen.h" />
+ <ClInclude Include="AGG\include\agg_conv_adaptor_vpgen.h" />
+ <ClInclude Include="AGG\include\agg_conv_bspline.h" />
+ <ClInclude Include="AGG\include\agg_conv_clip_polygon.h" />
+ <ClInclude Include="AGG\include\agg_conv_clip_polyline.h" />
+ <ClInclude Include="AGG\include\agg_conv_close_polygon.h" />
+ <ClInclude Include="AGG\include\agg_conv_concat.h" />
+ <ClInclude Include="AGG\include\agg_conv_contour.h" />
+ <ClInclude Include="AGG\include\agg_conv_curve.h" />
+ <ClInclude Include="AGG\include\agg_conv_dash.h" />
+ <ClInclude Include="AGG\include\agg_conv_gpc.h" />
+ <ClInclude Include="AGG\include\agg_conv_marker.h" />
+ <ClInclude Include="AGG\include\agg_conv_marker_adaptor.h" />
+ <ClInclude Include="AGG\include\agg_conv_segmentator.h" />
+ <ClInclude Include="AGG\include\agg_conv_shorten_path.h" />
+ <ClInclude Include="AGG\include\agg_conv_smooth_poly1.h" />
+ <ClInclude Include="AGG\include\agg_conv_stroke.h" />
+ <ClInclude Include="AGG\include\agg_conv_transform.h" />
+ <ClInclude Include="AGG\include\agg_conv_unclose_polygon.h" />
+ <ClInclude Include="AGG\include\agg_curves.h" />
+ <ClInclude Include="AGG\include\agg_dda_line.h" />
+ <ClInclude Include="AGG\include\agg_ellipse.h" />
+ <ClInclude Include="AGG\include\agg_ellipse_bresenham.h" />
+ <ClInclude Include="AGG\include\agg_embedded_raster_fonts.h" />
+ <ClInclude Include="AGG\include\agg_font_cache_manager.h" />
+ <ClInclude Include="AGG\include\agg_font_freetype.h" />
+ <ClInclude Include="AGG\include\agg_font_win32_tt.h" />
+ <ClInclude Include="AGG\include\agg_gamma_functions.h" />
+ <ClInclude Include="AGG\include\agg_gamma_lut.h" />
+ <ClInclude Include="AGG\include\agg_glyph_raster_bin.h" />
+ <ClInclude Include="AGG\include\agg_gradient_lut.h" />
+ <ClInclude Include="AGG\include\agg_gsv_text.h" />
+ <ClInclude Include="AGG\include\agg_image_accessors.h" />
+ <ClInclude Include="AGG\include\agg_image_filters.h" />
+ <ClInclude Include="AGG\include\agg_line_aa_basics.h" />
+ <ClInclude Include="AGG\include\agg_math.h" />
+ <ClInclude Include="AGG\include\agg_math_stroke.h" />
+ <ClInclude Include="AGG\include\agg_path_length.h" />
+ <ClInclude Include="AGG\include\agg_path_storage.h" />
+ <ClInclude Include="AGG\include\agg_path_storage_integer.h" />
+ <ClInclude Include="AGG\include\agg_pattern_filters_rgba.h" />
+ <ClInclude Include="AGG\include\agg_pixfmt_amask_adaptor.h" />
+ <ClInclude Include="AGG\include\agg_pixfmt_gray.h" />
+ <ClInclude Include="AGG\include\agg_pixfmt_rgb.h" />
+ <ClInclude Include="AGG\include\agg_pixfmt_rgba.h" />
+ <ClInclude Include="AGG\include\agg_pixfmt_rgb_packed.h" />
+ <ClInclude Include="AGG\include\agg_pixfmt_transposer.h" />
+ <ClInclude Include="AGG\include\agg_rasterizer_cells_aa.h" />
+ <ClInclude Include="AGG\include\agg_rasterizer_compound_aa.h" />
+ <ClInclude Include="AGG\include\agg_rasterizer_outline.h" />
+ <ClInclude Include="AGG\include\agg_rasterizer_outline_aa.h" />
+ <ClInclude Include="AGG\include\agg_rasterizer_scanline_aa.h" />
+ <ClInclude Include="AGG\include\agg_rasterizer_sl_clip.h" />
+ <ClInclude Include="AGG\include\agg_renderer_base.h" />
+ <ClInclude Include="AGG\include\agg_renderer_markers.h" />
+ <ClInclude Include="AGG\include\agg_renderer_mclip.h" />
+ <ClInclude Include="AGG\include\agg_renderer_outline_aa.h" />
+ <ClInclude Include="AGG\include\agg_renderer_outline_image.h" />
+ <ClInclude Include="AGG\include\agg_renderer_primitives.h" />
+ <ClInclude Include="AGG\include\agg_renderer_raster_text.h" />
+ <ClInclude Include="AGG\include\agg_renderer_scanline.h" />
+ <ClInclude Include="AGG\include\agg_rendering_buffer.h" />
+ <ClInclude Include="AGG\include\agg_rendering_buffer_dynarow.h" />
+ <ClInclude Include="AGG\include\agg_rounded_rect.h" />
+ <ClInclude Include="AGG\include\agg_scanline_bin.h" />
+ <ClInclude Include="AGG\include\agg_scanline_boolean_algebra.h" />
+ <ClInclude Include="AGG\include\agg_scanline_p.h" />
+ <ClInclude Include="AGG\include\agg_scanline_storage_aa.h" />
+ <ClInclude Include="AGG\include\agg_scanline_storage_bin.h" />
+ <ClInclude Include="AGG\include\agg_scanline_u.h" />
+ <ClInclude Include="AGG\include\agg_shorten_path.h" />
+ <ClInclude Include="AGG\include\agg_simul_eq.h" />
+ <ClInclude Include="AGG\include\agg_span_allocator.h" />
+ <ClInclude Include="AGG\include\agg_span_converter.h" />
+ <ClInclude Include="AGG\include\agg_span_gouraud.h" />
+ <ClInclude Include="AGG\include\agg_span_gouraud_gray.h" />
+ <ClInclude Include="AGG\include\agg_span_gouraud_rgba.h" />
+ <ClInclude Include="AGG\include\agg_span_gradient.h" />
+ <ClInclude Include="AGG\include\agg_span_gradient_alpha.h" />
+ <ClInclude Include="AGG\include\agg_span_image_filter.h" />
+ <ClInclude Include="AGG\include\agg_span_image_filter_gray.h" />
+ <ClInclude Include="AGG\include\agg_span_image_filter_rgb.h" />
+ <ClInclude Include="AGG\include\agg_span_image_filter_rgba.h" />
+ <ClInclude Include="AGG\include\agg_span_interpolator_adaptor.h" />
+ <ClInclude Include="AGG\include\agg_span_interpolator_linear.h" />
+ <ClInclude Include="AGG\include\agg_span_interpolator_persp.h" />
+ <ClInclude Include="AGG\include\agg_span_interpolator_trans.h" />
+ <ClInclude Include="AGG\include\agg_span_pattern_gray.h" />
+ <ClInclude Include="AGG\include\agg_span_pattern_rgb.h" />
+ <ClInclude Include="AGG\include\agg_span_pattern_rgba.h" />
+ <ClInclude Include="AGG\include\agg_span_solid.h" />
+ <ClInclude Include="AGG\include\agg_span_subdiv_adaptor.h" />
+ <ClInclude Include="AGG\include\agg_trans_affine.h" />
+ <ClInclude Include="AGG\include\agg_trans_bilinear.h" />
+ <ClInclude Include="AGG\include\agg_trans_double_path.h" />
+ <ClInclude Include="AGG\include\agg_trans_perspective.h" />
+ <ClInclude Include="AGG\include\agg_trans_single_path.h" />
+ <ClInclude Include="AGG\include\agg_trans_viewport.h" />
+ <ClInclude Include="AGG\include\agg_trans_warp_magnifier.h" />
+ <ClInclude Include="AGG\include\agg_vcgen_bspline.h" />
+ <ClInclude Include="AGG\include\agg_vcgen_contour.h" />
+ <ClInclude Include="AGG\include\agg_vcgen_dash.h" />
+ <ClInclude Include="AGG\include\agg_vcgen_markers_term.h" />
+ <ClInclude Include="AGG\include\agg_vcgen_smooth_poly1.h" />
+ <ClInclude Include="AGG\include\agg_vcgen_stroke.h" />
+ <ClInclude Include="AGG\include\agg_vcgen_vertex_sequence.h" />
+ <ClInclude Include="AGG\include\agg_vertex_sequence.h" />
+ <ClInclude Include="AGG\include\agg_vpgen_clip_polygon.h" />
+ <ClInclude Include="AGG\include\agg_vpgen_clip_polyline.h" />
+ <ClInclude Include="AGG\include\agg_vpgen_segmentator.h" />
+ <ClInclude Include="AGG\include\platform\agg_platform_support.h" />
+ <ClInclude Include="AGG\include\platform\win32\agg_win32_bmp.h" />
+ <ClInclude Include="AGG\include\util\agg_color_conv.h" />
+ <ClInclude Include="AGG\include\util\agg_color_conv_rgb16.h" />
+ <ClInclude Include="AGG\include\util\agg_color_conv_rgb8.h" />
+ <ClInclude Include="CLUIFrames\cluiframes.h" />
+ <ClInclude Include="coolsb\coolsb_internal.h" />
+ <ClInclude Include="coolsb\coolsblib.h" />
+ <ClInclude Include="coolsb\coolscroll.h" />
+ <ClInclude Include="coolsb\userdefs.h" />
+ <ClInclude Include="INCLUDE\clc.h" />
+ <ClInclude Include="INCLUDE\clist.h" />
+ <ClInclude Include="INCLUDE\clui.h" />
+ <ClInclude Include="INCLUDE\commonheaders.h" />
+ <ClInclude Include="include\config.h" />
+ <ClInclude Include="INCLUDE\gfx.h" />
+ <ClInclude Include="INCLUDE\m_cln_skinedit.h" />
+ <ClInclude Include="INCLUDE\resource.h" />
+ <ClInclude Include="INCLUDE\rowheight_funcs.h" />
+ <ClInclude Include="INCLUDE\skin.h" />
+ <ClInclude Include="INCLUDE\utils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="baseskin\back.png" />
+ <None Include="baseskin\base.cng" />
+ <None Include="baseskin\glyphs.png" />
+ <None Include="res\accounts.ico" />
+ <None Include="res\addgoupp.ico" />
+ <None Include="res\arrow-down.ico" />
+ <None Include="res\overlay\away.ico" />
+ <None Include="res\blank.ico" />
+ <None Include="res\overlay\chat.ico" />
+ <None Include="res\connecting.ico" />
+ <None Include="res\delete.ico" />
+ <None Include="res\overlay\dnd.ico" />
+ <None Include="res\dragcopy.cur" />
+ <None Include="res\dropuser.cur" />
+ <None Include="res\find.ico" />
+ <None Include="res\groups.ico" />
+ <None Include="res\hyperlin.cur" />
+ <None Include="res\invisible.ico" />
+ <None Include="res\overlay\invisible.ico" />
+ <None Include="res\overlay\lunch.ico" />
+ <None Include="res\menu.ico" />
+ <None Include="res\minimize.ico" />
+ <None Include="res\overlay\NA.ico" />
+ <None Include="res\notick.ico" />
+ <None Include="res\notick1.ico" />
+ <None Include="res\overlay\occupied.ico" />
+ <None Include="res\overlay\offline.ico" />
+ <None Include="res\online.ico" />
+ <None Include="res\overlay\online.ico" />
+ <None Include="res\options.ico" />
+ <None Include="res\options_clvm.ico" />
+ <None Include="res\overlay\phone.ico" />
+ <None Include="res\rename.ico" />
+ <None Include="res\slist.ico" />
+ <None Include="res\sounds_off.ico" />
+ <None Include="res\sounds_on.ico" />
+ <None Include="res\tabsrmm_menu.ico" />
+ <None Include="res\visible.ico" />
+ <None Include="docs\CHANGELOG" />
+ <None Include="docs\license.txt" />
+ <None Include="docs\README" />
+ <None Include="docs\Skinning.HOWTO" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/plugins/Clist_ng/clist_ng_10.vcxproj.user b/plugins/Clist_ng/clist_ng_10.vcxproj.user new file mode 100644 index 0000000000..695b5c78b9 --- /dev/null +++ b/plugins/Clist_ng/clist_ng_10.vcxproj.user @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file diff --git a/plugins/Clist_ng/coolsb/coolsb.dsp b/plugins/Clist_ng/coolsb/coolsb.dsp new file mode 100644 index 0000000000..34e7a537a1 --- /dev/null +++ b/plugins/Clist_ng/coolsb/coolsb.dsp @@ -0,0 +1,92 @@ +# Microsoft Developer Studio Project File - Name="coolsb" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=coolsb - Win32 Debug
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
+!MESSAGE
+!MESSAGE NMAKE /f "coolsb.mak".
+!MESSAGE
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
+!MESSAGE
+!MESSAGE NMAKE /f "coolsb.mak" CFG="coolsb - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "coolsb - Win32 Release" (basierend auf "Win32 (x86) Static Library")
+!MESSAGE "coolsb - Win32 Debug" (basierend auf "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "coolsb - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "coolsb - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "coolsb - Win32 Release"
+# Name "coolsb - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/plugins/Clist_ng/coolsb/coolsb.plg b/plugins/Clist_ng/coolsb/coolsb.plg new file mode 100644 index 0000000000..823664af18 --- /dev/null +++ b/plugins/Clist_ng/coolsb/coolsb.plg @@ -0,0 +1,31 @@ +<html>
+<body>
+<pre>
+<h1>Erstellungsprotokoll</h1>
+<h3>
+--------------------Konfiguration: coolsb - Win32 Debug--------------------
+</h3>
+<h3>Befehlszeilen</h3>
+Erstellen der temporären Datei "c:\temp\RSPCFBF.tmp" mit Inhalten
+[
+/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /Fp"Debug/coolsb.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
+"C:\tabsrmm\trunk\miranda\plugins\clist_nicer\coolsb\coolscroll.cpp"
+"C:\tabsrmm\trunk\miranda\plugins\clist_nicer\coolsb\coolsblib.cpp"
+]
+Creating command line "cl.exe @c:\temp\RSPCFBF.tmp"
+Erstellen der Befehlzeile "link.exe -lib /nologo /out:"Debug\coolsb.lib" .\Debug\coolscroll.obj .\Debug\coolsblib.obj "
+<h3>Ausgabefenster</h3>
+Kompilierung läuft...
+coolscroll.cpp
+c:\tabsrmm\trunk\miranda\plugins\clist_nicer\coolsb\coolscroll.cpp(49) : fatal error C1083: Include-Datei kann nicht geöffnet werden: 'commonheaders.h': No such file or directory
+coolsblib.cpp
+c:\tabsrmm\trunk\miranda\plugins\clist_nicer\coolsb\coolsblib.cpp(32) : fatal error C1083: Include-Datei kann nicht geöffnet werden: 'commonheaders.h': No such file or directory
+Fehler beim Ausführen von cl.exe.
+
+
+
+<h3>Ergebnisse</h3>
+coolsb.lib - 2 Fehler, 0 Warnung(en)
+</pre>
+</body>
+</html>
diff --git a/plugins/Clist_ng/coolsb/coolsb_internal.h b/plugins/Clist_ng/coolsb/coolsb_internal.h new file mode 100644 index 0000000000..8a394f8a51 --- /dev/null +++ b/plugins/Clist_ng/coolsb/coolsb_internal.h @@ -0,0 +1,95 @@ +#ifndef _COOLSB_INTERNAL_INCLUDED
+#define _COOLSB_INTERNAL_INCLUDED
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <windows.h>
+
+//
+// SCROLLBAR datatype. There are two of these structures per window
+//
+typedef struct
+{
+ UINT fScrollFlags; //flags
+ BOOL fScrollVisible; //if this scrollbar visible?
+ SCROLLINFO scrollInfo; //positional data (range, position, page size etc)
+
+ int nArrowLength; //perpendicular size (height of a horizontal, width of a vertical)
+ int nArrowWidth; //parallel size (width of horz, height of vert)
+
+ //data for inserted buttons
+ SCROLLBUT sbButtons[MAX_COOLSB_BUTS];
+ int nButtons;
+ int nButSizeBefore; //size to the left / above the bar
+ int nButSizeAfter; //size to the right / below the bar
+
+ BOOL fButVisibleBefore; //if the buttons to the left are visible
+ BOOL fButVisibleAfter; //if the buttons to the right are visible
+
+ int nBarType; //SB_HORZ / SB_VERT
+
+ UINT fFlatScrollbar; //do we display flat scrollbars?
+ int nMinThumbSize;
+
+} SCROLLBAR;
+
+//
+// Container structure for a cool scrollbar window.
+//
+typedef struct
+{
+ UINT bars; //which of the scrollbars do we handle? SB_VERT / SB_HORZ / SB_BOTH
+ WNDPROC oldproc; //old window procedure to call for every message
+
+ SCROLLBAR sbarHorz; //one scrollbar structure each for
+ SCROLLBAR sbarVert; //the horizontal and vertical scrollbars
+
+ BOOL fThumbTracking; // are we currently thumb-tracking??
+ BOOL fLeftScrollbar; // support the WS_EX_LEFTSCROLLBAR style
+
+ HWND hwndToolTip; // tooltip support!!!
+
+ //size of the window borders
+ int cxLeftEdge, cxRightEdge;
+ int cyTopEdge, cyBottomEdge;
+
+ // To prevent calling original WindowProc in response
+ // to our own temporary style change (fixes TreeView problem)
+ BOOL bPreventStyleChange;
+
+} SCROLLWND;
+
+
+//
+// PRIVATE INTERNAL FUNCTIONS
+//
+SCROLLWND *GetScrollWndFromHwnd(HWND hwnd);
+#define InvertCOLORREF(col) ((~col) & 0x00ffffff)
+
+#define COOLSB_TIMERID1 65533 //initial timer
+#define COOLSB_TIMERID2 65534 //scroll message timer
+#define COOLSB_TIMERID3 -14 //mouse hover timer
+#define COOLSB_TIMERINTERVAL1 300
+#define COOLSB_TIMERINTERVAL2 55
+#define COOLSB_TIMERINTERVAL3 20 //mouse hover time
+
+
+//
+// direction: 0 - same axis as scrollbar (i.e. width of a horizontal bar)
+// 1 - perpendicular dimesion (i.e. height of a horizontal bar)
+//
+#define SM_CXVERTSB 1
+#define SM_CYVERTSB 0
+#define SM_CXHORZSB 0
+#define SM_CYHORZSB 1
+#define SM_SCROLL_WIDTH 1
+#define SM_SCROLL_LENGTH 0
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/plugins/Clist_ng/coolsb/coolsblib.cpp b/plugins/Clist_ng/coolsb/coolsblib.cpp new file mode 100644 index 0000000000..e5da7f7605 --- /dev/null +++ b/plugins/Clist_ng/coolsb/coolsblib.cpp @@ -0,0 +1,1002 @@ +/*
+
+ Cool Scrollbar Library Version 1.2
+
+ Module: coolsblib.c
+ Copyright (c) J Brown 2001
+
+ This code is freeware, however, you may not publish
+ this code elsewhere or charge any money for it. This code
+ is supplied as-is. I make no guarantees about the suitability
+ of this code - use at your own risk.
+
+ It would be nice if you credited me, in the event
+ that you use this code in a product.
+
+ VERSION HISTORY:
+
+ V1.2: TreeView problem fixed by Diego Tartara
+ Small problem in thumbsize calculation also fixed (thanks Diego!)
+
+ V1.1: Added support for Right-left windows
+ Changed calling convention of APIs to WINAPI (__stdcall)
+ Completely standalone (no need for c-runtime)
+
+ V1.0: Apr 2001: Initial Version
+
+*/
+
+#define _WIN32_WINNT 0x0502
+#define _WIN32_IE 0x0501
+
+#include <commonheaders.h>
+#include "coolscroll.h"
+#include "userdefs.h"
+#include "coolsb_internal.h"
+
+static wchar_t szPropStr[] = _T("CoolSBSubclassPtr");
+
+LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+SCROLLWND *GetScrollWndFromHwnd(HWND hwnd)
+{
+ return (SCROLLWND *)GetProp(hwnd, szPropStr);
+}
+
+SCROLLBAR *GetScrollBarFromHwnd(HWND hwnd, UINT nBar)
+{
+ SCROLLWND *sw = GetScrollWndFromHwnd(hwnd);
+
+ if(!sw) return 0;
+
+ if(nBar == SB_HORZ)
+ return &sw->sbarHorz;
+ else if(nBar == SB_VERT)
+ return &sw->sbarVert;
+ else
+ return 0;
+}
+
+BOOL WINAPI CoolSB_IsCoolScrollEnabled(HWND hwnd)
+{
+ if(GetScrollWndFromHwnd(hwnd))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+BOOL GetScrollRect(SCROLLWND *sw, UINT nBar, HWND hwnd, RECT *rect);
+
+//
+// Special support for USER32.DLL patching (using Detours library)
+// The only place we call a real scrollbar API is in InitializeCoolSB,
+// where we call EnableScrollbar.
+//
+// We HAVE to call the origial EnableScrollbar function,
+// so we need to be able to set a pointer to this func when using
+// using Detours (or any other LIB??)
+//
+
+typedef BOOL (WINAPI *WPROC)(HWND, UINT, UINT);
+
+static WPROC pEnableScrollBar = 0;
+
+void WINAPI CoolSB_SetESBProc(WPROC proc)
+{
+ pEnableScrollBar = proc;
+}
+//
+//
+
+static void RedrawNonClient(HWND hwnd, BOOL fFrameChanged)
+{
+ if(fFrameChanged == FALSE)
+ {
+ /*
+ RECT rect;
+ HRGN hrgn1, hrgn2;
+
+ SCROLLWND *sw = GetScrollWndFromHwnd(hwnd);
+
+ GetScrollRect(sw, SB_HORZ, hwnd, &rect);
+ hrgn1 = CreateRectRgnIndirect(&rect);
+
+ GetScrollRect(sw, SB_VERT, hwnd, &rect);
+ hrgn2 = CreateRectRgnIndirect(&rect);
+
+ CombineRgn(hrgn1, hrgn2, hrgn1, RGN_OR);
+
+ SendMessage(hwnd, WM_NCPAINT, (WPARAM)hrgn1, 0);
+
+ DeleteObject(hrgn1);
+ DeleteObject(hrgn2);*/
+
+ SendMessage(hwnd, WM_NCPAINT, (WPARAM)1, 0);
+ }
+ else
+ {
+ SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE
+ | SWP_FRAMECHANGED | SWP_DRAWFRAME);
+ }
+}
+
+//
+// return the default minimum size of a scrollbar thumb
+//
+int WINAPI CoolSB_GetDefaultMinThumbSize(void)
+{
+ DWORD dwVersion = GetVersion();
+
+ // set the minimum thumb size for a scrollbar. This
+ // differs between NT4 and 2000, so need to check to see
+ // which platform we are running under
+ if(dwVersion < 0x80000000) // Windows NT/2000
+ {
+ if(LOBYTE(LOWORD(dwVersion)) >= 5)
+ return MINTHUMBSIZE_2000;
+ else
+ return MINTHUMBSIZE_NT4;
+ }
+ else
+ {
+ return MINTHUMBSIZE_NT4;
+ }
+}
+
+static SCROLLINFO *GetScrollInfoFromHwnd(HWND hwnd, int fnBar)
+{
+ SCROLLBAR *sb = GetScrollBarFromHwnd(hwnd, fnBar);
+
+ if(sb == 0)
+ return FALSE;
+
+ if(fnBar == SB_HORZ)
+ {
+ return &sb->scrollInfo;
+ }
+ else if(fnBar == SB_VERT)
+ {
+ return &sb->scrollInfo;
+ }
+ else
+ return NULL;
+}
+//
+// Initialize the cool scrollbars for a window by subclassing it
+// and using the coolsb window procedure instead
+//
+BOOL WINAPI InitializeCoolSB(HWND hwnd)
+{
+ SCROLLWND *sw;
+ SCROLLINFO *si;
+ INITCOMMONCONTROLSEX ice;
+ TOOLINFO ti;
+ RECT rect;
+ DWORD dwCurStyle;
+ //BOOL fDisabled;
+
+ if(pEnableScrollBar == 0)
+ pEnableScrollBar = EnableScrollBar;
+
+ GetClientRect(hwnd, &rect);
+
+ //if we have already initialized Cool Scrollbars for this window,
+ //then stop the user from doing it again
+ if(GetScrollWndFromHwnd(hwnd) != 0)
+ {
+ return FALSE;
+ }
+
+ //allocate a private scrollbar structure which we
+ //will use to keep track of the scrollbar data
+ sw = (SCROLLWND *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SCROLLWND));
+
+ si = &sw->sbarHorz.scrollInfo;
+ si->cbSize = sizeof(SCROLLINFO);
+ si->fMask = SIF_ALL;
+ GetScrollInfo(hwnd, SB_HORZ, si);
+
+ si = &sw->sbarVert.scrollInfo;
+ si->cbSize = sizeof(SCROLLINFO);
+ si->fMask = SIF_ALL;
+ GetScrollInfo(hwnd, SB_VERT, si);
+
+ //check to see if the window has left-aligned scrollbars
+ if(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)
+ sw->fLeftScrollbar = TRUE;
+ else
+ sw->fLeftScrollbar = FALSE;
+
+ dwCurStyle = GetWindowLong(hwnd, GWL_STYLE);
+
+ SetProp(hwnd, szPropStr, (HANDLE)sw);
+
+ //try to enable the scrollbar arrows - if the return value is
+ //non-zero, then the scrollbars were previously disabled
+ //fDisabled = pEnableScrollBar(hwnd, SB_HORZ, ESB_ENABLE_BOTH);
+
+ //scrollbars will automatically get enabled, even if
+ //they aren't to start with....sorry, but there isn't an
+ //easy alternative.
+ if(dwCurStyle & WS_HSCROLL)
+ sw->sbarHorz.fScrollFlags = CSBS_VISIBLE;
+
+ if(dwCurStyle & WS_VSCROLL)
+ sw->sbarVert.fScrollFlags = CSBS_VISIBLE;
+
+ //need to be able to distinguish between horizontal and vertical
+ //scrollbars in some instances
+ sw->sbarHorz.nBarType = SB_HORZ;
+ sw->sbarVert.nBarType = SB_VERT;
+
+ sw->sbarHorz.fFlatScrollbar = CSBS_NORMAL;
+ sw->sbarVert.fFlatScrollbar = CSBS_NORMAL;
+
+ //set the default arrow sizes for the scrollbars
+ sw->sbarHorz.nArrowLength = SYSTEM_METRIC;
+ sw->sbarHorz.nArrowWidth = SYSTEM_METRIC;
+ sw->sbarVert.nArrowLength = SYSTEM_METRIC;
+ sw->sbarVert.nArrowWidth = SYSTEM_METRIC;
+
+ sw->bPreventStyleChange = FALSE;
+
+ sw->oldproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)CoolSBWndProc);
+
+ CoolSB_SetMinThumbSize(hwnd, SB_BOTH, CoolSB_GetDefaultMinThumbSize());
+
+#ifdef COOLSB_TOOLTIPS
+ ice.dwSize = sizeof(ice);
+ ice.dwICC = ICC_BAR_CLASSES;
+ InitCommonControlsEx(&ice);
+
+ sw->hwndToolTip = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, TOOLTIPS_CLASS, _T(""),
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hwnd, NULL, GetModuleHandle(0),
+ NULL);
+
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.uFlags = TTF_IDISHWND;
+ ti.hwnd = hwnd;
+ ti.uId = (UINT)hwnd;
+ ti.lpszText = LPSTR_TEXTCALLBACK;
+ ti.hinst = GetModuleHandle(0);
+
+ SendMessage(sw->hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
+
+#else
+
+ UNREFERENCED_PARAMETER(ice);
+ UNREFERENCED_PARAMETER(ti);
+ sw->hwndToolTip = 0;
+
+#endif
+
+ //send the window a frame changed message to update the scrollbars
+ RedrawNonClient(hwnd, TRUE);
+
+ return TRUE;
+}
+
+BOOL WINAPI CoolSB_EnableScrollBar (HWND hwnd, int wSBflags, UINT wArrows)
+{
+ SCROLLBAR *sbar;
+ UINT oldstate;
+ BOOL bFailed = FALSE;
+
+ if(!CoolSB_IsCoolScrollEnabled(hwnd))
+ return EnableScrollBar(hwnd, wSBflags, wArrows);
+
+ if((wSBflags == SB_HORZ || wSBflags == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
+ {
+ oldstate = sbar->fScrollFlags;
+
+ //clear any existing state, and OR in the disabled flags
+ sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows;
+
+ if(oldstate == sbar->fScrollFlags)
+ bFailed = TRUE;
+
+ }
+
+ if((wSBflags == SB_VERT || wSBflags == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
+ {
+ oldstate = sbar->fScrollFlags;
+
+ //clear any existing state, and OR in the disabled flags
+ sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows;
+
+ if(oldstate == sbar->fScrollFlags)
+ bFailed = TRUE;
+ }
+
+ return !bFailed;
+}
+
+BOOL WINAPI CoolSB_GetScrollBarInfo(HWND hwnd)
+{
+// SCROLLBARINFO sbi; not defined in winuser.h
+ return FALSE;
+}
+
+BOOL WINAPI CoolSB_GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
+{
+ SCROLLINFO *mysi;
+ BOOL copied = FALSE;
+
+ if(!lpsi)
+ return FALSE;
+
+ if(!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar)))
+ {
+ return GetScrollInfo(hwnd, fnBar, lpsi);
+ }
+
+ if(lpsi->fMask & SIF_PAGE)
+ {
+ lpsi->nPage = mysi->nPage;
+ copied = TRUE;
+ }
+
+ if(lpsi->fMask & SIF_POS)
+ {
+ lpsi->nPos = mysi->nPos;
+ copied = TRUE;
+ }
+
+ if(lpsi->fMask & SIF_TRACKPOS)
+ {
+ lpsi->nTrackPos = mysi->nTrackPos;
+ copied = TRUE;
+ }
+
+ if(lpsi->fMask & SIF_RANGE)
+ {
+ lpsi->nMin = mysi->nMin;
+ lpsi->nMax = mysi->nMax;
+ copied = TRUE;
+ }
+
+ return copied;
+}
+
+int WINAPI CoolSB_GetScrollPos (HWND hwnd, int nBar)
+{
+ SCROLLINFO *mysi;
+
+ if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
+ return GetScrollPos(hwnd, nBar);
+
+ return mysi->nPos;
+}
+
+BOOL WINAPI CoolSB_GetScrollRange (HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos)
+{
+ SCROLLINFO *mysi;
+
+ if(!lpMinPos || !lpMaxPos)
+ return FALSE;
+
+ if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
+ return GetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos);
+
+ *lpMinPos = mysi->nMin;
+ *lpMaxPos = mysi->nMax;
+
+ return TRUE;
+}
+
+int WINAPI CoolSB_SetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw)
+{
+ SCROLLINFO *mysi;
+ SCROLLBAR *sbar;
+ BOOL fRecalcFrame = FALSE;
+
+ if(!lpsi)
+ return FALSE;
+
+ if(!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar)))
+ return SetScrollInfo(hwnd, fnBar, lpsi, fRedraw);
+
+ //if(CoolSB_IsThumbTracking(hwnd))
+ // return mysi->nPos;
+
+ if(lpsi->fMask & SIF_RANGE)
+ {
+ mysi->nMin = lpsi->nMin;
+ mysi->nMax = lpsi->nMax;
+ }
+
+ //The nPage member must specify a value from 0 to nMax - nMin +1.
+ if(lpsi->fMask & SIF_PAGE)
+ {
+ UINT t = (UINT)(mysi->nMax - mysi->nMin + 1);
+ mysi->nPage = min(max(0, lpsi->nPage), t);
+ }
+
+ //The nPos member must specify a value between nMin and nMax - max(nPage - 1, 0).
+ if(lpsi->fMask & SIF_POS)
+ {
+ mysi->nPos = max(lpsi->nPos, mysi->nMin);
+ mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0));
+ }
+
+ sbar = GetScrollBarFromHwnd(hwnd, fnBar);
+
+ if((lpsi->fMask & SIF_DISABLENOSCROLL) || (sbar->fScrollFlags & CSBS_THUMBALWAYS))
+ {
+ if(!sbar->fScrollVisible)
+ {
+ CoolSB_ShowScrollBar(hwnd, fnBar, TRUE);
+ fRecalcFrame = TRUE;
+ }
+ }
+ else
+ {
+ if( mysi->nPage > (UINT)mysi->nMax
+ || mysi->nPage == (UINT)mysi->nMax && mysi->nMax == 0
+ || mysi->nMax <= mysi->nMin)
+ {
+ if(sbar->fScrollVisible)
+ {
+ CoolSB_ShowScrollBar(hwnd, fnBar, FALSE);
+ fRecalcFrame = TRUE;
+ }
+ }
+ else
+ {
+ if(!sbar->fScrollVisible)
+ {
+ CoolSB_ShowScrollBar(hwnd, fnBar, TRUE);
+ fRecalcFrame = TRUE;
+ }
+
+ }
+
+ }
+
+ if(fRedraw && !CoolSB_IsThumbTracking(hwnd))
+ RedrawNonClient(hwnd, fRecalcFrame);
+
+ return mysi->nPos;
+}
+
+
+int WINAPI CoolSB_SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL fRedraw)
+{
+ SCROLLINFO *mysi;
+ int oldpos;
+
+ if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
+ {
+ return SetScrollPos(hwnd, nBar, nPos, fRedraw);
+ }
+
+ //this is what should happen, but real scrollbars don't work like this..
+ //if(CoolSB_IsThumbTracking(hwnd))
+ // return mysi->nPos;
+
+ //validate and set the scollbar position
+ oldpos = mysi->nPos;
+ mysi->nPos = max(nPos, mysi->nMin);
+ mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0));
+
+ if(fRedraw && !CoolSB_IsThumbTracking(hwnd))
+ RedrawNonClient(hwnd, FALSE);
+
+ return oldpos;
+}
+
+int WINAPI CoolSB_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw)
+{
+ SCROLLINFO *mysi;
+
+ if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
+ return SetScrollRange(hwnd, nBar, nMinPos, nMaxPos, fRedraw);
+
+ if(CoolSB_IsThumbTracking(hwnd))
+ return mysi->nPos;
+
+ //hide the scrollbar if nMin == nMax
+ //nMax-nMin must not be greater than MAXLONG
+ mysi->nMin = nMinPos;
+ mysi->nMax = nMaxPos;
+
+ if(fRedraw)
+ RedrawNonClient(hwnd, FALSE);
+
+ return TRUE;
+}
+
+//
+// Show or hide the specified scrollbars
+//
+BOOL WINAPI CoolSB_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow)
+{
+ SCROLLBAR *sbar;
+ BOOL bFailed = FALSE;
+ DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
+
+ if(!CoolSB_IsCoolScrollEnabled(hwnd))
+ return ShowScrollBar(hwnd, wBar, fShow);
+
+ if((wBar == SB_HORZ || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
+ {
+ sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE;
+ sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
+ //bFailed = TRUE;
+
+ if(fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_HSCROLL);
+ else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_HSCROLL);
+ }
+
+ if((wBar == SB_VERT || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
+ {
+ sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE;
+ sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
+ //bFailed = TRUE;
+
+ if(fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VSCROLL);
+ else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_VSCROLL);
+ }
+
+ if(bFailed)
+ {
+ return FALSE;
+ }
+ else
+ {
+ //DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+ //style |= WS_VSCROLL;
+
+ //if(s
+ //SetWindowLong(hwnd, GWL_STYLE, style);
+
+ SetWindowPos(hwnd, 0, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
+ SWP_NOACTIVATE | SWP_FRAMECHANGED);
+
+ return TRUE;
+ }
+}
+
+//
+// Remove cool scrollbars from the specified window.
+//
+HRESULT WINAPI UninitializeCoolSB(HWND hwnd)
+{
+ SCROLLWND *sw = GetScrollWndFromHwnd(hwnd);
+ if(!sw) return E_FAIL;
+
+ //restore the window procedure with the original one
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)sw->oldproc);
+
+ RemoveProp(hwnd, szPropStr);
+ //SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+
+ //finally, release the memory needed for the cool scrollbars
+ HeapFree(GetProcessHeap(), 0, sw);
+
+ //Force WM_NCCALCSIZE and WM_NCPAINT so the original scrollbars can kick in
+ RedrawNonClient(hwnd, TRUE);
+
+ return S_OK;
+}
+
+#ifdef INCLUDE_BUTTONS
+
+//
+// Cool scrollbar specific interface (BUTTON support)
+//
+
+//
+// Insert a button into the scrollbar area
+//
+// wSBflags - SB_HORZ / SB_VERT only
+// uPos - position into which to insert.
+// can be 0 to insert at the start, or -1 to insert
+// at the end of previously inserted buttons
+//
+
+BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb)
+{
+ SCROLLBAR *sbar;
+ SCROLLBUT *sbut;
+ UINT i;
+
+ if(!psb) return FALSE;
+
+ if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
+ return FALSE;
+
+ //check that we havn't reached the maximum allowed buttons yet
+ if(sbar->nButtons == MAX_COOLSB_BUTS)
+ return FALSE;
+
+ //insert at end
+ if(nPos == -1)
+ {
+ sbut = &sbar->sbButtons[sbar->nButtons];
+ }
+ //otherwise, need to make room
+ else if((int)nPos < 0 || (int)nPos > (UINT)sbar->nButtons)
+ {
+ return FALSE;
+ }
+ else
+ {
+ //insert space for the button at the specified position
+ for(i = sbar->nButtons; i > nPos; i--)
+ {
+ sbar->sbButtons[i] = sbar->sbButtons[i-1];
+ }
+
+ sbut = &sbar->sbButtons[nPos];
+ }
+
+ //only set the button's properties if they are
+ //specified by the SCROLLBUT->fMask.
+ //Otherwise, use a default property value
+
+ if(psb->fMask & SBBF_TYPE)
+ sbut->uButType = psb->uButType;
+ else
+ sbut->uButType = SBBT_PUSHBUTTON;
+
+ if(psb->fMask & SBBF_STATE)
+ sbut->uState = psb->uState;
+ else
+ sbut->uState = 0;
+
+ if(psb->fMask & SBBF_ID)
+ sbut->uCmdId = psb->uCmdId;
+ else
+ sbut->uCmdId = 0;
+
+ if(psb->fMask & SBBF_SIZE)
+ sbut->nSize = psb->nSize;
+ else
+ sbut->nSize = -1;
+
+ if(psb->fMask & SBBF_PLACEMENT)
+ sbut->uPlacement = psb->uPlacement;
+ else
+ sbut->uPlacement = SBBP_LEFT;
+
+ if(psb->fMask & SBBF_BITMAP)
+ sbut->hBmp = psb->hBmp;
+ else
+ sbut->hBmp = 0;
+
+ if(psb->fMask & SBBF_ENHMETAFILE)
+ sbut->hEmf = psb->hEmf;
+ else
+ sbut->hEmf = 0;
+
+ if(psb->fMask & SBBF_CURSOR)
+ sbut->hCurs = psb->hCurs;
+ else
+ sbut->hCurs = 0;
+
+ /*
+ We don't use the callback function anymore. The uButType
+ member must now specify SBBT_OWNERDRAW, and a WM_NOTIFY will
+ be sent when a button must be drawn
+ if((psb->fMask & SBBF_OWNERDRAW) && ((psb->uButType & SBBT_MASK) == SBBT_OWNERDRAW))
+ pDrawProc = psb->pDrawProc;
+ else
+ pDrawProc = 0;*/
+
+ sbar->nButtons++;
+ sbut->nSizeReserved = sbut->nSize;
+
+ //MAKE SURE that any resizable buttons are only to the left / above
+ //a scrollbar. We don't support resize operations to the right of a scrollbar
+ if((sbut->uButType & SBBM_RESIZABLE) && sbut->uPlacement == SBBP_RIGHT)
+ sbut->uButType &= ~SBBM_RESIZABLE;
+
+ if(psb->fMask & SBBF_BUTMINMAX)
+ {
+ sbut->nMinSize = psb->nMinSize;
+ sbut->nMaxSize = psb->nMaxSize;
+ }
+ else
+ {
+ sbut->nMinSize = 0;
+ sbut->nMaxSize = -1;
+ }
+
+ return TRUE;
+}
+
+static SCROLLBUT *GetButtonFromId(SCROLLBAR *sbar, UINT uCmdId)
+{
+ int i;
+ for(i = 0; i < sbar->nButtons; i++)
+ {
+ if(sbar->sbButtons[i].uCmdId == uCmdId)
+ return &sbar->sbButtons[i];
+ }
+
+ return 0;
+}
+
+//
+// Modify the properties of the specified scrollbar button.
+// wSBflags - SB_HORZ / SB_VERT only
+// uItem - the command identifier specified when the button was created,
+// or a non-negative position of the button, depending on if
+// fByCmd is FALSE or TRUE, respectively
+//
+BOOL WINAPI CoolSB_ModifyButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb)
+{
+ SCROLLBAR *sbar;
+ SCROLLBUT *sbut;
+
+ if(!psb) return FALSE;
+
+ //find if this window is CoolScroll enabled
+ if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
+ return FALSE;
+
+ //find the button to modify, depending on if we
+ //are modifying by position or command id
+ if(fByCmd == FALSE)
+ {
+ //button from position
+ if((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons)
+ return FALSE;
+ else
+ sbut = &sbar->sbButtons[uItem];
+ }
+ else if(fByCmd == TRUE)
+ {
+ //button from command identifier
+ if(!(sbut = GetButtonFromId(sbar, uItem)))
+ return FALSE;
+ }
+
+ if(psb->fMask & SBBF_TYPE) sbut->uButType = psb->uButType;
+ if(psb->fMask & SBBF_STATE) sbut->uState = psb->uState;
+ if(psb->fMask & SBBF_ID) sbut->uCmdId = psb->uCmdId;
+ if(psb->fMask & SBBF_SIZE) sbut->nSize = psb->nSize;
+ if(psb->fMask & SBBF_PLACEMENT) sbut->uPlacement = psb->uPlacement;
+ if(psb->fMask & SBBF_BITMAP) sbut->hBmp = psb->hBmp;
+ if(psb->fMask & SBBF_ENHMETAFILE) sbut->hEmf = psb->hEmf;
+ if(psb->fMask & SBBF_CURSOR) sbut->hCurs = psb->hCurs;
+
+ if(psb->fMask & SBBF_BUTMINMAX)
+ {
+ sbut->nMinSize = psb->nMinSize;
+ sbut->nMaxSize = psb->nMaxSize;
+ }
+
+ return TRUE;
+}
+
+BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd)
+{
+ int i;
+ SCROLLBAR *sbar;
+
+ //find if this window is CoolScroll enabled
+ if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
+ return FALSE;
+
+ //find the button to modify, depending on if we
+ //are modifying by position or command id
+ if(fByCmd == FALSE && ((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons))
+ {
+ return FALSE;
+ }
+ else if(fByCmd == TRUE)
+ {
+ //find the button with the specified command id
+ for(i = 0; i < sbar->nButtons; i++)
+ {
+ if(sbar->sbButtons[i].uCmdId == uItem)
+ {
+ //change the id to an index
+ uItem = i;
+ break;
+ }
+ }
+
+ //if we failed to find the button...
+ if(i == sbar->nButtons) return FALSE;
+ }
+
+ //remove the button!
+ for(i = uItem; i < sbar->nButtons - 1; i++)
+ {
+ sbar->sbButtons[i] = sbar->sbButtons[i+1];
+ }
+
+ sbar->nButtons--;
+
+ RedrawNonClient(hwnd, TRUE);
+
+ return TRUE;
+}
+
+//
+// fill in the supplied SCROLLBUT structure
+//
+BOOL WINAPI CoolSB_GetButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb)
+{
+ SCROLLBAR *sbar;
+ SCROLLBUT *sbut;
+
+ if(!psb) return FALSE;
+
+ //find if this window is CoolScroll enabled
+ if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
+ return FALSE;
+
+ //find the button to modify, depending on if we
+ //are modifying by position or command id
+ if(fByCmd == FALSE)
+ {
+ //button from position
+ if((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons)
+ return FALSE;
+ else
+ sbut = &sbar->sbButtons[uItem];
+ }
+ else if(fByCmd == TRUE)
+ {
+ //button from command identifier
+ if(!(sbut = GetButtonFromId(sbar, uItem)))
+ return FALSE;
+ }
+
+ //copy them across
+ *psb = *sbut;
+
+ return FALSE;
+}
+
+#else
+
+BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb) { return FALSE; }
+BOOL WINAPI CoolSB_ModifyButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) { return FALSE; }
+BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd) { return FALSE; }
+BOOL WINAPI CoolSB_GetButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) { return FALSE; }
+
+#endif //INCLUDE_BUTTONS
+
+//
+// Set the size of the scrollbars
+//
+BOOL WINAPI CoolSB_SetSize (HWND hwnd, int wBar, int nLength, int nWidth)
+{
+ SCROLLBAR *sbar;
+
+ if(nLength == 0 || nWidth == 0)
+ return FALSE;
+
+ if(nLength < -8 || nWidth < -8)
+ return FALSE;
+
+ if(nLength > 256 || nWidth > 256)
+ return FALSE;
+
+ if(!GetScrollWndFromHwnd(hwnd))
+ return FALSE;
+
+ if((wBar == SB_HORZ || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
+ {
+ sbar->nArrowLength = nLength;
+ sbar->nArrowWidth = nWidth;
+ }
+
+ if((wBar == SB_VERT || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
+ {
+ sbar->nArrowLength = nLength;
+ sbar->nArrowWidth = nWidth;
+ }
+
+ RedrawNonClient(hwnd, TRUE);
+
+ return TRUE;
+}
+
+
+//
+// Alter the display mode of the scrollbars
+// wBar - SB_HORZ / SB_VERT / SB_BOTH
+// nStyle - CSBF_NORMAL / CSBF_FLAT / CSBF_HOTTRACKED
+//
+BOOL WINAPI CoolSB_SetStyle(HWND hwnd, int wBar, UINT nStyle)
+{
+ SCROLLBAR *sbar;
+
+ if(!GetScrollWndFromHwnd(hwnd))
+ return FALSE;
+
+ if((wBar == SB_HORZ || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
+ {
+ sbar->fFlatScrollbar = nStyle;
+ }
+
+ if((wBar == SB_VERT || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
+ {
+ sbar->fFlatScrollbar = nStyle;
+ }
+
+ RedrawNonClient(hwnd, FALSE);
+
+ return TRUE;
+}
+
+//
+// Set if the thumb is always visible, even if there is no data to
+// scroll. Setting this keeps the scrollbar enabled, but the thumb
+// covers the whole area
+//
+BOOL WINAPI CoolSB_SetThumbAlways(HWND hwnd, int wBar, BOOL fThumbAlways)
+{
+ SCROLLBAR *sbar;
+
+ if(!GetScrollWndFromHwnd(hwnd))
+ return FALSE;
+
+ if((wBar == SB_HORZ || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
+ {
+ if(fThumbAlways)
+ sbar->fScrollFlags |= CSBS_THUMBALWAYS;
+ else
+ sbar->fScrollFlags &= ~CSBS_THUMBALWAYS;
+ }
+
+ if((wBar == SB_VERT || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
+ {
+ if(fThumbAlways)
+ sbar->fScrollFlags |= CSBS_THUMBALWAYS;
+ else
+ sbar->fScrollFlags &= ~CSBS_THUMBALWAYS;
+ }
+
+ RedrawNonClient(hwnd, FALSE);
+
+ return TRUE;
+}
+
+//
+// Set the minimum size, in pixels, that the thumb box will shrink to.
+//
+BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size)
+{
+ SCROLLBAR *sbar;
+
+ if(!GetScrollWndFromHwnd(hwnd))
+ return FALSE;
+
+ if(size == -1)
+ size = CoolSB_GetDefaultMinThumbSize();
+
+ if((wBar == SB_HORZ || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
+ {
+ sbar->nMinThumbSize = size;
+ }
+
+ if((wBar == SB_VERT || wBar == SB_BOTH) &&
+ (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
+ {
+ sbar->nMinThumbSize = size;
+ }
+
+ return TRUE;
+}
diff --git a/plugins/Clist_ng/coolsb/coolsblib.h b/plugins/Clist_ng/coolsb/coolsblib.h new file mode 100644 index 0000000000..d9b1c711f3 --- /dev/null +++ b/plugins/Clist_ng/coolsb/coolsblib.h @@ -0,0 +1,41 @@ +#ifndef _SUPERSCROLL_INCLUDED
+#define _SUPERSCROLL_INCLUDED
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <windows.h>
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/Clist_ng/coolsb/coolscroll.cpp b/plugins/Clist_ng/coolsb/coolscroll.cpp new file mode 100644 index 0000000000..1a056fe301 --- /dev/null +++ b/plugins/Clist_ng/coolsb/coolscroll.cpp @@ -0,0 +1,3214 @@ +/*
+ Cool Scrollbar Library Version 1.2
+
+ Module: coolscroll.c
+ Copyright (c) J Brown 2001
+
+ This code is freeware, however, you may not publish
+ this code elsewhere or charge any money for it. This code
+ is supplied as-is. I make no guarantees about the suitability
+ of this code - use at your own risk.
+
+ It would be nice if you credited me, in the event
+ that you use this code in a product.
+
+ VERSION HISTORY:
+
+ V1.2: TreeView problem fixed by Diego Tartara
+ Small problem in thumbsize calculation also fixed (thanks Diego!)
+
+ V1.1: Added support for Right-left windows
+ Changed calling convention of APIs to WINAPI (__stdcall)
+ Completely standalone (no need for c-runtime)
+ Now supports ALL windows with appropriate USER32.DLL patching
+ (you provide!!)
+
+ V1.0: Apr 2001: Initial Version
+
+ IMPORTANT:
+ This whole library is based around code for a horizontal scrollbar.
+ All "vertical" scrollbar drawing / mouse interaction uses the
+ horizontal scrollbar functions, but uses a trick to convert the vertical
+ scrollbar coordinates into horizontal equivelants. When I started this project,
+ I quickly realised that the code for horz/vert bars was IDENTICAL, apart
+ from the fact that horizontal code uses left/right coords, and vertical code
+ uses top/bottom coords. On entry to a "vertical" drawing function, for example,
+ the coordinates are "rotated" before the horizontal function is called, and
+ then rotated back once the function has completed. When something needs to
+ be drawn, the coords are converted back again before drawing.
+
+ This trick greatly reduces the amount of code required, and makes
+ maintanence much simpler. This way, only one function is needed to draw
+ a scrollbar, but this can be used for both horizontal and vertical bars
+ with careful thought.
+*/
+
+#define _WIN32_WINNT 0x0502
+#define _WIN32_IE 0x0501
+
+#include <commonheaders.h>
+#include "coolscroll.h"
+#include "userdefs.h"
+#include "coolsb_internal.h"
+
+//define some values if the new version of common controls
+//is not available.
+#ifndef NM_CUSTOMDRAW
+#define NM_CUSTOMDRAW (NM_FIRST-12)
+#define CDRF_DODEFAULT 0x0000
+#define CDRF_SKIPDEFAULT 0x0004
+#define CDDS_PREPAINT 0x0001
+#define CDDS_POSTPAINT 0x0002
+#endif
+
+//
+// Special thumb-tracking variables
+//
+//
+static UINT uCurrentScrollbar = COOLSB_NONE; //SB_HORZ / SB_VERT
+static UINT uCurrentScrollPortion = HTSCROLL_NONE;
+static UINT uCurrentButton = 0;
+
+static RECT rcThumbBounds; //area that the scroll thumb can travel in
+static int nThumbSize; //(pixels)
+static int nThumbPos; //(pixels)
+static int nThumbMouseOffset; //(pixels)
+static int nLastPos = -1; //(scrollbar units)
+static int nThumbPos0; //(pixels) initial thumb position
+
+//
+// Temporary state used to auto-generate timer messages
+//
+static UINT_PTR uMouseOverId = 0;
+static UINT uMouseOverScrollbar = COOLSB_NONE;
+static UINT uHitTestPortion = HTSCROLL_NONE;
+static UINT uLastHitTestPortion = HTSCROLL_NONE;
+static RECT MouseOverRect;
+
+static UINT uScrollTimerMsg = 0;
+static UINT uScrollTimerPortion = HTSCROLL_NONE;
+static UINT_PTR uScrollTimerId = 0;
+static HWND hwndCurCoolSB = 0;
+
+extern int CustomDrawScrollBars(NMCSBCUSTOMDRAW *nmcsbcd);
+
+//
+// Provide this so there are NO dependencies on CRT
+//
+static void CoolSB_ZeroMemory(void *ptr, DWORD bytes)
+{
+ BYTE *bptr = (BYTE *)ptr;
+
+ while(bytes--) *bptr++ = 0;
+}
+
+BOOL WINAPI CoolSB_IsThumbTracking(HWND hwnd)
+{
+ SCROLLWND *sw;
+
+ if((sw = GetScrollWndFromHwnd(hwnd)) == NULL)
+ return FALSE;
+ else
+ return sw->fThumbTracking;
+}
+
+//
+// swap the rectangle's x coords with its y coords
+//
+static void __stdcall RotateRect(RECT *rect)
+{
+ int temp;
+ temp = rect->left;
+ rect->left = rect->top;
+ rect->top = temp;
+
+ temp = rect->right;
+ rect->right = rect->bottom;
+ rect->bottom = temp;
+}
+
+//
+// swap the coords if the scrollbar is a SB_VERT
+//
+static void __stdcall RotateRect0(SCROLLBAR *sb, RECT *rect)
+{
+ if(sb->nBarType == SB_VERT)
+ RotateRect(rect);
+}
+
+//
+// Calculate if the SCROLLINFO members produce
+// an enabled or disabled scrollbar
+//
+static BOOL IsScrollInfoActive(SCROLLINFO *si)
+{
+ if((si->nPage > (UINT)si->nMax
+ || si->nMax <= si->nMin || si->nMax == 0))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+//
+// Return if the specified scrollbar is enabled or not
+//
+static BOOL IsScrollbarActive(SCROLLBAR *sb)
+{
+ SCROLLINFO *si = &sb->scrollInfo;
+ if(((sb->fScrollFlags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ||
+ !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(si))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+//
+// Draw a standard scrollbar arrow
+//
+static int DrawScrollArrow(SCROLLBAR *sbar, HDC hdc, RECT *rect, UINT arrow, BOOL fMouseDown, BOOL fMouseOver)
+{
+ UINT ret;
+ UINT flags = arrow;
+
+ //HACKY bit so this routine can be called by vertical and horizontal code
+ if(sbar->nBarType == SB_VERT)
+ {
+ if(flags & DFCS_SCROLLLEFT) flags = flags & ~DFCS_SCROLLLEFT | DFCS_SCROLLUP;
+ if(flags & DFCS_SCROLLRIGHT) flags = flags & ~DFCS_SCROLLRIGHT | DFCS_SCROLLDOWN;
+ }
+
+ if(fMouseDown) flags |= (DFCS_FLAT | DFCS_PUSHED);
+
+#ifdef FLAT_SCROLLBARS
+ if(sbar->fFlatScrollbar != CSBS_NORMAL)
+ {
+ HDC hdcmem1, hdcmem2;
+ HBITMAP hbm1, oldbm1;
+ HBITMAP hbm2, oldbm2;
+ RECT rc;
+ int width, height;
+
+ rc = *rect;
+ width = rc.right-rc.left;
+ height = rc.bottom-rc.top;
+ SetRect(&rc, 0, 0, width, height);
+
+ //MONOCHROME bitmap to convert the arrow to black/white mask
+ hdcmem1 = CreateCompatibleDC(hdc);
+ hbm1 = CreateBitmap(width, height, 1, 1, NULL);
+ UnrealizeObject(hbm1);
+ oldbm1 = reinterpret_cast<HBITMAP>(SelectObject(hdcmem1, hbm1));
+
+
+ //NORMAL bitmap to draw the arrow into
+ hdcmem2 = CreateCompatibleDC(hdc);
+ hbm2 = CreateCompatibleBitmap(hdc, width, height);
+ UnrealizeObject(hbm2);
+ oldbm2 = reinterpret_cast<HBITMAP>(SelectObject(hdcmem2, hbm2));
+
+
+ flags = flags & ~DFCS_PUSHED | DFCS_FLAT; //just in case
+ DrawFrameControl(hdcmem2, &rc, DFC_SCROLL, flags);
+
+
+#ifndef HOT_TRACKING
+ if(fMouseDown)
+ {
+ //uncomment these to make the cool scrollbars
+ //look like the common controls flat scrollbars
+ //fMouseDown = FALSE;
+ //fMouseOver = TRUE;
+ }
+#endif
+ //draw a flat monochrome version of a scrollbar arrow (dark)
+ if(fMouseDown)
+ {
+ SetBkColor(hdcmem2, GetSysColor(COLOR_BTNTEXT));
+ BitBlt(hdcmem1, 0, 0, width, height, hdcmem2, 0, 0, SRCCOPY);
+ SetBkColor(hdc, 0x00ffffff);
+ SetTextColor(hdc, GetSysColor(COLOR_3DDKSHADOW));
+ BitBlt(hdc, rect->left, rect->top, width, height, hdcmem1, 0, 0, SRCCOPY);
+ }
+ //draw a flat monochrome version of a scrollbar arrow (grey)
+ else if(fMouseOver)
+ {
+ SetBkColor(hdcmem2, GetSysColor(COLOR_BTNTEXT));
+ FillRect(hdcmem1, &rc, reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
+ BitBlt(hdcmem1, 0, 0, width, height, hdcmem2, 0, 0, SRCINVERT);
+
+ SetBkColor(hdc, GetSysColor(COLOR_3DSHADOW));
+ SetTextColor(hdc, 0x00ffffff);
+ BitBlt(hdc, rect->left, rect->top, width, height, hdcmem1, 0, 0, SRCCOPY);
+ }
+ //draw the arrow normally
+ else
+ {
+ BitBlt(hdc, rect->left, rect->top, width, height, hdcmem2, 0, 0, SRCCOPY);
+ }
+
+ SelectObject(hdcmem1, oldbm1);
+ SelectObject(hdcmem2, oldbm2);
+ DeleteObject(hbm1);
+ DeleteObject(hbm2);
+ DeleteDC(hdcmem1);
+ DeleteDC(hdcmem2);
+
+ ret = 0;
+ }
+ else
+#endif
+ ret = DrawFrameControl(hdc, rect, DFC_SCROLL, flags);
+
+ return ret;
+}
+
+//
+// Return the size in pixels for the specified scrollbar metric,
+// for the specified scrollbar
+//
+static int GetScrollMetric(SCROLLBAR *sbar, int metric)
+{
+ if(sbar->nBarType == SB_HORZ)
+ {
+ if(metric == SM_CXHORZSB)
+ {
+ if(sbar->nArrowLength < 0)
+ return -sbar->nArrowLength * GetSystemMetrics(SM_CXHSCROLL);
+ else
+ return sbar->nArrowLength;
+ }
+ else
+ {
+ if(sbar->nArrowWidth < 0)
+ return -sbar->nArrowWidth * GetSystemMetrics(SM_CYHSCROLL);
+ else
+ return sbar->nArrowWidth;
+ }
+ }
+ else if(sbar->nBarType == SB_VERT)
+ {
+ if(metric == SM_CYVERTSB)
+ {
+ if(sbar->nArrowLength < 0)
+ return -sbar->nArrowLength * GetSystemMetrics(SM_CYVSCROLL);
+ else
+ return sbar->nArrowLength;
+ }
+ else
+ {
+ if(sbar->nArrowWidth < 0)
+ return -sbar->nArrowWidth * GetSystemMetrics(SM_CXVSCROLL);
+ else
+ return sbar->nArrowWidth;
+ }
+ }
+
+ return 0;
+}
+
+//
+//
+//
+static COLORREF GetSBForeColor(void)
+{
+ COLORREF c1 = GetSysColor(COLOR_3DHILIGHT);
+ COLORREF c2 = GetSysColor(COLOR_WINDOW);
+
+ if(c1 != 0xffffff && c1 == c2)
+ {
+ return GetSysColor(COLOR_BTNFACE);
+ }
+ else
+ {
+ return GetSysColor(COLOR_3DHILIGHT);
+ }
+}
+
+static COLORREF GetSBBackColor(void)
+{
+ return GetSysColor(COLOR_SCROLLBAR);
+}
+
+//
+// Paint a checkered rectangle, with each alternate
+// pixel being assigned a different colour
+//
+static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)
+{
+ static WORD wCheckPat[8] =
+ {
+ 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
+ };
+
+ HBITMAP hbmp;
+ HBRUSH hbr, hbrold;
+ COLORREF fgold, bgold;
+
+ hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);
+ hbr = CreatePatternBrush(hbmp);
+
+ UnrealizeObject(hbr);
+ SetBrushOrgEx(hdc, rect->left, rect->top, 0);
+
+ hbrold = (HBRUSH)SelectObject(hdc, hbr);
+
+ fgold = SetTextColor(hdc, fg);
+ bgold = SetBkColor(hdc, bg);
+
+ PatBlt(hdc, rect->left, rect->top,
+ rect->right - rect->left,
+ rect->bottom - rect->top,
+ PATCOPY);
+
+ SetBkColor(hdc, bgold);
+ SetTextColor(hdc, fgold);
+
+ SelectObject(hdc, hbrold);
+ DeleteObject(hbr);
+ DeleteObject(hbmp);
+}
+
+//
+// Fill the specifed rectangle using a solid colour
+//
+static void PaintRect(HDC hdc, RECT *rect, COLORREF color)
+{
+ COLORREF oldcol = SetBkColor(hdc, color);
+ ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, NULL);
+ SetBkColor(hdc, oldcol);
+}
+
+//
+// Draw a simple blank scrollbar push-button. Can be used
+// to draw a push button, or the scrollbar thumb
+// drawflag - could set to BF_FLAT to make flat scrollbars
+//
+void DrawBlankButton(HDC hdc, const RECT *rect, UINT drawflag)
+{
+ RECT rc = *rect;
+
+#ifndef FLAT_SCROLLBARS
+ drawflag &= ~BF_FLAT;
+#endif
+
+ DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | drawflag | BF_ADJUST);
+ FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
+}
+
+//
+// Send a WM_VSCROLL or WM_HSCROLL message
+//
+static void SendScrollMessage(HWND hwnd, UINT scrMsg, UINT scrId, UINT pos)
+{
+ SendMessage(hwnd, scrMsg, MAKEWPARAM(scrId, pos), 0);
+}
+
+//
+// Calculate the screen coordinates of the area taken by
+// the horizontal scrollbar. Take into account the size
+// of the window borders
+//
+static BOOL GetHScrollRect(SCROLLWND *sw, HWND hwnd, RECT *rect)
+{
+ GetWindowRect(hwnd, rect);
+
+ if(sw->fLeftScrollbar)
+ {
+ rect->left += sw->cxLeftEdge + (sw->sbarVert.fScrollVisible ?
+ GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
+ rect->right -= sw->cxRightEdge;
+ }
+ else
+ {
+ rect->left += sw->cxLeftEdge; //left window edge
+
+ rect->right -= sw->cxRightEdge + //right window edge
+ (sw->sbarVert.fScrollVisible ?
+ GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
+ }
+
+ rect->bottom -= sw->cyBottomEdge; //bottom window edge
+
+ rect->top = rect->bottom -
+ (sw->sbarHorz.fScrollVisible ?
+ GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0);
+
+ return TRUE;
+}
+
+//
+// Calculate the screen coordinates of the area taken by the
+// vertical scrollbar
+//
+static BOOL GetVScrollRect(SCROLLWND *sw, HWND hwnd, RECT *rect)
+{
+ GetWindowRect(hwnd, rect);
+ rect->top += sw->cyTopEdge; //top window edge
+
+ rect->bottom -= sw->cyBottomEdge +
+ (sw->sbarHorz.fScrollVisible ? //bottom window edge
+ GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0);
+
+ if(sw->fLeftScrollbar)
+ {
+ rect->left += sw->cxLeftEdge;
+ rect->right = rect->left + (sw->sbarVert.fScrollVisible ?
+ GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
+ }
+ else
+ {
+ rect->right -= sw->cxRightEdge;
+ rect->left = rect->right - (sw->sbarVert.fScrollVisible ?
+ GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
+ }
+
+ return TRUE;
+}
+
+// Depending on what type of scrollbar nBar refers to, call the
+// appropriate Get?ScrollRect function
+//
+BOOL GetScrollRect(SCROLLWND *sw, UINT nBar, HWND hwnd, RECT *rect)
+{
+ if(nBar == SB_HORZ)
+ return GetHScrollRect(sw, hwnd, rect);
+ else if(nBar == SB_VERT)
+ return GetVScrollRect(sw, hwnd, rect);
+ else
+ return FALSE;
+}
+
+//
+// This code is a prime candidate for splitting out into a separate
+// file at some stage
+//
+#ifdef INCLUDE_BUTTONS
+
+//
+// Calculate the size in pixels of the specified button
+//
+static int GetSingleButSize(SCROLLBAR *sbar, SCROLLBUT *sbut)
+{
+ //multiple of the system button size
+ //or a specific button size
+ if(sbut->nSize < 0)
+ {
+ if(sbar->nBarType == SB_HORZ)
+ return -sbut->nSize * GetSystemMetrics(SM_CXHSCROLL);
+ else
+ return -sbut->nSize * GetSystemMetrics(SM_CYVSCROLL);
+ }
+ else
+ return sbut->nSize;
+}
+
+//
+// Find the size in pixels of all the inserted buttons,
+// either before or after the specified scrollbar
+//
+static int GetButtonSize(SCROLLBAR *sbar, HWND hwnd, UINT uBeforeAfter)
+{
+ int i;
+ int nPixels = 0;
+
+ SCROLLBUT *sbut = sbar->sbButtons;
+
+ for(i = 0; i < sbar->nButtons; i++)
+ {
+ //only consider those buttons on the same side as nTopBottom says
+ if(sbut[i].uPlacement == uBeforeAfter)
+ {
+ nPixels += GetSingleButSize(sbar, &sbut[i]);
+ }
+ }
+
+ return nPixels;
+}
+#endif //INCLUDE_BUTTONS
+
+//
+// Work out the scrollbar width/height for either type of scrollbar (SB_HORZ/SB_VERT)
+// rect - coords of the scrollbar.
+// store results into *thumbsize and *thumbpos
+//
+static int CalcThumbSize(SCROLLBAR *sbar, const RECT *rect, int *pthumbsize, int *pthumbpos)
+{
+ SCROLLINFO *si;
+ int scrollsize; //total size of the scrollbar including arrow buttons
+ int workingsize; //working area (where the thumb can slide)
+ int siMaxMin;
+ int butsize;
+ int startcoord;
+ int thumbpos = 0, thumbsize = 0;
+
+ static int count=0;
+
+ //work out the width (for a horizontal) or the height (for a vertical)
+ //of a standard scrollbar button
+ butsize = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
+
+ if(1) //sbar->nBarType == SB_HORZ)
+ {
+ scrollsize = rect->right - rect->left;
+ startcoord = rect->left;
+ }
+ /*else if(sbar->nBarType == SB_VERT)
+ {
+ scrollsize = rect->bottom - rect->top;
+ startcoord = rect->top;
+ }
+ else
+ {
+ return 0;
+ }*/
+
+ si = &sbar->scrollInfo;
+ siMaxMin = si->nMax - si->nMin + 1;
+ workingsize = scrollsize - butsize * 2;
+
+ //
+ // Work out the scrollbar thumb SIZE
+ //
+ if(si->nPage == 0)
+ {
+ thumbsize = butsize;
+ }
+ else if(siMaxMin > 0)
+ {
+ thumbsize = MulDiv(si->nPage, workingsize, siMaxMin);
+
+ if(thumbsize < sbar->nMinThumbSize)
+ thumbsize = sbar->nMinThumbSize;
+ }
+
+ //
+ // Work out the scrollbar thumb position
+ //
+ if(siMaxMin > 0)
+ {
+ int pagesize = max(1, si->nPage);
+ thumbpos = MulDiv(si->nPos - si->nMin, workingsize-thumbsize, siMaxMin - pagesize);
+
+ if(thumbpos < 0)
+ thumbpos = 0;
+
+ if(thumbpos >= workingsize-thumbsize)
+ thumbpos = workingsize-thumbsize;
+ }
+
+ thumbpos += startcoord + butsize;
+
+ *pthumbpos = thumbpos;
+ *pthumbsize = thumbsize;
+
+ return 1;
+}
+
+//
+// return a hit-test value for whatever part of the scrollbar x,y is located in
+// rect, x, y: SCREEN coordinates
+// the rectangle must not include space for any inserted buttons
+// (i.e, JUST the scrollbar area)
+//
+static UINT GetHorzScrollPortion(SCROLLBAR *sbar, HWND hwnd, const RECT *rect, int x, int y)
+{
+ int thumbwidth, thumbpos;
+ int butwidth = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
+ int scrollwidth = rect->right-rect->left;
+ int workingwidth = scrollwidth - butwidth*2;
+
+ if(y < rect->top || y >= rect->bottom)
+ return HTSCROLL_NONE;
+
+ CalcThumbSize(sbar, rect, &thumbwidth, &thumbpos);
+
+ //if we have had to scale the buttons to fit in the rect,
+ //then adjust the button width accordingly
+ if(scrollwidth <= butwidth * 2)
+ {
+ butwidth = scrollwidth / 2;
+ }
+
+ //check for left button click
+ if(x >= rect->left && x < rect->left + butwidth)
+ {
+ return HTSCROLL_LEFT;
+ }
+ //check for right button click
+ else if(x >= rect->right-butwidth && x < rect->right)
+ {
+ return HTSCROLL_RIGHT;
+ }
+
+ //if the thumb is too big to fit (i.e. it isn't visible)
+ //then return a NULL scrollbar area
+ if(thumbwidth >= workingwidth)
+ return HTSCROLL_NONE;
+
+ //check for point in the thumbbar
+ if(x >= thumbpos && x < thumbpos+thumbwidth)
+ {
+ return HTSCROLL_THUMB;
+ }
+ //check for left margin
+ else if(x >= rect->left+butwidth && x < thumbpos)
+ {
+ return HTSCROLL_PAGELEFT;
+ }
+ else if(x >= thumbpos+thumbwidth && x < rect->right-butwidth)
+ {
+ return HTSCROLL_PAGERIGHT;
+ }
+
+ return HTSCROLL_NONE;
+}
+
+//
+// For vertical scrollbars, rotate all coordinates by -90 degrees
+// so that we can use the horizontal version of this function
+//
+static UINT GetVertScrollPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
+{
+ UINT r;
+
+ RotateRect(rect);
+ r = GetHorzScrollPortion(sb, hwnd, rect, y, x);
+ RotateRect(rect);
+ return r;
+}
+
+//
+// CUSTOM DRAW support
+//
+static LRESULT PostCustomPrePostPaint(HWND hwnd, HDC hdc, SCROLLBAR *sb, UINT dwStage)
+{
+#ifdef CUSTOM_DRAW
+ NMCSBCUSTOMDRAW nmcd;
+
+ CoolSB_ZeroMemory(&nmcd, sizeof nmcd);
+ nmcd.hdr.hwndFrom = hwnd;
+ nmcd.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID);
+ nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW;
+ nmcd.nBar = sb->nBarType;
+ nmcd.dwDrawStage = dwStage;
+ nmcd.hdc = hdc;
+
+ hwnd = GetParent(hwnd);
+ return CustomDrawScrollBars(&nmcd);
+#else
+ return 0;
+#endif
+}
+
+static LRESULT PostCustomDrawNotify(HWND hwnd, HDC hdc, UINT nBar, RECT *prect, UINT nItem, BOOL fMouseDown, BOOL fMouseOver, BOOL fInactive)
+{
+#ifdef CUSTOM_DRAW
+ NMCSBCUSTOMDRAW nmcd;
+
+ //fill in the standard header
+ nmcd.hdr.hwndFrom = hwnd;
+ nmcd.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID);
+ nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW;
+
+ nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
+ nmcd.nBar = nBar;
+ nmcd.rect = *prect;
+ nmcd.uItem = nItem;
+ nmcd.hdc = hdc;
+
+ if(fMouseDown)
+ nmcd.uState = CDIS_SELECTED;
+ else if(fMouseOver)
+ nmcd.uState = CDIS_HOT;
+ else if(fInactive)
+ nmcd.uState = CDIS_DISABLED;
+ else
+ nmcd.uState = CDIS_DEFAULT;
+
+ hwnd = GetParent(hwnd);
+ return CustomDrawScrollBars(&nmcd);
+#else
+ return 0;
+#endif
+}
+
+// Depending on if we are supporting custom draw, either define
+// a macro to the function name, or to nothing at all. If custom draw
+// is turned off, then we can save ALOT of code space by binning all
+// calls to the custom draw support.
+
+/*
+#ifdef CUSTOM_DRAW
+#define PostCustomDrawNotify PostCustomDrawNotify0
+#define PostCustomPrePostPaint PostCustomPrePostPaint0
+#else
+#define PostCustomDrawNotify 1 ? (void)0 : PostCustomDrawNotify0
+#define PostCustomPrePostPaint 1 ? (void)0 : PostCustomPrePostPaint0
+#endif
+*/
+
+static LRESULT PostMouseNotify0(HWND hwnd, UINT msg, UINT nBar, RECT *prect, UINT nCmdId, POINT pt)
+{
+#ifdef NOTIFY_MOUSE
+ NMCOOLBUTMSG nmcb;
+
+ //fill in the standard header
+ nmcb.hdr.hwndFrom = hwnd;
+ nmcb.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID);
+ nmcb.hdr.code = NM_CLICK;
+
+ nmcb.nBar = nBar;
+ nmcb.uCmdId = nCmdId;
+ nmcb.uState = 0;
+ nmcb.rect = *prect;
+ nmcb.pt = pt;
+
+ hwnd = GetParent(hwnd);
+ return SendMessage(hwnd, WM_NOTIFY, nmcb.hdr.idFrom, (LPARAM)&nmcb);
+#else
+ return 0;
+#endif
+}
+
+#ifdef NOTIFY_MOUSE
+#define PostMouseNotify PostMouseNotify0
+#else
+#define PostMouseNotify 1 ? (void)0 : PostMouseNotify0
+#endif
+
+
+
+//
+// Draw a complete HORIZONTAL scrollbar in the given rectangle
+// Don't draw any inserted buttons in this procedure
+//
+// uDrawFlags - hittest code, to say if to draw the
+// specified portion in an active state or not.
+//
+//
+static LRESULT NCDrawHScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
+{
+ SCROLLINFO *si;
+ RECT ctrl, thumb;
+ RECT sbm;
+ int butwidth = GetScrollMetric(sb, SM_SCROLL_LENGTH);
+ int scrollwidth = rect->right-rect->left;
+ int workingwidth = scrollwidth - butwidth*2;
+ int thumbwidth = 0, thumbpos = 0;
+ int siMaxMin;
+
+ BOOL fCustomDraw = 1;
+
+ BOOL fMouseDownL = 0, fMouseOverL = 0, fBarHot = 0;
+ BOOL fMouseDownR = 0, fMouseOverR = 0;
+
+ COLORREF crCheck1 = GetSBForeColor();
+ COLORREF crCheck2 = GetSBBackColor();
+ COLORREF crInverse1 = InvertCOLORREF(crCheck1);
+ COLORREF crInverse2 = InvertCOLORREF(crCheck2);
+
+ //UINT uDFCFlat = sb->fFlatScrollbar ? DFCS_FLAT : 0;
+ UINT uDEFlat = sb->fFlatScrollbar ? BF_FLAT : 0;
+
+ //drawing flags to modify the appearance of the scrollbar buttons
+ UINT uLeftButFlags = DFCS_SCROLLLEFT;
+ UINT uRightButFlags = DFCS_SCROLLRIGHT;
+
+ if(scrollwidth <= 0)
+ return 0;
+
+ si = &sb->scrollInfo;
+ siMaxMin = si->nMax - si->nMin;
+
+ if(hwnd != hwndCurCoolSB)
+ uDrawFlags = HTSCROLL_NONE;
+ //
+ // work out the thumb size and position
+ //
+ CalcThumbSize(sb, rect, &thumbwidth, &thumbpos);
+
+ if(sb->fScrollFlags & ESB_DISABLE_LEFT) uLeftButFlags |= DFCS_INACTIVE;
+ if(sb->fScrollFlags & ESB_DISABLE_RIGHT) uRightButFlags |= DFCS_INACTIVE;
+
+ //if we need to grey the arrows because there is no data to scroll
+ if(!IsScrollInfoActive(si) && !(sb->fScrollFlags & CSBS_THUMBALWAYS))
+ {
+ uLeftButFlags |= DFCS_INACTIVE;
+ uRightButFlags |= DFCS_INACTIVE;
+ }
+
+ if(hwnd == hwndCurCoolSB)
+ {
+#ifdef FLAT_SCROLLBARS
+ BOOL ldis = !(uLeftButFlags & DFCS_INACTIVE);
+ BOOL rdis = !(uRightButFlags & DFCS_INACTIVE);
+
+ fBarHot = (sb->nBarType == (int)uMouseOverScrollbar && sb->fFlatScrollbar == CSBS_HOTTRACKED);
+
+ fMouseOverL = uHitTestPortion == HTSCROLL_LEFT && fBarHot && ldis;
+ fMouseOverR = uHitTestPortion == HTSCROLL_RIGHT && fBarHot && rdis;
+#endif
+ fMouseDownL = (uDrawFlags == HTSCROLL_LEFT);
+ fMouseDownR = (uDrawFlags == HTSCROLL_RIGHT);
+ }
+
+
+//#ifdef CUSTOM_DRAW
+ fCustomDraw = ((PostCustomPrePostPaint(hwnd, hdc, sb, CDDS_PREPAINT)) == CDRF_SKIPDEFAULT);
+ //#endif
+
+ //
+ // Draw the scrollbar now
+ //
+ if(scrollwidth > butwidth*2)
+ {
+ //LEFT ARROW
+ SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
+
+ RotateRect0(sb, &ctrl);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE);
+ else
+ DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL);
+
+ RotateRect0(sb, &ctrl);
+
+ //MIDDLE PORTION
+ //if we can fit the thumbbar in, then draw it
+ if(thumbwidth > 0 && thumbwidth <= workingwidth
+ && IsScrollInfoActive(si) && ((sb->fScrollFlags & ESB_DISABLE_BOTH) != ESB_DISABLE_BOTH))
+ {
+ //Draw the scrollbar margin above the thumb
+ SetRect(&sbm, rect->left + butwidth, rect->top, thumbpos, rect->bottom);
+
+ RotateRect0(sb, &sbm);
+
+ if(fCustomDraw)
+ {
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGELEFT, uDrawFlags == HTSCROLL_PAGELEFT, FALSE, FALSE);
+ }
+ else
+ {
+ if(uDrawFlags == HTSCROLL_PAGELEFT)
+ DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
+ else
+ DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
+
+ }
+
+ RotateRect0(sb, &sbm);
+
+ //Draw the margin below the thumb
+ sbm.left = thumbpos+thumbwidth;
+ sbm.right = rect->right - butwidth;
+
+ RotateRect0(sb, &sbm);
+ if(fCustomDraw)
+ {
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGERIGHT, uDrawFlags == HTSCROLL_PAGERIGHT, 0, 0);
+ }
+ else
+ {
+ if(uDrawFlags == HTSCROLL_PAGERIGHT)
+ DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
+ else
+ DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
+
+ }
+ RotateRect0(sb, &sbm);
+
+ //Draw the THUMB finally
+ SetRect(&thumb, thumbpos, rect->top, thumbpos+thumbwidth, rect->bottom);
+
+ RotateRect0(sb, &thumb);
+
+ if(fCustomDraw)
+ {
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &thumb, SB_THUMBTRACK, uDrawFlags==HTSCROLL_THUMB, uHitTestPortion == HTSCROLL_THUMB && fBarHot, FALSE);
+ }
+ else
+ {
+
+#ifdef FLAT_SCROLLBARS
+ if(hwnd == hwndCurCoolSB && sb->fFlatScrollbar && (uDrawFlags == HTSCROLL_THUMB ||
+ (uHitTestPortion == HTSCROLL_THUMB && fBarHot)))
+ {
+ PaintRect(hdc, &thumb, GetSysColor(COLOR_3DSHADOW));
+ }
+ else
+#endif
+ {
+ DrawBlankButton(hdc, &thumb, uDEFlat);
+ }
+ }
+ RotateRect0(sb, &thumb);
+
+ }
+ //otherwise, just leave that whole area blank
+ else
+ {
+ OffsetRect(&ctrl, butwidth, 0);
+ ctrl.right = rect->right - butwidth;
+
+ //if we always show the thumb covering the whole scrollbar,
+ //then draw it that way
+ if(!IsScrollInfoActive(si) && (sb->fScrollFlags & CSBS_THUMBALWAYS)
+ && ctrl.right - ctrl.left > sb->nMinThumbSize)
+ {
+ //leave a 1-pixel gap between the thumb + right button
+ ctrl.right --;
+ RotateRect0(sb, &ctrl);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_THUMBTRACK, fMouseDownL, FALSE, FALSE);
+ else
+ {
+#ifdef FLAT_SCROLLBARS
+ if(sb->fFlatScrollbar == CSBS_HOTTRACKED && uDrawFlags == HTSCROLL_THUMB)
+ PaintRect(hdc, &ctrl, GetSysColor(COLOR_3DSHADOW));
+ else
+#endif
+ DrawBlankButton(hdc, &ctrl, uDEFlat);
+
+ }
+ RotateRect0(sb, &ctrl);
+
+ //draw the single-line gap
+ ctrl.left = ctrl.right;
+ ctrl.right += 1;
+
+ RotateRect0(sb, &ctrl);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
+ else
+ PaintRect(hdc, &ctrl, GetSysColor(COLOR_SCROLLBAR));
+
+ RotateRect0(sb, &ctrl);
+ }
+ //otherwise, paint a blank if the thumb doesn't fit in
+ else
+ {
+ RotateRect0(sb, &ctrl);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
+ else
+ DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2);
+
+ RotateRect0(sb, &ctrl);
+ }
+ }
+
+ //RIGHT ARROW
+ SetRect(&ctrl, rect->right - butwidth, rect->top, rect->right, rect->bottom);
+
+ RotateRect0(sb, &ctrl);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE);
+ else
+ DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR);
+
+ RotateRect0(sb, &ctrl);
+ }
+ //not enough room for the scrollbar, so just draw the buttons (scaled in size to fit)
+ else
+ {
+ butwidth = scrollwidth / 2;
+
+ //LEFT ARROW
+ SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
+
+ RotateRect0(sb, &ctrl);
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE);
+ else
+ DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL);
+ RotateRect0(sb, &ctrl);
+
+ //RIGHT ARROW
+ OffsetRect(&ctrl, scrollwidth - butwidth, 0);
+
+ RotateRect0(sb, &ctrl);
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE);
+ else
+ DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR);
+ RotateRect0(sb, &ctrl);
+
+ //if there is a gap between the buttons, fill it with a solid color
+ //if(butwidth & 0x0001)
+ if(ctrl.left != rect->left + butwidth)
+ {
+ ctrl.left --;
+ ctrl.right -= butwidth;
+ RotateRect0(sb, &ctrl);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
+ else
+ DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2);
+
+ RotateRect0(sb, &ctrl);
+ }
+
+ }
+
+//#ifdef CUSTOM_DRAW
+ PostCustomPrePostPaint(hwnd, hdc, sb, CDDS_POSTPAINT);
+//#endif
+
+ return fCustomDraw;
+}
+
+//
+// Draw a vertical scrollbar using the horizontal draw routine, but
+// with the coordinates adjusted accordingly
+//
+static LRESULT NCDrawVScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
+{
+ LRESULT ret;
+ RECT rc;
+
+ rc = *rect;
+ RotateRect(&rc);
+ ret = NCDrawHScrollbar(sb, hwnd, hdc, &rc, uDrawFlags);
+ RotateRect(&rc);
+
+ return ret;
+}
+
+//
+// Generic wrapper function for the scrollbar drawing
+//
+static LRESULT NCDrawScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
+{
+ if(sb->nBarType == SB_HORZ)
+ return NCDrawHScrollbar(sb, hwnd, hdc, rect, uDrawFlags);
+ else
+ return NCDrawVScrollbar(sb, hwnd, hdc, rect, uDrawFlags);
+}
+
+#ifdef INCLUDE_BUTTONS
+
+//
+// Draw the specified bitmap centered in the rectangle
+//
+static void DrawImage(HDC hdc, HBITMAP hBitmap, RECT *rc)
+{
+ BITMAP bm;
+ int cx;
+ int cy;
+ HDC memdc;
+ HBITMAP hOldBM;
+ RECT rcDest = *rc;
+ POINT p;
+ SIZE delta;
+ COLORREF colorOld;
+
+ if(hBitmap == NULL)
+ return;
+
+ // center bitmap in caller's rectangle
+ GetObject(hBitmap, sizeof bm, &bm);
+
+ cx = bm.bmWidth;
+ cy = bm.bmHeight;
+
+ delta.cx = (rc->right-rc->left - cx) / 2;
+ delta.cy = (rc->bottom-rc->top - cy) / 2;
+
+ if(rc->right-rc->left > cx)
+ {
+ SetRect(&rcDest, rc->left+delta.cx, rc->top + delta.cy, 0, 0);
+ rcDest.right = rcDest.left + cx;
+ rcDest.bottom = rcDest.top + cy;
+ p.x = 0;
+ p.y = 0;
+ }
+ else
+ {
+ p.x = -delta.cx;
+ p.y = -delta.cy;
+ }
+
+ // select checkmark into memory DC
+ memdc = CreateCompatibleDC(hdc);
+ hOldBM = (HBITMAP)SelectObject(memdc, hBitmap);
+
+ // set BG color based on selected state
+ colorOld = SetBkColor(hdc, GetSysColor(COLOR_3DFACE));
+
+ BitBlt(hdc, rcDest.left, rcDest.top, rcDest.right-rcDest.left, rcDest.bottom-rcDest.top, memdc, p.x, p.y, SRCCOPY);
+
+ // restore
+ SetBkColor(hdc, colorOld);
+ SelectObject(memdc, hOldBM);
+ DeleteDC(memdc);
+}
+
+//
+// Draw the specified metafile
+//
+static void DrawMetaFile(HDC hdc, HENHMETAFILE hemf, RECT *rect)
+{
+ RECT rc;
+ POINT pt;
+
+ SetRect(&rc, 0, 0, rect->right-rect->left, rect->bottom-rect->top);
+ SetWindowOrgEx(hdc, -rect->left, -rect->top, &pt);
+ PlayEnhMetaFile(hdc, hemf, &rc);
+ SetWindowOrgEx(hdc, pt.x, pt.y, 0);
+}
+
+//
+// Draw a single scrollbar inserted button, in whatever style
+// it has been defined to use.
+//
+static UINT DrawScrollButton(SCROLLBUT *sbut, HDC hdc, const RECT *pctrl, UINT flags)
+{
+ NMCSBCUSTOMDRAW nmcd;
+ HWND hwnd;
+ RECT rect = *pctrl;
+ UINT f;
+
+ switch(sbut->uButType & SBBT_MASK)
+ {
+ case SBBT_OWNERDRAW:
+
+ hwnd = WindowFromDC(hdc);
+
+ //fill in the standard header
+ nmcd.hdr.hwndFrom = hwnd;
+<<<<<<< .mine
+ nmcd.hdr.idFrom = GetWindowLongPtr(hwnd, GWL_ID);
+=======
+ nmcd.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID);
+>>>>>>> .r12533
+ nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW;
+
+ nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
+ nmcd.nBar = SB_INSBUT;
+ nmcd.rect = *pctrl;
+ nmcd.uItem = sbut->uCmdId;
+ nmcd.hdc = hdc;
+ nmcd.uState = flags;
+
+ IntersectClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);
+ SendMessage(GetParent(hwnd), WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
+ SelectClipRgn(hdc, NULL);
+
+ break;
+
+ case SBBT_FIXED:
+ flags &= ~SBBS_PUSHED;
+
+ case SBBT_TOGGLEBUTTON:
+ if(sbut->uState != SBBS_NORMAL)
+ flags |= SBBS_PUSHED;
+
+ //intentionally fall through here...
+
+ case SBBT_PUSHBUTTON:
+
+ f = flags & SBBS_PUSHED ? DFCS_PUSHED | DFCS_FLAT : 0;
+ if(sbut->uButType & SBBM_LEFTARROW)
+ {
+ DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLLEFT | f);
+ }
+ else if(sbut->uButType & SBBM_RIGHTARROW)
+ {
+ DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLRIGHT | f);
+ }
+ else if(sbut->uButType & SBBM_UPARROW)
+ {
+ DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLUP | f);
+ }
+ else if(sbut->uButType & SBBM_DOWNARROW)
+ {
+ DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | f);
+ }
+ else
+ {
+ //
+ if(flags & SBBS_PUSHED)
+ {
+ if(sbut->uButType & SBBM_RECESSED)
+ {
+ InflateRect(&rect, -1, -1);
+ DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT|BF_FLAT);
+ InflateRect(&rect, 1, 1);
+
+ FrameRect(hdc, &rect, GetSysColorBrush(COLOR_3DDKSHADOW));
+ InflateRect(&rect, -2, -2);
+ }
+ else
+ {
+ DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_FLAT | BF_ADJUST);
+ InflateRect(&rect, 1, 1);
+ }
+ }
+ else
+ {
+ // draw the button borders
+ if(sbut->uButType & SBBM_TYPE2)
+ {
+ DrawFrameControl(hdc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH);
+ InflateRect(&rect, -2, -2);
+ }
+
+ else if(sbut->uButType & SBBM_TYPE3)
+ {
+ DrawFrameControl(hdc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH);
+ InflateRect(&rect, -1, -1);
+ }
+ else
+ {
+ DrawEdge(hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
+ rect.bottom++;
+ rect.right++;
+ }
+
+ OffsetRect(&rect, -1, -1);
+ rect.top++; rect.left++;
+ }
+
+ if(sbut->hBmp)
+ {
+ PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE));
+
+ if(flags & SBBS_PUSHED)
+ {
+ rect.top++; rect.left++;
+ }
+
+ IntersectClipRect(hdc, rect.left, rect.top, rect.right,rect.bottom);
+ DrawImage(hdc, sbut->hBmp, &rect);
+ SelectClipRgn(hdc, 0);
+ }
+ else if(sbut->hEmf)
+ {
+ PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE));
+ InflateRect(&rect, -1, -1);
+
+ if(flags & SBBS_PUSHED)
+ {
+ rect.top++; rect.left++;
+ }
+
+ IntersectClipRect(hdc, rect.left, rect.top, rect.right,rect.bottom);
+ DrawMetaFile(hdc, sbut->hEmf, &rect);
+ SelectClipRgn(hdc, 0);
+ }
+ else
+ {
+ PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE));
+ }
+ }
+
+
+ break;
+
+ case SBBT_BLANK:
+ PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE));
+ break;
+
+ case SBBT_FLAT:
+ DrawBlankButton(hdc, &rect, BF_FLAT);
+ break;
+
+ case SBBT_DARK:
+ PaintRect(hdc, &rect, GetSysColor(COLOR_3DDKSHADOW));
+ break;
+ }
+
+ return 0;
+}
+
+//
+// Draw any buttons inserted into the horizontal scrollbar
+// assume that the button widths have already been calculated
+// Note: RECT *rect is the rectangle of the scrollbar
+// leftright: 1 = left, 2 = right, 3 = both
+//
+static LRESULT DrawHorzButtons(SCROLLBAR *sbar, HDC hdc, const RECT *rect, int leftright)
+{
+ int i;
+ int xposl, xposr;
+ RECT ctrl;
+ SCROLLBUT *sbut = sbar->sbButtons;
+
+ xposl = rect->left - sbar->nButSizeBefore;
+ xposr = rect->right;
+
+ for(i = 0; i < sbar->nButtons; i++)
+ {
+ if((leftright & SBBP_LEFT) && sbut[i].uPlacement == SBBP_LEFT)
+ {
+ int butwidth = GetSingleButSize(sbar, &sbut[i]);
+ SetRect(&ctrl, xposl, rect->top, xposl + butwidth, rect->bottom);
+ RotateRect0(sbar, &ctrl);
+ DrawScrollButton(&sbut[i], hdc, &ctrl, SBBS_NORMAL);
+
+ xposl += butwidth;
+ }
+
+ if((leftright & SBBP_RIGHT) && sbut[i].uPlacement == SBBP_RIGHT)
+ {
+ int butwidth = GetSingleButSize(sbar, &sbut[i]);
+ SetRect(&ctrl, xposr, rect->top, xposr + butwidth, rect->bottom);
+ RotateRect0(sbar, &ctrl);
+ DrawScrollButton(&sbut[i], hdc, &ctrl, SBBS_NORMAL);
+ xposr += butwidth;
+ }
+ }
+ return 0;
+}
+
+static LRESULT DrawVertButtons(SCROLLBAR *sbar, HDC hdc, const RECT *rect, int leftright)
+{
+ RECT rc = *rect;
+ RotateRect(&rc);
+ DrawHorzButtons(sbar, hdc, &rc, leftright);
+ return 0;
+}
+#endif // INCLUDE_BUTTONS
+
+//
+// Define these two for proper processing of NCPAINT
+// NOT needed if we don't bother to mask the scrollbars we draw
+// to prevent the old window procedure from accidently drawing over them
+//
+HDC CoolSB_GetDC(HWND hwnd, WPARAM wParam)
+{
+ // I just can't figure out GetDCEx, so I'll just use this:
+ return GetWindowDC(hwnd);
+
+ /*
+ RECT rc;
+ DWORD flags = 0x10000;
+ HRGN hrgn = (HRGN)wParam;
+
+ if(hrgn == (HRGN)1)
+ {
+ GetWindowRect(hwnd, &rc);
+ OffsetRect(&rc, -rc.left, -rc.top);
+ hrgn = CreateRectRgnIndirect(&rc);
+ }
+
+ if(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CLIPCHILDREN)
+ flags |= DCX_CLIPCHILDREN;
+
+ if(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CLIPSIBLINGS)
+ flags |= DCX_CLIPSIBLINGS;
+
+ return GetDCEx(hwnd, hrgn, flags | DCX_CACHE|DCX_NORESETATTRS|DCX_WINDOW | DCX_INTERSECTUPDATE);
+ */
+ //return GetDCEx(hwnd, NULL, flags | DCX_WINDOW| DCX_NORESETATTRS);
+}
+
+static LRESULT NCPaint(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ SCROLLBAR *sb;
+ HDC hdc;
+ HRGN hrgn;
+ RECT winrect, rect;
+ HRGN clip = 0;
+ BOOL fUpdateAll = ((LONG)wParam == 1);
+ BOOL fCustomDraw = FALSE;
+ LRESULT ret;
+ DWORD dwStyle;
+
+ GetWindowRect(hwnd, &winrect);
+
+ //if entire region needs painting, then make a region to cover the entire window
+ if(fUpdateAll)
+ hrgn = (HRGN)wParam;
+ else
+ hrgn = (HRGN)wParam;
+
+ //hdc = GetWindowDC(hwnd);
+ hdc = CoolSB_GetDC(hwnd, wParam);
+
+ //
+ // Only draw the horizontal scrollbar if the window is tall enough
+ //
+ sb = &sw->sbarHorz;
+ if(sb->fScrollVisible)
+ {
+ int hbarwidth, leftright;
+
+ hbarwidth = leftright = 0;
+
+ //get the screen coordinates of the whole horizontal scrollbar area
+ GetHScrollRect(sw, hwnd, &rect);
+
+ //make the coordinates relative to the window for drawing
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+
+#ifdef INCLUDE_BUTTONS
+
+ //work out the size of any inserted buttons so we can dra them
+ sb->nButSizeBefore = GetButtonSize(sb, hwnd, SBBP_LEFT);
+ sb->nButSizeAfter = GetButtonSize(sb, hwnd, SBBP_RIGHT);
+
+ //make sure there is room for the buttons
+ hbarwidth = rect.right - rect.left;
+
+ //check that we can fit any left/right buttons in the available space
+ if(sb->nButSizeAfter < (hbarwidth - MIN_COOLSB_SIZE))
+ {
+ //adjust the scrollbar rectangle to fit the buttons into
+ sb->fButVisibleAfter = TRUE;
+ rect.right -= sb->nButSizeAfter;
+ leftright |= SBBP_RIGHT;
+
+ //check that there is enough space for the right buttons
+ if(sb->nButSizeBefore + sb->nButSizeAfter < (hbarwidth - MIN_COOLSB_SIZE))
+ {
+ sb->fButVisibleBefore = TRUE;
+ rect.left += sb->nButSizeBefore;
+ leftright |= SBBP_LEFT;
+ }
+ else
+ sb->fButVisibleBefore = FALSE;
+ }
+ else
+ sb->fButVisibleAfter = FALSE;
+
+
+ DrawHorzButtons(sb, hdc, &rect, leftright);
+#endif// INCLUDE_BUTTONS
+
+ if(uCurrentScrollbar == SB_HORZ)
+ fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
+ else
+ fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE);
+ }
+
+ //
+ // Only draw the vertical scrollbar if the window is wide enough to accomodate it
+ //
+ sb = &sw->sbarVert;
+ if(sb->fScrollVisible)
+ {
+ int vbarheight;
+ vbarheight = 0;
+
+ //get the screen cooridinates of the whole horizontal scrollbar area
+ GetVScrollRect(sw, hwnd, &rect);
+
+ //make the coordinates relative to the window for drawing
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+
+#ifdef INCLUDE_BUTTONS
+
+ //work out the size of any inserted buttons so we can dra them
+ sb->nButSizeBefore = GetButtonSize(sb, hwnd, SBBP_LEFT);
+ sb->nButSizeAfter = GetButtonSize(sb, hwnd, SBBP_RIGHT);
+
+ //make sure there is room for the buttons
+ vbarheight = rect.bottom - rect.top;
+
+ //check that we can fit any left/right buttons in the available space
+ if(sb->nButSizeAfter < (vbarheight - MIN_COOLSB_SIZE))
+ {
+ //adjust the scrollbar rectangle to fit the buttons into
+ sb->fButVisibleAfter = TRUE;
+ rect.bottom -= sb->nButSizeAfter;
+ updown |= SBBP_BOTTOM;
+
+ //check that there is enough space for the right buttons
+ if(sb->nButSizeBefore + sb->nButSizeAfter < (vbarheight - MIN_COOLSB_SIZE))
+ {
+ sb->fButVisibleBefore = TRUE;
+ rect.top += sb->nButSizeBefore;
+ updown |= SBBP_TOP;
+ }
+ else
+ sb->fButVisibleBefore = FALSE;
+ }
+ else
+ sb->fButVisibleAfter = FALSE;
+
+
+ DrawVertButtons(sb, hdc, &rect, updown);
+#endif // INCLUDE_BUTTONS
+
+ if(uCurrentScrollbar == SB_VERT)
+ fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
+ else
+ fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE);
+ }
+
+ //Call the default window procedure for WM_NCPAINT, with the
+ //new window region. ** region must be in SCREEN coordinates **
+ dwStyle = GetWindowLong(hwnd, GWL_STYLE);
+
+ // If the window has WS_(H-V)SCROLL bits set, we should reset them
+ // to avoid windows taking the scrollbars into account.
+ // We temporarily set a flag preventing the subsecuent
+ // WM_STYLECHANGING/WM_STYLECHANGED to be forwarded to
+ // the original window procedure
+ if ( dwStyle & (WS_VSCROLL|WS_HSCROLL) )
+ {
+ sw->bPreventStyleChange = TRUE;
+ SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL|WS_HSCROLL));
+ }
+
+ ret = CallWindowProc(sw->oldproc, hwnd, WM_NCPAINT, (WPARAM)hrgn, lParam);
+
+ if ( dwStyle & (WS_VSCROLL|WS_HSCROLL) )
+ {
+ SetWindowLong(hwnd, GWL_STYLE, dwStyle);
+ sw->bPreventStyleChange = FALSE;
+ }
+
+
+ // DRAW THE DEAD AREA
+ // only do this if the horizontal and vertical bars are visible
+ if(sw->sbarHorz.fScrollVisible && sw->sbarVert.fScrollVisible)
+ {
+ GetWindowRect(hwnd, &rect);
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+
+ rect.bottom -= sw->cyBottomEdge;
+ rect.top = rect.bottom - GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB);
+
+ if(sw->fLeftScrollbar)
+ {
+ rect.left += sw->cxLeftEdge;
+ rect.right = rect.left + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
+ }
+ else
+ {
+ rect.right -= sw->cxRightEdge;
+ rect.left = rect.right - GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
+ }
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, SB_BOTH, &rect, 32, 0, 0, 0);
+ else
+ {
+ //calculate the position of THIS window's dead area
+ //with the position of the PARENT window's client rectangle.
+ //if THIS window has been positioned such that its bottom-right
+ //corner sits in the parent's bottom-right corner, then we should
+ //show the sizing-grip.
+ //Otherwise, assume this window is not in the right place, and
+ //just draw a blank rectangle
+ RECT parent;
+ RECT rect2;
+ HWND hwndParent = GetParent(hwnd);
+
+ GetClientRect(hwndParent, &parent);
+ MapWindowPoints(hwndParent, 0, (POINT *)&parent, 2);
+
+ CopyRect(&rect2, &rect);
+ OffsetRect(&rect2, winrect.left, winrect.top);
+
+ if(!sw->fLeftScrollbar && parent.right == rect2.right+sw->cxRightEdge && parent.bottom == rect2.bottom+sw->cyBottomEdge
+ || sw->fLeftScrollbar && parent.left == rect2.left -sw->cxLeftEdge && parent.bottom == rect2.bottom+sw->cyBottomEdge)
+ DrawFrameControl(hdc, &rect, DFC_SCROLL, sw->fLeftScrollbar ? DFCS_SCROLLSIZEGRIPRIGHT : DFCS_SCROLLSIZEGRIP );
+ else
+ PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE));
+ }
+ }
+
+ UNREFERENCED_PARAMETER(clip);
+ ReleaseDC(hwnd, hdc);
+ return ret;
+}
+
+//
+// Need to detect if we have clicked in the scrollbar region or not
+//
+static LRESULT NCHitTest(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ RECT hrect;
+ RECT vrect;
+ POINT pt;
+
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ //work out exactly where the Horizontal and Vertical scrollbars are
+ GetHScrollRect(sw, hwnd, &hrect);
+ GetVScrollRect(sw, hwnd, &vrect);
+
+ //Clicked in the horizontal scrollbar area
+ if(sw->sbarHorz.fScrollVisible && PtInRect(&hrect, pt))
+ {
+ return HTHSCROLL;
+ }
+ //Clicked in the vertical scrollbar area
+ else if(sw->sbarVert.fScrollVisible && PtInRect(&vrect, pt))
+ {
+ return HTVSCROLL;
+ }
+ //clicked somewhere else
+ else
+ {
+ return CallWindowProc(sw->oldproc, hwnd, WM_NCHITTEST, wParam, lParam);
+ }
+}
+
+//
+// Return a HT* value indicating what part of the scrollbar was clicked
+// Rectangle is not adjusted
+//
+static UINT GetHorzPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
+{
+ RECT rc = *rect;
+
+ if(y < rc.top || y >= rc.bottom) return HTSCROLL_NONE;
+
+#ifdef INCLUDE_BUTTONS
+
+ if(sb->fButVisibleBefore)
+ {
+ //clicked on the buttons to the left of the scrollbar
+ if(x >= rc.left && x < rc.left + sb->nButSizeBefore)
+ return HTSCROLL_INSERTED;
+
+ //adjust the rectangle to exclude the left-side buttons, now that we
+ //know we havn't clicked on them
+ rc.left += sb->nButSizeBefore;
+ }
+
+ if(sb->fButVisibleAfter)
+ {
+ //clicked on the buttons to the right of the scrollbar
+ if(x >= rc.right - sb->nButSizeAfter && x < rc.right)
+ return HTSCROLL_INSERTED;
+
+ //adjust the rectangle to exclude the right-side buttons, now that we
+ //know we havn't clicked on them
+ rc.right -= sb->nButSizeAfter;
+ }
+
+#endif INCLUDE_BUTTONS
+
+ //Now we have the rectangle for the scrollbar itself, so work out
+ //what part we clicked on.
+ return GetHorzScrollPortion(sb, hwnd, &rc, x, y);
+}
+
+//
+// Just call the horizontal version, with adjusted coordinates
+//
+static UINT GetVertPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
+{
+ UINT ret;
+ RotateRect(rect);
+ ret = GetHorzPortion(sb, hwnd, rect, y, x);
+ RotateRect(rect);
+ return ret;
+}
+
+//
+// Wrapper function for GetHorzPortion and GetVertPortion
+//
+static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
+{
+ if(sb->nBarType == SB_HORZ)
+ return GetHorzPortion(sb, hwnd, rect, x, y);
+ else if(sb->nBarType == SB_VERT)
+ return GetVertPortion(sb, hwnd, rect, x, y);
+ else
+ return HTSCROLL_NONE;
+}
+
+//
+// Input: rectangle of the total scrollbar area
+// Output: adjusted to take the inserted buttons into account
+//
+static void GetRealHorzScrollRect(SCROLLBAR *sb, RECT *rect)
+{
+ if(sb->fButVisibleBefore) rect->left += sb->nButSizeBefore;
+ if(sb->fButVisibleAfter) rect->right -= sb->nButSizeAfter;
+}
+
+//
+// Input: rectangle of the total scrollbar area
+// Output: adjusted to take the inserted buttons into account
+//
+static void GetRealVertScrollRect(SCROLLBAR *sb, RECT *rect)
+{
+ if(sb->fButVisibleBefore) rect->top += sb->nButSizeBefore;
+ if(sb->fButVisibleAfter) rect->bottom -= sb->nButSizeAfter;
+}
+
+//
+// Decide which type of scrollbar we have before calling
+// the real function to do the job
+//
+static void GetRealScrollRect(SCROLLBAR *sb, RECT *rect)
+{
+ if(sb->nBarType == SB_HORZ)
+ {
+ GetRealHorzScrollRect(sb, rect);
+ }
+ else if(sb->nBarType == SB_VERT)
+ {
+ GetRealVertScrollRect(sb, rect);
+ }
+}
+
+//
+// All button code shoule be collected together
+//
+//
+#ifdef INCLUDE_BUTTONS
+
+//
+// Return the index of the button covering the specified point
+// rect - rectangle of the whole scrollbar area
+// pt - screen coords of the mouse
+// fReturnRect - do/don't modify the rect to return the button's area
+//
+static UINT GetHorzButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect)
+{
+ int leftpos = rect->left, rightpos = rect->right;
+ int i;
+ int butwidth;
+ SCROLLBUT *sbut = sb->sbButtons;
+
+ if(!PtInRect(rect, pt))
+ return -1;
+
+ if(sb->fButVisibleAfter)
+ rightpos -= sb->nButSizeAfter;
+
+ for(i = 0; i < sb->nButtons; i++)
+ {
+ if(sb->fButVisibleBefore && sbut[i].uPlacement == SBBP_LEFT)
+ {
+ butwidth = GetSingleButSize(sb, &sbut[i]);
+
+ //if the current button is under the specified point
+ if(pt.x >= leftpos && pt.x < leftpos + butwidth)
+ {
+ //if the caller wants us to return the rectangle of the button
+ if(fReturnRect)
+ {
+ rect->left = leftpos;
+ rect->right = leftpos + butwidth;
+ }
+
+ return i;
+ }
+
+ leftpos += butwidth;
+ }
+ else if(sb->fButVisibleAfter && sbut[i].uPlacement == SBBP_RIGHT)
+ {
+ butwidth = GetSingleButSize(sb, &sbut[i]);
+
+ //if the current button is under the specified point
+ if(pt.x >= rightpos && pt.x < rightpos + butwidth)
+ {
+ //if the caller wants us to return the rectangle of the button
+ if(fReturnRect)
+ {
+ rect->left = rightpos;
+ rect->right = rightpos + butwidth;
+ }
+ return i;
+ }
+
+ rightpos += butwidth;
+ }
+ }
+
+ return -1;
+}
+
+
+static UINT GetVertButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect)
+{
+ UINT ret;
+ int temp;
+
+ //swap the X/Y coords
+ temp = pt.x;
+ pt.x = pt.y;
+ pt.y = temp;
+
+ //swap the rectangle
+ RotateRect(rect);
+
+ ret = GetHorzButtonFromPt(sb, rect, pt, fReturnRect);
+
+ RotateRect(rect);
+ return ret;
+}
+
+//
+//
+//
+static UINT GetButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect)
+{
+ if(sb->nBarType == SB_HORZ)
+ {
+ return GetHorzButtonFromPt(sb, rect, pt, fReturnRect);
+ }
+ else
+ {
+ return GetVertButtonFromPt(sb, rect, pt, fReturnRect);
+ }
+}
+
+//
+// Find the coordinates (in RECT format) of the specified button index
+//
+static UINT GetHorzButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index)
+{
+ UINT i;
+ SCROLLBUT *sbut = sb->sbButtons;
+ int leftpos = rect->left, rightpos = rect->right;
+
+ if(sb->fButVisibleAfter)
+ rightpos -= sb->nButSizeAfter;
+
+ //find the particular button in question
+ for(i = 0; i < index; i++)
+ {
+ if(sb->fButVisibleBefore && sbut[i].uPlacement == SBBP_LEFT)
+ {
+ leftpos += GetSingleButSize(sb, &sbut[i]);
+ }
+ else if(sb->fButVisibleAfter && sbut[i].uPlacement == SBBP_RIGHT)
+ {
+ rightpos += GetSingleButSize(sb, &sbut[i]);
+ }
+ }
+
+ //now return the rectangle
+ if(sbut[i].uPlacement == SBBP_LEFT)
+ {
+ rect->left = leftpos;
+ rect->right = leftpos + GetSingleButSize(sb, &sbut[i]);
+ }
+ else
+ {
+ rect->left = rightpos;
+ rect->right = rightpos + GetSingleButSize(sb, &sbut[i]);
+ }
+
+ return 0;
+}
+
+static UINT GetVertButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index)
+{
+ UINT ret;
+ RotateRect(rect);
+ ret = GetHorzButtonRectFromId(sb, rect, index);
+ RotateRect(rect);
+ return ret;
+}
+
+static UINT GetButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index)
+{
+ if(sb->nBarType == SB_HORZ)
+ {
+ return GetHorzButtonRectFromId(sb, rect, index);
+ }
+ else
+ {
+ return GetVertButtonRectFromId(sb, rect, index);
+ }
+}
+#endif //INCLUDE_BUTTONS
+
+//
+// Left button click in the non-client area
+//
+static LRESULT NCLButtonDown(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ RECT rect, winrect;
+ HDC hdc;
+ SCROLLBAR *sb;
+ SCROLLBUT *sbut;
+ POINT pt;
+
+ sbut = 0;
+
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ hwndCurCoolSB = hwnd;
+
+ //
+ // HORIZONTAL SCROLLBAR PROCESSING
+ //
+ if(wParam == HTHSCROLL)
+ {
+ uScrollTimerMsg = WM_HSCROLL;
+ uCurrentScrollbar = SB_HORZ;
+ sb = &sw->sbarHorz;
+
+ //get the total area of the normal Horz scrollbar area
+ GetHScrollRect(sw, hwnd, &rect);
+ uCurrentScrollPortion = GetHorzPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
+ }
+ //
+ // VERTICAL SCROLLBAR PROCESSING
+ //
+ else if(wParam == HTVSCROLL)
+ {
+ uScrollTimerMsg = WM_VSCROLL;
+ uCurrentScrollbar = SB_VERT;
+ sb = &sw->sbarVert;
+
+ //get the total area of the normal Horz scrollbar area
+ GetVScrollRect(sw, hwnd, &rect);
+ uCurrentScrollPortion = GetVertPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
+ }
+ //
+ // NORMAL PROCESSING
+ //
+ else
+ {
+ uCurrentScrollPortion = HTSCROLL_NONE;
+ return CallWindowProc(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam);
+ }
+
+ //
+ // we can now share the same code for vertical
+ // and horizontal scrollbars
+ //
+ switch(uCurrentScrollPortion)
+ {
+ //inserted buttons to the left/right
+#ifdef INCLUDE_BUTTONS
+ case HTSCROLL_INSERTED:
+
+#ifdef HOT_TRACKING
+ KillTimer(hwnd, uMouseOverId);
+ uMouseOverId = 0;
+ uMouseOverScrollbar = COOLSB_NONE;
+#endif
+
+ //find the index of the button that has been clicked
+ //adjust the rectangle to give the button's rectangle
+ uCurrentButton = GetButtonFromPt(sb, &rect, pt, TRUE);
+
+ sbut = &sb->sbButtons[uCurrentButton];
+
+ //post a notification message
+ PostMouseNotify(hwnd, NM_CLICK, sb->nBarType, &rect, sbut->uCmdId, pt);
+
+ GetWindowRect(hwnd, &winrect);
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+ hdc = GetWindowDC(hwnd);
+
+ DrawScrollButton(sbut, hdc, &rect, SBBS_PUSHED);
+
+ ReleaseDC(hwnd, hdc);
+
+ break;
+#endif //INCLUDE_BUTTONS
+
+ case HTSCROLL_THUMB:
+
+ //if the scrollbar is disabled, then do no further processing
+ if(!IsScrollbarActive(sb))
+ return 0;
+
+ GetRealScrollRect(sb, &rect);
+ RotateRect0(sb, &rect);
+ CalcThumbSize(sb, &rect, &nThumbSize, &nThumbPos);
+ RotateRect0(sb, &rect);
+
+ //remember the bounding rectangle of the scrollbar work area
+ rcThumbBounds = rect;
+
+ sw->fThumbTracking = TRUE;
+ sb->scrollInfo.nTrackPos = sb->scrollInfo.nPos;
+
+ if(wParam == HTVSCROLL)
+ nThumbMouseOffset = pt.y - nThumbPos;
+ else
+ nThumbMouseOffset = pt.x - nThumbPos;
+
+ nLastPos = -sb->scrollInfo.nPos;
+ nThumbPos0 = nThumbPos;
+
+ //if(sb->fFlatScrollbar)
+ //{
+ GetWindowRect(hwnd, &winrect);
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+ hdc = GetWindowDC(hwnd);
+ NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_THUMB);
+ ReleaseDC(hwnd, hdc);
+ //}
+
+ break;
+
+ //Any part of the scrollbar
+ case HTSCROLL_LEFT:
+ if(sb->fScrollFlags & ESB_DISABLE_LEFT) return 0;
+ else goto target1;
+
+ case HTSCROLL_RIGHT:
+ if(sb->fScrollFlags & ESB_DISABLE_RIGHT) return 0;
+ else goto target1;
+
+ goto target1;
+
+ case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
+
+ target1:
+
+ //if the scrollbar is disabled, then do no further processing
+ if(!IsScrollbarActive(sb))
+ break;
+
+ //ajust the horizontal rectangle to NOT include
+ //any inserted buttons
+ GetRealScrollRect(sb, &rect);
+
+ SendScrollMessage(hwnd, uScrollTimerMsg, uCurrentScrollPortion, 0);
+
+ // Check what area the mouse is now over :
+ // If the scroll thumb has moved under the mouse in response to
+ // a call to SetScrollPos etc, then we don't hilight the scrollbar margin
+ if(uCurrentScrollbar == SB_HORZ)
+ uScrollTimerPortion = GetHorzScrollPortion(sb, hwnd, &rect, pt.x, pt.y);
+ else
+ uScrollTimerPortion = GetVertScrollPortion(sb, hwnd, &rect, pt.x, pt.y);
+
+ GetWindowRect(hwnd, &winrect);
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+ hdc = GetWindowDC(hwnd);
+
+#ifndef HOT_TRACKING
+ //if we aren't hot-tracking, then don't highlight
+ //the scrollbar thumb unless we click on it
+ if(uScrollTimerPortion == HTSCROLL_THUMB)
+ uScrollTimerPortion = HTSCROLL_NONE;
+#endif
+ NCDrawScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
+ ReleaseDC(hwnd, hdc);
+
+ //Post the scroll message!!!!
+ uScrollTimerPortion = uCurrentScrollPortion;
+
+ //set a timer going on the first click.
+ //if this one expires, then we can start off a more regular timer
+ //to generate the auto-scroll behaviour
+ uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID1, COOLSB_TIMERINTERVAL1, 0);
+ break;
+ default:
+ return CallWindowProc(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam);
+ //return 0;
+ }
+
+ SetCapture(hwnd);
+ return 0;
+}
+
+//
+// Left button released
+//
+static LRESULT LButtonUp(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ RECT rect;
+ //UINT thisportion;
+ HDC hdc;
+ POINT pt;
+ RECT winrect;
+
+ //current scrollportion is the button that we clicked down on
+ if(uCurrentScrollPortion != HTSCROLL_NONE)
+ {
+ SCROLLBAR *sb = &sw->sbarHorz;
+ lParam = GetMessagePos();
+ ReleaseCapture();
+
+ GetWindowRect(hwnd, &winrect);
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ //emulate the mouse input on a scrollbar here...
+ if(uCurrentScrollbar == SB_HORZ)
+ {
+ //get the total area of the normal Horz scrollbar area
+ sb = &sw->sbarHorz;
+ GetHScrollRect(sw, hwnd, &rect);
+ }
+ else if(uCurrentScrollbar == SB_VERT)
+ {
+ //get the total area of the normal Horz scrollbar area
+ sb = &sw->sbarVert;
+ GetVScrollRect(sw, hwnd, &rect);
+ }
+
+ //we need to do different things depending on if the
+ //user is activating the scrollbar itself, or one of
+ //the inserted buttons
+ switch(uCurrentScrollPortion)
+ {
+#ifdef INCLUDE_BUTTONS
+ //inserted buttons are being clicked
+ case HTSCROLL_INSERTED:
+
+ //get the rectangle of the ACTIVE button
+ buttonIdx = GetButtonFromPt(sb, &rect, pt, FALSE);
+ GetButtonRectFromId(sb, &rect, uCurrentButton);
+
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+
+ //Send the notification BEFORE we redraw, so the
+ //bitmap can be changed smoothly by the user if they require
+ if(uCurrentButton == buttonIdx)
+ {
+ SCROLLBUT *sbut = &sb->sbButtons[buttonIdx];
+ UINT cmdid = sbut->uCmdId;
+
+ if((sbut->uButType & SBBT_MASK) == SBBT_TOGGLEBUTTON)
+ sbut->uState ^= 1;
+
+ //send a notify??
+ //only post a message if the command id is valid
+ if(cmdid != -1 && cmdid > 0)
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(cmdid, CSBN_CLICKED), 0);
+
+ //user might have deleted this button, so redraw whole area
+ NCPaint(sw, hwnd, 1, 0);
+ }
+ else
+ {
+ //otherwise, just redraw the button in its new state
+ hdc = GetWindowDC(hwnd);
+ DrawScrollButton(&sb->sbButtons[uCurrentButton], hdc, &rect, SBBS_NORMAL);
+ ReleaseDC(hwnd, hdc);
+ }
+
+ break;
+#endif // INCLUDE_BUTTONS
+
+ //The scrollbar is active
+ case HTSCROLL_LEFT: case HTSCROLL_RIGHT:
+ case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
+ case HTSCROLL_NONE:
+
+ KillTimer(hwnd, uScrollTimerId);
+
+ case HTSCROLL_THUMB:
+
+ //In case we were thumb tracking, make sure we stop NOW
+ if(sw->fThumbTracking == TRUE)
+ {
+ SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBPOSITION, nLastPos);
+ sw->fThumbTracking = FALSE;
+ }
+
+ //send the SB_ENDSCROLL message now that scrolling has finished
+ SendScrollMessage(hwnd, uScrollTimerMsg, SB_ENDSCROLL, 0);
+
+ //adjust the total scroll area to become where the scrollbar
+ //really is (take into account the inserted buttons)
+ GetRealScrollRect(sb, &rect);
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+ hdc = GetWindowDC(hwnd);
+
+ //draw whichever scrollbar sb is
+ NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL);
+
+ ReleaseDC(hwnd, hdc);
+ break;
+ }
+
+ //reset our state to default
+ uCurrentScrollPortion = HTSCROLL_NONE;
+ uScrollTimerPortion = HTSCROLL_NONE;
+ uScrollTimerId = 0;
+
+ uScrollTimerMsg = 0;
+ uCurrentScrollbar = COOLSB_NONE;
+
+ return 0;
+ }
+ else
+ {
+ /*
+ // Can't remember why I did this!
+ if(GetCapture() == hwnd)
+ {
+ ReleaseCapture();
+ }*/
+ }
+
+ return CallWindowProc(sw->oldproc, hwnd, WM_LBUTTONUP, wParam, lParam);
+}
+
+//
+// This function is called whenever the mouse is moved and
+// we are dragging the scrollbar thumb about.
+//
+static LRESULT ThumbTrackHorz(SCROLLBAR *sbar, HWND hwnd, int x, int y)
+{
+ POINT pt;
+ RECT rc, winrect, rc2;
+ COLORREF crCheck1 = GetSBForeColor();
+ COLORREF crCheck2 = GetSBBackColor();
+ HDC hdc;
+ int thumbpos = nThumbPos;
+ int pos;
+ int siMaxMin = 0;
+ UINT flatflag = sbar->fFlatScrollbar ? BF_FLAT : 0;
+ BOOL fCustomDraw = FALSE;
+
+ SCROLLINFO *si;
+ si = &sbar->scrollInfo;
+
+ pt.x = x;
+ pt.y = y;
+
+ //draw the thumb at whatever position
+ rc = rcThumbBounds;
+
+ SetRect(&rc2, rc.left - THUMBTRACK_SNAPDIST*2, rc.top - THUMBTRACK_SNAPDIST,
+ rc.right + THUMBTRACK_SNAPDIST*2, rc.bottom + THUMBTRACK_SNAPDIST);
+
+ rc.left += GetScrollMetric(sbar, SM_CXHORZSB);
+ rc.right -= GetScrollMetric(sbar, SM_CXHORZSB);
+
+ //if the mouse is not in a suitable distance of the scrollbar,
+ //then "snap" the thumb back to its initial position
+#ifdef SNAP_THUMB_BACK
+ if(!PtInRect(&rc2, pt))
+ {
+ thumbpos = nThumbPos0;
+ }
+ //otherwise, move the thumb to where the mouse is
+ else
+#endif //SNAP_THUMB_BACK
+ {
+ //keep the thumb within the scrollbar limits
+ thumbpos = pt.x - nThumbMouseOffset;
+ if(thumbpos < rc.left) thumbpos = rc.left;
+ if(thumbpos > rc.right - nThumbSize) thumbpos = rc.right - nThumbSize;
+ }
+
+ GetWindowRect(hwnd, &winrect);
+
+ if(sbar->nBarType == SB_VERT)
+ RotateRect(&winrect);
+
+ hdc = GetWindowDC(hwnd);
+
+//#ifdef CUSTOM_DRAW
+ fCustomDraw = PostCustomPrePostPaint(hwnd, hdc, sbar, CDDS_PREPAINT) == CDRF_SKIPDEFAULT;
+//#endif
+
+ OffsetRect(&rc, -winrect.left, -winrect.top);
+ thumbpos -= winrect.left;
+
+ //draw the margin before the thumb
+ SetRect(&rc2, rc.left, rc.top, thumbpos, rc.bottom);
+ RotateRect0(sbar, &rc2);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGELEFT, 0, 0, 0);
+ else
+ DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2);
+
+ RotateRect0(sbar, &rc2);
+
+ //draw the margin after the thumb
+ SetRect(&rc2, thumbpos+nThumbSize, rc.top, rc.right, rc.bottom);
+
+ RotateRect0(sbar, &rc2);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGERIGHT, 0, 0, 0);
+ else
+ DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2);
+
+ RotateRect0(sbar, &rc2);
+
+ //finally draw the thumb itelf. This is how it looks on win2000, anyway
+ SetRect(&rc2, thumbpos, rc.top, thumbpos+nThumbSize, rc.bottom);
+
+ RotateRect0(sbar, &rc2);
+
+ if(fCustomDraw)
+ PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_THUMBTRACK, TRUE, TRUE, FALSE);
+ else
+ {
+
+#ifdef FLAT_SCROLLBARS
+ if(sbar->fFlatScrollbar)
+ PaintRect(hdc, &rc2, GetSysColor(COLOR_3DSHADOW));
+ else
+#endif
+ {
+ DrawBlankButton(hdc, &rc2, flatflag);
+ }
+ }
+
+ RotateRect0(sbar, &rc2);
+ ReleaseDC(hwnd, hdc);
+
+ //post a SB_TRACKPOS message!!!
+ siMaxMin = si->nMax - si->nMin;
+
+ if(siMaxMin > 0)
+ pos = MulDiv(thumbpos-rc.left, siMaxMin-si->nPage + 1, rc.right-rc.left-nThumbSize);
+ else
+ pos = thumbpos - rc.left;
+
+ if(pos != nLastPos)
+ {
+ si->nTrackPos = pos;
+ SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, pos);
+ }
+
+ nLastPos = pos;
+
+//#ifdef CUSTOM_DRAW
+ PostCustomPrePostPaint(hwnd, hdc, sbar, CDDS_POSTPAINT);
+//#endif
+
+ return 0;
+}
+
+//
+// remember to rotate the thumb bounds rectangle!!
+//
+static LRESULT ThumbTrackVert(SCROLLBAR *sb, HWND hwnd, int x, int y)
+{
+ //sw->swapcoords = TRUE;
+ RotateRect(&rcThumbBounds);
+ ThumbTrackHorz(sb, hwnd, y, x);
+ RotateRect(&rcThumbBounds);
+ //sw->swapcoords = FALSE;
+
+ return 0;
+}
+
+//
+// Called when we have set the capture from the NCLButtonDown(...)
+//
+static LRESULT MouseMove(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ RECT rect;
+ UINT thisportion;
+ HDC hdc;
+ static UINT lastportion = 0;
+ static UINT lastbutton = 0;
+ POINT pt;
+ RECT winrect;
+ UINT buttonIdx = 0;
+
+ if(sw->fThumbTracking == TRUE)
+ {
+ int x, y;
+ lParam = GetMessagePos();
+ x = LOWORD(lParam);
+ y = HIWORD(lParam);
+
+ if(uCurrentScrollbar == SB_HORZ)
+ return ThumbTrackHorz(&sw->sbarHorz, hwnd, x,y);
+
+
+ else if(uCurrentScrollbar == SB_VERT)
+ return ThumbTrackVert(&sw->sbarVert, hwnd, x,y);
+ }
+
+ if(uCurrentScrollPortion == HTSCROLL_NONE)
+ {
+ return CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
+ }
+ else
+ {
+ LPARAM nlParam;
+ SCROLLBAR *sb = &sw->sbarHorz;
+ SCROLLBUT *sbut;
+
+ sbut = 0;
+
+ nlParam = GetMessagePos();
+
+ GetWindowRect(hwnd, &winrect);
+
+ pt.x = LOWORD(nlParam);
+ pt.y = HIWORD(nlParam);
+
+ //emulate the mouse input on a scrollbar here...
+ if(uCurrentScrollbar == SB_HORZ)
+ {
+ sb = &sw->sbarHorz;
+ }
+ else if(uCurrentScrollbar == SB_VERT)
+ {
+ sb = &sw->sbarVert;
+ }
+
+ //get the total area of the normal scrollbar area
+ GetScrollRect(sw, sb->nBarType, hwnd, &rect);
+
+ //see if we clicked in the inserted buttons / normal scrollbar
+ //thisportion = GetPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
+ thisportion = GetPortion(sb, hwnd, &rect, pt.x, pt.y);
+
+ //we need to do different things depending on if the
+ //user is activating the scrollbar itself, or one of
+ //the inserted buttons
+ switch(uCurrentScrollPortion)
+ {
+#ifdef INCLUDE_BUTTONS
+ //inserted buttons are being clicked
+ case HTSCROLL_INSERTED:
+
+ //find the index of the button that has been clicked
+ //Don't adjust the rectangle though
+ buttonIdx = GetButtonFromPt(sb, &rect, pt, FALSE);
+
+ //Get the rectangle of the active button
+ GetButtonRectFromId(sb, &rect, uCurrentButton);
+
+ //if the button to the LEFT of the current
+ //button is resizable, then resize it
+#ifdef RESIZABLE_BUTTONS
+ if(uCurrentButton > 0)
+ {
+ sbut = &sb->sbButtons[uCurrentButton - 1];
+
+ //only resize if BOTH buttons are on same side of scrollbar
+ if(sbut->uPlacement == (sbut+1)->uPlacement && (sbut->uButType & SBBM_RESIZABLE))
+ {
+ int oldsize = sbut->nSize;
+ int butsize1, butsize2;
+ RECT rect2;
+ int scrollsize;
+
+ if(uCurrentScrollbar == SB_HORZ)
+ {
+ rect.left -= GetSingleButSize(sb, sbut);
+ sbut->nSize = pt.x - rect.left;
+ }
+ else
+ {
+ rect.top -= GetSingleButSize(sb, sbut);
+ sbut->nSize = pt.y - rect.top;
+ }
+
+ //if(sbut->nSize < 0) sbut->nSize = 0;
+ if(sbut->nSize < (int)sbut->nMinSize)
+ sbut->nSize = sbut->nMinSize;
+
+ if((UINT)sbut->nSize > (UINT)sbut->nMaxSize)
+ sbut->nSize = sbut->nMaxSize;
+
+ GetScrollRect(sw, uCurrentScrollbar, hwnd, &rect2);
+
+ if(uCurrentScrollbar == SB_HORZ)
+ scrollsize = rect2.right-rect2.left;
+ else
+ scrollsize = rect2.bottom-rect2.top;
+
+ butsize1 = GetButtonSize(sb, hwnd, SBBP_LEFT);
+ butsize2 = GetButtonSize(sb, hwnd, SBBP_RIGHT);
+
+ //adjust the button size if it gets too big
+ if(butsize1 + butsize2 > scrollsize - MINSCROLLSIZE)
+ {
+ sbut->nSize -= (butsize1+butsize2) - (scrollsize - MINSCROLLSIZE);
+ }
+
+ //remember what size the USER set the button to
+ sbut->nSizeReserved = sbut->nSize;
+ NCPaint(sw, hwnd, (WPARAM)1, (LPARAM)0);
+ return 0;
+ }
+ }
+#endif //RESIZABLE_BUTTONS
+
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+
+ hdc = GetWindowDC(hwnd);
+
+ //if the button under the mouse is not the active button,
+ //then display the active button in its normal state
+ if(buttonIdx != uCurrentButton
+ //include this if toggle buttons always stay depressed
+ //if they are being activated
+ && (sb->sbButtons[uCurrentButton].uButType & SBBT_MASK) != SBBT_TOGGLEBUTTON)
+ {
+ if(lastbutton != buttonIdx)
+ DrawScrollButton(&sb->sbButtons[uCurrentButton], hdc, &rect, SBBS_NORMAL);
+ }
+ //otherwise, depress the active button if the mouse is over
+ //it (just like a normal scroll button works)
+ else
+ {
+ if(lastbutton != buttonIdx)
+ DrawScrollButton(&sb->sbButtons[uCurrentButton], hdc, &rect, SBBS_PUSHED);
+ }
+
+ ReleaseDC(hwnd, hdc);
+ return CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
+ //break;
+
+#endif //INCLUDE_BUTTONS
+
+ //The scrollbar is active
+ case HTSCROLL_LEFT: case HTSCROLL_RIGHT:case HTSCROLL_THUMB:
+ case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
+ case HTSCROLL_NONE:
+
+ //adjust the total scroll area to become where the scrollbar
+ //really is (take into account the inserted buttons)
+ GetRealScrollRect(sb, &rect);
+
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+ hdc = GetWindowDC(hwnd);
+
+ if(thisportion != uCurrentScrollPortion)
+ {
+ uScrollTimerPortion = HTSCROLL_NONE;
+
+ if(lastportion != thisportion)
+ NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL);
+ }
+ //otherwise, draw the button in its depressed / clicked state
+ else
+ {
+ uScrollTimerPortion = uCurrentScrollPortion;
+
+ if(lastportion != thisportion)
+ NCDrawScrollbar(sb, hwnd, hdc, &rect, thisportion);
+ }
+
+ ReleaseDC(hwnd, hdc);
+
+ break;
+ }
+
+
+ lastportion = thisportion;
+ lastbutton = buttonIdx;
+
+ //must return zero here, because we might get cursor anomilies
+ //CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
+ return 0;
+
+ }
+}
+
+#ifdef INCLUDE_BUTTONS
+#ifdef RESIZABLE_BUTTONS
+//
+// Any resizable buttons must be shrunk to fit if the window is made too small
+//
+static void ResizeButtonsToFit(SCROLLWND *sw, SCROLLBAR *sbar, HWND hwnd)
+{
+ int butsize1, butsize2;
+ RECT rc;
+ int scrollsize;
+ int i;
+ SCROLLBUT *sbut;
+
+ //make sure that the scrollbar can fit into space, by
+ //shrinking any resizable buttons
+ GetScrollRect(sw, sbar->nBarType, hwnd, &rc);
+
+ if(sbar->nBarType == SB_HORZ)
+ scrollsize = rc.right-rc.left;
+ else
+ scrollsize = rc.bottom-rc.top;
+
+ //restore any resizable buttons to their user-defined sizes,
+ //before shrinking them to fit. This means when we make the window
+ //bigger, the buttons will restore to their initial sizes
+ for(i = 0; i < sbar->nButtons; i++)
+ {
+ sbut = &sbar->sbButtons[i];
+ if(sbut->uButType & SBBM_RESIZABLE)
+ {
+ sbut->nSize = sbut->nSizeReserved;
+ }
+ }
+
+ butsize1 = GetButtonSize(sbar, hwnd, SBBP_LEFT);
+ butsize2 = GetButtonSize(sbar, hwnd, SBBP_RIGHT);
+
+ if(butsize1 + butsize2 > scrollsize - MINSCROLLSIZE)
+ {
+ i = 0;
+ while(i < sbar->nButtons &&
+ butsize1 + butsize2 > scrollsize - MINSCROLLSIZE)
+ {
+ sbut = &sbar->sbButtons[i++];
+ if(sbut->uButType & SBBM_RESIZABLE)
+ {
+ int oldsize = sbut->nSize;
+ sbut->nSize -= (butsize1+butsize2) - (scrollsize-MINSCROLLSIZE);
+
+ if(sbut->nSize < (int)sbut->nMinSize)
+ sbut->nSize = sbut->nMinSize;
+
+ if((UINT)sbut->nSize > (UINT)sbut->nMaxSize)
+ sbut->nSize = sbut->nMaxSize;
+
+
+ butsize1 -= (oldsize - sbut->nSize);
+ }
+ }
+ }
+
+}
+#endif
+#endif
+
+//
+// We must allocate from in the non-client area for our scrollbars
+// Call the default window procedure first, to get the borders (if any)
+// allocated some space, then allocate the space for the scrollbars
+// if they fit
+//
+static LRESULT NCCalcSize(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ NCCALCSIZE_PARAMS *nccsp;
+ RECT *rect;
+ RECT oldrect;
+ SCROLLBAR *sb;
+ LRESULT ret;
+ DWORD dwStyle;
+
+ //Regardless of the value of fCalcValidRects, the first rectangle
+ //in the array specified by the rgrc structure member of the
+ //NCCALCSIZE_PARAMS structure contains the coordinates of the window,
+ //so we can use the exact same code to modify this rectangle, when
+ //wParam is TRUE and when it is FALSE.
+ nccsp = (NCCALCSIZE_PARAMS *)lParam;
+ rect = &nccsp->rgrc[0];
+ oldrect = *rect;
+
+ dwStyle = GetWindowLong(hwnd, GWL_STYLE);
+
+ // TURN OFF SCROLL-STYLES.
+ if ( dwStyle & (WS_VSCROLL|WS_HSCROLL) )
+ {
+ sw->bPreventStyleChange = TRUE;
+ SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL|WS_HSCROLL));
+ }
+
+ //call the default procedure to get the borders allocated
+ ret = CallWindowProc(sw->oldproc, hwnd, WM_NCCALCSIZE, wParam, lParam);
+
+ // RESTORE PREVIOUS STYLES (if present at all)
+ if ( dwStyle & (WS_VSCROLL|WS_HSCROLL) )
+ {
+ SetWindowLong(hwnd, GWL_STYLE, dwStyle);
+ sw->bPreventStyleChange = FALSE;
+ }
+
+ // calculate what the size of each window border is,
+ sw->cxLeftEdge = rect->left - oldrect.left;
+ sw->cxRightEdge = oldrect.right - rect->right;
+ sw->cyTopEdge = rect->top - oldrect.top;
+ sw->cyBottomEdge = oldrect.bottom - rect->bottom;
+
+ sb = &sw->sbarHorz;
+
+ //if there is room, allocate some space for the horizontal scrollbar
+ //NOTE: Change the ">" to a ">=" to make the horz bar totally fill the
+ //window before disappearing
+ if((sb->fScrollFlags & CSBS_VISIBLE) &&
+#ifdef COOLSB_FILLWINDOW
+ rect->bottom - rect->top >= GetScrollMetric(sb, SM_CYHORZSB))
+#else
+ rect->bottom - rect->top > GetScrollMetric(sb, SM_CYHORZSB))
+#endif
+ {
+ rect->bottom -= GetScrollMetric(sb, SM_CYHORZSB);
+ sb->fScrollVisible = TRUE;
+ }
+ else
+ sb->fScrollVisible = FALSE;
+
+ sb = &sw->sbarVert;
+
+ //if there is room, allocate some space for the vertical scrollbar
+ if((sb->fScrollFlags & CSBS_VISIBLE) &&
+ rect->right - rect->left >= GetScrollMetric(sb, SM_CXVERTSB))
+ {
+ if(sw->fLeftScrollbar)
+ rect->left += GetScrollMetric(sb, SM_CXVERTSB);
+ else
+ rect->right -= GetScrollMetric(sb, SM_CXVERTSB);
+
+ sb->fScrollVisible = TRUE;
+ }
+ else
+ sb->fScrollVisible = FALSE;
+
+#ifdef INCLUDE_BUTTONS
+#ifdef RESIZABLE_BUTTONS
+ ResizeButtonsToFit(sw, &sw->sbarHorz, hwnd);
+ ResizeButtonsToFit(sw, &sw->sbarVert, hwnd);
+#endif
+#endif
+
+ //don't return a value unless we actually modify the other rectangles
+ //in the NCCALCSIZE_PARAMS structure. In this case, we return 0
+ //no matter what the value of fCalcValidRects is
+ return ret;//FALSE;
+}
+
+//
+// used for hot-tracking over the scroll buttons
+//
+static LRESULT NCMouseMove(SCROLLWND *sw, HWND hwnd, WPARAM wHitTest, LPARAM lParam)
+{
+ //install a timer for the mouse-over events, if the mouse moves
+ //over one of the scrollbars
+#ifdef HOT_TRACKING
+ hwndCurCoolSB = hwnd;
+ if(wHitTest == HTHSCROLL)
+ {
+ if(uMouseOverScrollbar == SB_HORZ)
+ return CallWindowProc(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam);
+
+ uLastHitTestPortion = HTSCROLL_NONE;
+ uHitTestPortion = HTSCROLL_NONE;
+ GetScrollRect(sw, SB_HORZ, hwnd, &MouseOverRect);
+ uMouseOverScrollbar = SB_HORZ;
+ uMouseOverId = SetTimer(hwnd, COOLSB_TIMERID3, COOLSB_TIMERINTERVAL3, 0);
+
+ NCPaint(sw, hwnd, 1, 0);
+ }
+ else if(wHitTest == HTVSCROLL)
+ {
+ if(uMouseOverScrollbar == SB_VERT)
+ return CallWindowProc(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam);
+
+ uLastHitTestPortion = HTSCROLL_NONE;
+ uHitTestPortion = HTSCROLL_NONE;
+ GetScrollRect(sw, SB_VERT, hwnd, &MouseOverRect);
+ uMouseOverScrollbar = SB_VERT;
+ uMouseOverId = SetTimer(hwnd, COOLSB_TIMERID3, COOLSB_TIMERINTERVAL3, 0);
+
+ NCPaint(sw, hwnd, 1, 0);
+ }
+
+#endif //HOT_TRACKING
+ return CallWindowProc(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam);
+}
+
+//
+// Timer routine to generate scrollbar messages
+//
+static LRESULT CoolSB_Timer(SCROLLWND *swnd, HWND hwnd, WPARAM wTimerId, LPARAM lParam)
+{
+ //let all timer messages go past if we don't have a timer installed ourselves
+ if(uScrollTimerId == 0 && uMouseOverId == 0)
+ {
+ return CallWindowProc(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam);
+ }
+
+#ifdef HOT_TRACKING
+ //mouse-over timer
+ if(wTimerId == COOLSB_TIMERID3)
+ {
+ POINT pt;
+ RECT rect, winrect;
+ HDC hdc;
+ SCROLLBAR *sbar;
+
+ if(swnd->fThumbTracking)
+ return 0;
+
+ //if the mouse moves outside the current scrollbar,
+ //then kill the timer..
+ GetCursorPos(&pt);
+
+ if(!PtInRect(&MouseOverRect, pt))
+ {
+ KillTimer(hwnd, uMouseOverId);
+ uMouseOverId = 0;
+ uMouseOverScrollbar = COOLSB_NONE;
+ uLastHitTestPortion = HTSCROLL_NONE;
+
+ uHitTestPortion = HTSCROLL_NONE;
+ NCPaint(swnd, hwnd, 1, 0);
+ }
+ else
+ {
+ if(uMouseOverScrollbar == SB_HORZ)
+ {
+ sbar = &swnd->sbarHorz;
+ uHitTestPortion = GetHorzPortion(sbar, hwnd, &MouseOverRect, pt.x, pt.y);
+ }
+ else
+ {
+ sbar = &swnd->sbarVert;
+ uHitTestPortion = GetVertPortion(sbar, hwnd, &MouseOverRect, pt.x, pt.y);
+ }
+
+ if(uLastHitTestPortion != uHitTestPortion)
+ {
+ rect = MouseOverRect;
+ GetRealScrollRect(sbar, &rect);
+
+ GetWindowRect(hwnd, &winrect);
+ OffsetRect(&rect, -winrect.left, -winrect.top);
+
+ hdc = GetWindowDC(hwnd);
+ NCDrawScrollbar(sbar, hwnd, hdc, &rect, HTSCROLL_NONE);
+ ReleaseDC(hwnd, hdc);
+ }
+
+ uLastHitTestPortion = uHitTestPortion;
+ }
+
+ return 0;
+ }
+#endif // HOT_TRACKING
+
+ //if the first timer goes off, then we can start a more
+ //regular timer interval to auto-generate scroll messages
+ //this gives a slight pause between first pressing the scroll arrow, and the
+ //actual scroll starting
+ if(wTimerId == COOLSB_TIMERID1)
+ {
+ KillTimer(hwnd, uScrollTimerId);
+ uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID2, COOLSB_TIMERINTERVAL2, 0);
+ return 0;
+ }
+ //send the scrollbar message repeatedly
+ else if(wTimerId == COOLSB_TIMERID2)
+ {
+ //need to process a spoof WM_MOUSEMOVE, so that
+ //we know where the mouse is each time the scroll timer goes off.
+ //This is so we can stop sending scroll messages if the thumb moves
+ //under the mouse.
+ POINT pt;
+ GetCursorPos(&pt);
+ ScreenToClient(hwnd, &pt);
+
+ MouseMove(swnd, hwnd, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
+
+ if(uScrollTimerPortion != HTSCROLL_NONE)
+ SendScrollMessage(hwnd, uScrollTimerMsg, uScrollTimerPortion, 0);
+
+ return 0;
+ }
+ else
+ {
+ return CallWindowProc(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam);
+ }
+}
+
+//
+// We must intercept any calls to SetWindowLong, to check if
+// left-scrollbars are taking effect or not
+//
+static LRESULT CoolSB_StyleChange(SCROLLWND *swnd, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ STYLESTRUCT *ss = (STYLESTRUCT *)lParam;
+
+ if(wParam == GWL_EXSTYLE)
+ {
+ if(ss->styleNew & WS_EX_LEFTSCROLLBAR)
+ swnd->fLeftScrollbar = TRUE;
+ else
+ swnd->fLeftScrollbar = FALSE;
+ }
+
+ return CallWindowProc(swnd->oldproc, hwnd, msg, wParam, lParam);
+}
+
+static UINT curTool = -1;
+static LRESULT CoolSB_Notify(SCROLLWND *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+#ifdef COOLSB_TOOLTIPS
+
+ NMTTDISPINFO *nmdi = (NMTTDISPINFO *)lParam;
+
+ if(nmdi->hdr.hwndFrom == swnd->hwndToolTip &&
+ nmdi->hdr.code == TTN_GETDISPINFO)
+ {
+ //convert the tooltip notify from a "ISHWND" style
+ //request to an id-based request.
+ //We do this because our tooltip is a window-style
+ //tip, with no tools, and the GETDISPINFO request must
+ //indicate which button to retrieve the text for
+ //nmdi->hdr.idFrom = curTool;
+ nmdi->hdr.idFrom = curTool;
+ nmdi->hinst = GetModuleHandle(0);
+ nmdi->uFlags &= ~TTF_IDISHWND;
+ }
+#endif //COOLSB_TOOLTIPS
+
+ return CallWindowProc(swnd->oldproc, hwnd, WM_NOTIFY, wParam, lParam);
+}
+
+static LRESULT SendToolTipMessage0(HWND hwndTT, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ return SendMessage(hwndTT, message, wParam, lParam);
+}
+
+#ifdef COOLSB_TOOLTIPS
+#define SendToolTipMessage SendToolTipMessage0
+#else
+#define SendToolTipMessage 1 ? (void)0 : SendToolTipMessage0
+#endif
+
+
+//
+// We must intercept any calls to SetWindowLong, to make sure that
+// the user does not set the WS_VSCROLL or WS_HSCROLL styles
+//
+static LRESULT CoolSB_SetCursor(SCROLLWND *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+#ifdef INCLUDE_BUTTONS
+ UINT lo = LOWORD(lParam);
+ UINT hi = HIWORD(lParam);
+ UINT xy;
+ RECT rect;
+ SCROLLBAR *sbar;
+ SCROLLBUT *sbut;
+ POINT pt;
+ UINT id;
+ static UINT lastid;
+
+#ifdef HIDE_CURSOR_AFTER_MOUSEUP
+ static UINT lastmsg;
+ if(lastmsg == WM_LBUTTONDOWN)
+ {
+ lastmsg = hi;
+ return CallWindowProc(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam);
+ }
+ else
+ lastmsg = hi;
+#endif
+
+ //if we are over either or our scrollbars
+ if(lo == HTHSCROLL || lo == HTVSCROLL)
+ {
+ xy = GetMessagePos();
+ pt.x = LOWORD(xy);
+ pt.y = HIWORD(xy);
+
+ if(lo == HTHSCROLL)
+ {
+ sbar = &swnd->sbarHorz;
+ GetScrollRect(swnd, SB_HORZ, hwnd, &rect);
+ id = GetHorzPortion(sbar, hwnd, &rect, pt.x, pt.y);
+ }
+ else
+ {
+ sbar = &swnd->sbarVert;
+ GetScrollRect(swnd, SB_VERT, hwnd, &rect);
+ id = GetVertPortion(sbar, hwnd, &rect, pt.x, pt.y);
+ }
+
+ if(id != HTSCROLL_INSERTED)
+ {
+ if(swnd->hwndToolTip != 0)
+ {
+ SendToolTipMessage(swnd->hwndToolTip, TTM_ACTIVATE, FALSE, 0);
+ SendToolTipMessage(swnd->hwndToolTip, TTM_POP, 0, 0);
+ }
+
+ return CallWindowProc(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam);
+ }
+
+ if(swnd->hwndToolTip != 0)
+ {
+ SendToolTipMessage(swnd->hwndToolTip, TTM_ACTIVATE, TRUE, 0);
+ }
+
+ //set the cursor if one has been specified
+ if((id = GetButtonFromPt(sbar, &rect, pt, TRUE)) != -1)
+ {
+ sbut = &sbar->sbButtons[id];
+ curTool = sbut->uCmdId;
+
+ if(lastid != id && swnd->hwndToolTip != 0)
+ {
+ if(IsWindowVisible(swnd->hwndToolTip))
+ SendToolTipMessage(swnd->hwndToolTip, TTM_UPDATE, TRUE, 0);
+ }
+
+ lastid = id;
+
+ if(sbut->hCurs != 0)
+ {
+ SetCursor(sbut->hCurs);
+ return 0;
+ }
+ }
+ else
+ {
+ curTool = -1;
+ lastid = -1;
+ }
+ }
+ else if(swnd->hwndToolTip != 0)
+ {
+ SendToolTipMessage(swnd->hwndToolTip, TTM_ACTIVATE, FALSE, 0);
+ SendToolTipMessage(swnd->hwndToolTip, TTM_POP, 0, 0);
+ }
+
+#endif //INCLUDE_BUTTONS
+ return CallWindowProc(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam);
+}
+
+
+//
+// Send the specified message to the tooltip control
+//
+static void __stdcall RelayMouseEvent(HWND hwnd, HWND hwndToolTip, UINT event)
+{
+#ifdef COOLSB_TOOLTIPS
+ MSG msg;
+
+ CoolSB_ZeroMemory(&msg, sizeof(MSG));
+ msg.hwnd = hwnd;
+ msg.message = event;
+
+ SendMessage(hwndToolTip, TTM_RELAYEVENT, 0, (LONG)&msg);
+#else
+ UNREFERENCED_PARAMETER(hwnd);
+ UNREFERENCED_PARAMETER(hwndToolTip);
+ UNREFERENCED_PARAMETER(event);
+#endif
+}
+
+
+//
+// CoolScrollbar subclass procedure.
+// Handle all messages needed to mimick normal windows scrollbars
+//
+LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC oldproc;
+ SCROLLWND *swnd = GetScrollWndFromHwnd(hwnd);
+ static int count;
+
+ switch(message)
+ {
+ case WM_NCDESTROY:
+ //this should NEVER be called, because the user
+ //should have called Uninitialize() themselves.
+
+ //However, if the user tries to call Uninitialize()..
+ //after this window is destroyed, this window's entry in the lookup
+ //table will not be there, and the call will fail
+ oldproc = swnd->oldproc;
+ UninitializeCoolSB(hwnd);
+
+ //we must call the original window procedure, otherwise it
+ //will never get the WM_NCDESTROY message, and it wouldn't
+ //be able to clean up etc.
+ return CallWindowProc(oldproc, hwnd, message, wParam, lParam);
+
+ case WM_NCCALCSIZE:
+ return NCCalcSize(swnd, hwnd, wParam, lParam);
+
+ case WM_NCPAINT:
+ return NCPaint(swnd, hwnd, wParam, lParam);
+
+ case WM_NCHITTEST:
+ return NCHitTest(swnd, hwnd, wParam, lParam);
+
+ case WM_NCRBUTTONDOWN: case WM_NCRBUTTONUP:
+ case WM_NCMBUTTONDOWN: case WM_NCMBUTTONUP:
+ RelayMouseEvent(hwnd, swnd->hwndToolTip, (WM_MOUSEMOVE-WM_NCMOUSEMOVE) + (message));
+ if(wParam == HTHSCROLL || wParam == HTVSCROLL)
+ return 0;
+ else
+ break;
+
+ case WM_NCLBUTTONDBLCLK:
+ //TRACE("WM_NCLBUTTONDBLCLK %d\n", count++);
+ if(wParam == HTHSCROLL || wParam == HTVSCROLL)
+ return NCLButtonDown(swnd, hwnd, wParam, lParam);
+ else
+ break;
+
+ case WM_NCLBUTTONDOWN:
+ //TRACE("WM_NCLBUTTONDOWN%d\n", count++);
+ RelayMouseEvent(hwnd, swnd->hwndToolTip, WM_LBUTTONDOWN);
+ return NCLButtonDown(swnd, hwnd, wParam, lParam);
+
+
+ case WM_LBUTTONUP:
+ //TRACE("WM_LBUTTONUP %d\n", count++);
+ RelayMouseEvent(hwnd, swnd->hwndToolTip, WM_LBUTTONUP);
+ return LButtonUp(swnd, hwnd, wParam, lParam);
+
+ case WM_NOTIFY:
+ return CoolSB_Notify(swnd, hwnd, wParam, lParam);
+
+ //Mouse moves are received when we set the mouse capture,
+ //even when the mouse moves over the non-client area
+ case WM_MOUSEMOVE:
+ //TRACE("WM_MOUSEMOVE %d\n", count++);
+ return MouseMove(swnd, hwnd, wParam, lParam);
+
+ case WM_TIMER:
+ return CoolSB_Timer(swnd, hwnd, wParam, lParam);
+
+ //case WM_STYLECHANGING:
+ // return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGING, wParam, lParam);
+ case WM_STYLECHANGED:
+
+ if(swnd->bPreventStyleChange)
+ {
+ // the NCPAINT handler has told us to eat this message!
+ return 0;
+ }
+ else
+ {
+ if (message == WM_STYLECHANGED)
+ return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGED, wParam, lParam);
+ else
+ break;
+ }
+
+ case WM_NCMOUSEMOVE:
+ {
+ static LONG_PTR lastpos = -1;
+
+ //TRACE("WM_NCMOUSEMOVE %d\n", count++);
+
+ //The problem with NCMOUSEMOVE is that it is sent continuously
+ //even when the mouse is stationary (under win2000 / win98)
+ //
+ //Tooltips don't like being sent a continous stream of mouse-moves
+ //if the cursor isn't moving, because they will think that the mouse
+ //is moving position, and the internal timer will never expire
+ //
+ if(lastpos != lParam)
+ {
+ RelayMouseEvent(hwnd, swnd->hwndToolTip, WM_MOUSEMOVE);
+ lastpos = lParam;
+ }
+ }
+
+ return NCMouseMove(swnd, hwnd, wParam, lParam);
+
+
+ case WM_SETCURSOR:
+ return CoolSB_SetCursor(swnd, hwnd, wParam, lParam);
+
+ case WM_CAPTURECHANGED:
+ break;
+
+ default:
+ break;
+ }
+
+ return CallWindowProc(swnd->oldproc, hwnd, message, wParam, lParam);
+}
+
diff --git a/plugins/Clist_ng/coolsb/coolscroll.h b/plugins/Clist_ng/coolsb/coolscroll.h new file mode 100644 index 0000000000..c5fe848a83 --- /dev/null +++ b/plugins/Clist_ng/coolsb/coolscroll.h @@ -0,0 +1,232 @@ +#ifndef _COOLSBLIB_INCLUDED
+#define _COOLSBLIB_INCLUDED
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <windows.h>
+#include <win2k.h>
+
+// To complement the exisiting SB_HORZ, SB_VERT, SB_BOTH
+// scrollbar identifiers
+#define COOLSB_NONE (-1)
+#define SB_INSBUT (-2)
+
+//
+// Arrow size defines
+//
+#define SYSTEM_METRIC (-1)
+
+
+//
+// general scrollbar styles
+//
+// use the standard ESB_DISABLE_xxx flags to represent the
+// enabled / disabled states. (defined in winuser.h)
+//
+#define CSBS_THUMBALWAYS 4
+#define CSBS_VISIBLE 8
+
+//cool scrollbar styles for Flat scrollbars
+#define CSBS_NORMAL 0
+#define CSBS_FLAT 1
+#define CSBS_HOTTRACKED 2
+
+//
+// Button mask flags for indicating which members of SCROLLBUT
+// to use during a button insertion / modification
+//
+#define SBBF_TYPE 0x0001
+#define SBBF_ID 0x0002
+#define SBBF_PLACEMENT 0x0004
+#define SBBF_SIZE 0x0008
+#define SBBF_BITMAP 0x0010
+#define SBBF_ENHMETAFILE 0x0020
+//#define SBBF_OWNERDRAW 0x0040 //unused at present
+#define SBBF_CURSOR 0x0080
+#define SBBF_BUTMINMAX 0x0100
+#define SBBF_STATE 0x0200
+
+//button styles (states)
+#define SBBS_NORMAL 0
+#define SBBS_PUSHED 1
+#define SBBS_CHECKED SBBS_PUSHED
+
+//
+// scrollbar button types
+//
+#define SBBT_PUSHBUTTON 1 //standard push button
+#define SBBT_TOGGLEBUTTON 2 //toggle button
+#define SBBT_FIXED 3 //fixed button (non-clickable)
+#define SBBT_FLAT 4 //blank area (flat, with border)
+#define SBBT_BLANK 5 //blank area (flat, no border)
+#define SBBT_DARK 6 //dark blank area (flat)
+#define SBBT_OWNERDRAW 7 //user draws the button via a WM_NOTIFY
+
+#define SBBT_MASK 0x1f //mask off low 5 bits
+
+//button type modifiers
+#define SBBM_RECESSED 0x0020 //recessed when clicked (like Word 97)
+#define SBBM_LEFTARROW 0x0040
+#define SBBM_RIGHTARROW 0x0080
+#define SBBM_UPARROW 0x0100
+#define SBBM_DOWNARROW 0x0200
+#define SBBM_RESIZABLE 0x0400
+#define SBBM_TYPE2 0x0800
+#define SBBM_TYPE3 0x1000
+#define SBBM_TOOLTIPS 0x2000 //currently unused (define COOLSB_TOOLTIPS in userdefs.h)
+
+//button placement flags
+#define SBBP_LEFT 1
+#define SBBP_RIGHT 2
+#define SBBP_TOP 1 //3
+#define SBBP_BOTTOM 2 //4
+
+
+//
+// Button command notification codes
+// for sending with a WM_COMMAND message
+//
+#define CSBN_BASE 0
+#define CSBN_CLICKED (1 + CSBN_BASE)
+#define CSBN_HILIGHT (2 + CSBN_BASE)
+
+//
+// Minimum size in pixels of a scrollbar thumb
+//
+#define MINTHUMBSIZE_NT4 8
+#define MINTHUMBSIZE_2000 6
+
+//define some more hittest values for our cool-scrollbar
+#define HTSCROLL_LEFT (SB_LINELEFT)
+#define HTSCROLL_RIGHT (SB_LINERIGHT)
+#define HTSCROLL_UP (SB_LINEUP)
+#define HTSCROLL_DOWN (SB_LINEDOWN)
+#define HTSCROLL_THUMB (SB_THUMBTRACK)
+#define HTSCROLL_PAGEGUP (SB_PAGEUP)
+#define HTSCROLL_PAGEGDOWN (SB_PAGEDOWN)
+#define HTSCROLL_PAGELEFT (SB_PAGELEFT)
+#define HTSCROLL_PAGERIGHT (SB_PAGERIGHT)
+
+#define HTSCROLL_NONE (-1)
+#define HTSCROLL_NORMAL (-1)
+
+#define HTSCROLL_INSERTED (128)
+#define HTSCROLL_PRE (32 | HTSCROLL_INSERTED)
+#define HTSCROLL_POST (64 | HTSCROLL_INSERTED)
+
+/*
+
+ Public interface to the Cool Scrollbar library
+
+
+*/
+
+BOOL WINAPI InitializeCoolSB(HWND hwnd);
+HRESULT WINAPI UninitializeCoolSB (HWND hwnd);
+
+BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size);
+BOOL WINAPI CoolSB_IsThumbTracking(HWND hwnd);
+BOOL WINAPI CoolSB_IsCoolScrollEnabled(HWND hwnd);
+
+//
+BOOL WINAPI CoolSB_EnableScrollBar (HWND hwnd, int wSBflags, UINT wArrows);
+BOOL WINAPI CoolSB_GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
+int WINAPI CoolSB_GetScrollPos (HWND hwnd, int nBar);
+BOOL WINAPI CoolSB_GetScrollRange (HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos);
+
+//
+int WINAPI CoolSB_SetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
+int WINAPI CoolSB_SetScrollPos (HWND hwnd, int nBar, int nPos, BOOL fRedraw);
+int WINAPI CoolSB_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw);
+BOOL WINAPI CoolSB_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow);
+
+//
+// Scrollbar dimension functions
+//
+BOOL WINAPI CoolSB_SetSize (HWND hwnd, int wBar, int nLength, int nWidth);
+
+//
+// Set the visual nature of a scrollbar (flat, normal etc)
+//
+BOOL WINAPI CoolSB_SetStyle (HWND hwnd, int wBar, UINT nStyle);
+BOOL WINAPI CoolSB_SetThumbAlways (HWND hwnd, int wBar, BOOL fThumbAlways);
+
+//
+// Scrollbar button structure, for inserted buttons only
+//
+typedef struct
+{
+ UINT fMask; //which members are in use
+ UINT uPlacement; //is this button to the left/right (above/below) of the scrollbar??
+ UINT uCmdId; //command identifier (WM_COMMAND value to send)
+ UINT uButType; //
+ UINT uState; //toggled etc
+ int nSize; //size in pixels. -1 for autosize
+
+ HBITMAP hBmp; //handle to a bitmap to use as the button face
+ HENHMETAFILE hEmf; //handle to an enhanced metafile
+
+ HCURSOR hCurs; //handle to a user-supplied mouse cursor to apply
+ //to this button
+
+ int nSizeReserved; //internal variable used for resizing
+ int nMinSize; //min size
+ int nMaxSize; //max size
+
+} SCROLLBUT;
+
+BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb);
+BOOL WINAPI CoolSB_ModifyButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb);
+BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd);
+BOOL WINAPI CoolSB_GetButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb);
+
+void WINAPI CoolSB_SetESBProc(void *proc);
+
+typedef struct
+{
+ NMHDR hdr;
+ DWORD dwDrawStage;
+ HDC hdc;
+ RECT rect;
+ UINT uItem;
+ UINT uState;
+ UINT nBar;
+
+} NMCSBCUSTOMDRAW;
+
+typedef struct
+{
+ NMHDR hdr;
+ RECT rect;
+ POINT pt;
+ UINT uCmdId;
+ UINT uState;
+ int nBar;
+} NMCOOLBUTMSG;
+
+/*
+typedef struct
+{
+ NMHDR hdr;
+ DWORD dwDrawStage;
+ HDC hdc;
+ RECT rect;
+ UINT uCmdId;
+ UINT uState;
+
+} NMCOOLBUTTON_CUSTOMDRAW;
+*/
+
+
+//
+// Define the WM_NOTIFY code value for cool-scrollbar custom drawing
+//
+#define NM_COOLSB_CUSTOMDRAW (0-0xfffU)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/plugins/Clist_ng/coolsb/userdefs.h b/plugins/Clist_ng/coolsb/userdefs.h new file mode 100644 index 0000000000..ea7ea1fe92 --- /dev/null +++ b/plugins/Clist_ng/coolsb/userdefs.h @@ -0,0 +1,79 @@ +#ifndef _USERDEFINES_INCLUDED
+#define _USERDEFINES_INCLUDED
+
+/*
+
+ Define these values to alter the various
+ features of the coolscroll library. If you don't want
+ a certain feature, then you might be able to reduce the
+ size of your app by a few kb...
+
+*/
+
+/* allow inserted buttons. Without this, all button code will
+ be excluded, resulting in a smaller build (about 4kb less). This
+ may not seem much, but it is a 25% reduction! */
+//#define INCLUDE_BUTTONS
+
+/* Allow user-resizable buttons. Makes no difference if INCLUDE_BUTTONS
+ is not defined for the project */
+#define RESIZABLE_BUTTONS
+
+/* Include tooltip support for inserted buttons. Without this, no
+ tooltip requests (TTN_GETDISPINFO's) will be sent to the window */
+//#define COOLSB_TOOLTIPS
+
+/* Define this to include the custom-draw support */
+#define CUSTOM_DRAW
+
+/* Define to enable WM_NOTIFY messages to be sent for mouse event */
+#define NOTIFY_MOUSE
+
+/* Define this value to make the horizontal scrollbar stay visible even
+ if the window is sized to small vertically. Normal scrollbars always leave
+ a 1-pixel line of "client" area before hiding the horizontal scrollbar. This
+ value allows the window to be sized so the client area totally disappears if
+ sized too small */
+//#define COOLSB_FILLWINDOW
+
+/* minimum size of scrollbar before inserted buttons are
+ hidden to make room when the window is sized too small */
+#define MIN_COOLSB_SIZE 24
+
+/* min size of scrollbar when resizing a button, before the
+ resize is stopped because the scrollbar has gotten too small */
+#define MINSCROLLSIZE 50
+
+/* define this to display the default mouse arrow whenever the
+ the mouse is released over a button which has a user-defined cursor.
+ not really very useful, just provides a different type of feedback */
+#undef HIDE_CURSOR_AFTER_MOUSEUP
+
+/* enable HOT_TRACKING to provide visual feedback when the mouse
+ moves over a scrollbar area (like Flat Scrollbars) */
+#define HOT_TRACKING
+
+/* enable FLAT_SCROLLBARS to include support for flat scrollbars
+ note that they must be enabled by the user first of all */
+#define FLAT_SCROLLBARS
+
+/* a normal scrollbar "snaps" its scroll-thumb back into position if
+ you move the mouse too far away from the window, whilst you are
+ dragging the thumb, that is. #undeffing this results in the thumb
+ never snapping back into position, no matter how far away you move
+ the mouse */
+#define SNAP_THUMB_BACK
+
+/* distance (in pixels) the mouse must move away from the thumb
+ during tracking to cause the thumb bar to snap back to its
+ starting place. Has no effect unless SNAP_THUMB_BACK is defined */
+#define THUMBTRACK_SNAPDIST 24
+
+/* maximum number of inserted buttons per bar */
+#define MAX_COOLSB_BUTS 16
+
+/* maximum number of coolsb windows per application.
+ Set to lower if you don't need many. */
+#define MAX_COOLSB 4
+
+#endif /* _USERDEFINES_INCLUDED */
\ No newline at end of file diff --git a/plugins/Clist_ng/docs/CHANGELOG b/plugins/Clist_ng/docs/CHANGELOG new file mode 100644 index 0000000000..dd718ce84f --- /dev/null +++ b/plugins/Clist_ng/docs/CHANGELOG @@ -0,0 +1,1109 @@ +
+ Changelog:
+ ---------
+
+! = bugfix
+* = changed feature
++ = new feature
+- = removed
+
+0.9.0.2 - 2009/07/20
+ * It is now possible to use the real location-based timezones set
+ by UserInfoEx. If present, clist_nicer will use it to calculate
+ a correct date and time.
+
+0.9.0.1 - 2009/07/18
+ * removed separator from view mode menu when not needed
+ * version bump, plugin will only load in Miranda 0.9.dev
+
+0.8.1.2 - 2009/07/03
+ * support relative path for skin filenames.
+ * fixed some redrawing problems for floating frames
+ * fixed issue with disappearing "Appearance" context menu item.
+
+0.8.1.0 - 2009/06/30
+
+ * release for Miranda 0.8.1
+
+0.8.0.x - 2009/05/03
+ * resource.rc rework for vc6 bugfix
+ + statusbar font can be changed
+ * fix for 'Contact list display and ignore options' window
+ ! fix for the valid skin extension
+ * slots numbers unification (part 2)
+
+0.8.0.5 - 2009/04/09
+ * slots numbers unification (m_cluiframes.h is now shared between all plugins)
+ + ToolbarButton support for modernopt.dll
+ ! fix for translation issues in clist_nicer options
+ + x64 portability
+
+0.8.0.4 - 2009/03/05
+
+ * Made project GCC / MingW32 compatible. Added makefile(s) and project
+ files.
+
+ + option added to allow clist being shown on task bar, under the following
+ circumstances:
+
+ a) Window style is set to "title bar" (ordinary Window like any other,
+ not border- or frameless).
+ b) Option "Always hide on task bar" (Options->Contact List-> Window) is
+ DISABLED. This option is enabled by default.
+
+ Does not work with skinned contact list, only when using a default windows
+ theme.
+
+ * corrected some visual glitches in various option dialogs.
+
+0.8.0.2 - 2007/10/20
+
+ * advanced option to save position while moving or resizing (old behaviour)
+ Use DBEditor++ and set CLUI/save_pos_always (BYTE value) to 1. RESTART
+ MIRANDA thereafter (the setting is only read at plugin startup).
+ Deleting the value or set it to 0 to disable it (save position/size only
+ when Miranda exits).
+
+ * new option for floating contacts (Fill with contact list background color).
+ If enabled, floaters will be filled with this color before drawing the skin
+ item. This allows people who don't use a skin at all to show the floaters w/o
+ having them fully transparent.
+
+0.8.0.1 - 2007/10/02
+
+ * removed all hardcoded instances of the MetaContacts protocol name
+
+0.8.0.0 - 2007/10/02
+
+ * released for Miranda 0.7. NOT compatible with 0.6 or earlier.
+
+0.7.2.1 - 2007/09/xx
+
+ * completed floating contacts (patch by yaho, yaho@miranda-easy.net). All the
+ options on Options->Contact List->Floating contacts are now working and a few
+ new features (transparency, snapping) have been added.
+
+ * reworked options. Display profiles is now where you can set most things for
+ the contact layout. Right now, only one profile (<current>) is available, but
+ in the future, there will be the possibility to configure multiple profiles for
+ quickly changing display options.
+
+0.7.1.1 - 2007/01/25
+
+ * more options for per contact display settings.
+
+ * the font colors for selected and hottracked skin items are no longer ignored.
+
+ * removed internal font configuration dialog. Customize->Fonts is now where fonts
+ and colors can be configured for NON-SKINNED MODE ONLY. Otherwise, settings from
+ Customize->Contact List skin->Skin items are used.
+
+0.7.1.0 - 2007/01/20
+
+ * removed old icon code. From now on, clist_nicer requires IcoLib services, either
+ via IcoLib plugin or by using Miranda 0.7.x build.
+
+ * added new option to auto-apply last active view mode when the contact list
+ starts (Options->Contact List)
+
+ * Removed the "Priority Contact" menu item. This can now be found in the new
+ "Contact settings" dialog which is an improved version of the old "Visibility and
+ Ignore" dialog. It allows to set various other options "per contact" (e.g. avatar
+ display override/disable, 2nd line of text display option etc.).
+
+0.7.0.x - see SVN for changes. Mostly bugfixes, no new features.
+
+0.6.0.7 - 2006/03/xx
+
+ * added 2 items to the view mode menu, allowing to:
+ 1) setup view modes
+ 2) clear the current view mode
+
+ * fixed another frame ordering bug.
+
+0.6.0.6 - 2006/02/28
+
+ * fixed possible crash on exit bug.
+
+ * fixed auth requests not appearing on the tray & event area
+
+ * improved performance for "sort by last message" - event timestamps are only
+ retrieved when actually needed.
+
+ * Various CLUIframes tweaks and fixes to get rid of some annoying problems with
+ frame re-ordering after deleting or installing frame-aware plugins.
+
+0.6.0.5 - 2006/01/30
+
+ * groups now have their own alignment option.
+ * Always left
+ * Always right
+ * Automatic (in that case, RTL detection will determine whether the group name will
+ be right or left aligned).
+
+ ! fixed hit-testing for right-aligned groups (you can now click on the expand/collapse
+ icon even if it is aligned to the right).
+
+ * sort by last message works "dynamically" now (when new messages or events arrive,
+ the contact list will update its sorting).
+
+ + started floating contacts implementation. Quite big changes, will take a while until
+ it is usable.
+
+0.6.0.4 - 2006/01/27
+
+ ! The option "If window is partially covered..." should no longer affect the
+ minimize/maximize feature when the visual style in use has a rounded window frame.
+
+ ! more docking tweaks (still possible minor visual glitches)
+
+ * tweaked RTL detection for group names and completely disabled RTL for the non-
+ unicode build.
+
+ ! fixed long standing CLUIframes bug - Position up/down is now working for all top
+ or bottom aligned frames, so re-arranging frames shouldn't be longer a problem.
+
+0.6.0.3 - 2006/01/27
+
+ * fixed possible memory allocation - related crash on startup.
+
+0.6.0.2 - 2006/01/27
+
+ * still bugfixing phase. Some troubles with autosizing were fixed.
+
+ fix: sticky taskbar button when there shouldn't be one (e.g. borderless mode)
+ restored the old way of skinning the clist with the desktop wallpaper (the
+ option "Use these settings to skin the entire background" now works like it did
+ in older builds).
+
+ * added "priority contacts" - you can toggle a priority contact in the contact menu
+ (right click). A priority contact will always be on top of the list or its group
+ and override the normal sorting order. If there are multiple priority contacts
+ per group, then they will be sorted according to the normal contact list sorting,
+ but will still all stay on top of the group.
+
+ * added multilevel sorting. Up to 3 levels of sorting can be selected to sort the clist.
+ There are 4 available sorting criterias, as following:
+
+ * name
+ * protocol
+ * status
+ * last message received
+
+ The feature works similar to the sorting in clist_modern. It respects the setting "Do
+ not separate offline contacts" and will also take priority contacts into account.
+
+ * improved docking. Should now work again, but the clist must have one of the following
+ frame styles:
+
+ * tool window
+ * thin border
+ * no border.
+
+ With the default border/title bar, docking doesn't work (may or may be not fixed in the
+ future, but it doesn't matter much - most people prefer to dock the clist without any
+ title bar at all.
+
+ * status floater fixed. In some cases, it appeared when it shouldn't (auto-hide was
+ "reversed"). Also, the event area on the status floater will now clear events when
+ the clist is hidden.
+
+0.6.0.00 - 2006
+
+ * from now on, clist_nicer+ is based on the new clist interface code which was
+ introduced in 0.4.3.x (nightly build #42). It is no longer compatible with older
+ versions of the miranda core and requires a recent core + database plugin.
+ We call this "post clist revolution", because the changes in the contact list api
+ were HUGE and required a lot of changes to all contact list plugins.
+
+0.5.1.17 - 2005/11/20
+
+ ! fixed a few minimize/maximize issues with various border styles.
+ Minimize now always follow the "miniemize to tray" setting
+
+0.5.1.16 - 2005/11/20
+
+ + added UNICODE_AWARE so that a unicode core will not reject the contact list.
+
+0.5.1.15 - 2005/11/05
+
+ ! toolbar icon bugs (introduced in .14) fixed.
+
+ ! fixed flickering group header items when group skin items are set to be ignored.
+
+ * GDI+ text rendering is disabled since the results were not satisfying. You can
+ still enable it if you want.
+
+ Use dbeditor and create the following setting:
+ CLC/gdiplustext (BYTE value, set it to 1).
+
+ + added per contact skin items. There is no UI for that (and there probably won't
+ come one). It can be done by editing a .ini style file which can be loaded when
+ at startup or during runtime (from the Background+ options page).
+
+ See the included contacts.cln for description how per contact skinning works and
+ how to create your own personal .ini file.
+
+ Note that per contact skinning should be considered an advanced and probably rarely
+ used feature. Future enahancements, like more advanced contact matching, are
+ possible, but I don't think I'll make an UI for it.
+
+ * moved the invisible/visible icons to the right so they are now aligned with the
+ other extra icons. Looks better, also it makes much better text flow possible. If
+ the avatar is high enough to allow more than 2 lines of text, the 2nd row (status
+ message) will wrap and show with multiple lines (if needed). The text flows
+ around the icons so that the available space is used in the best possible way.
+
+ + added ability to right align the entire contact list. This will just mirror the
+ entire display, so right becomes left and vice versa.
+ On the advanced options page you can specify when this should happen.
+
+ + added new toolbarbutton. "Status menu" -> can be used to set and show the current
+ global status.
+
+ + added option to set the border and titlebar type on Options->Contact List->Window.
+ 4 options are possible.
+ * Normal (normal title bar, window frame)
+ * Tool window (toolstyle titlebar, thinner window frame)
+ * Thin border (one pixel, black border)
+ * No border (nothing, no title bar, no window border).
+
+ * BIG skinning changes. See the skinning.howto for more detail on how to use it. Along
+ with this, some options now have different effects. Particularly the "Rounded window"
+ and "Clip border by" options now only work when the clist is set to full transparency.
+ If you only want to remove the border - don't use the clipping anymore, use the new
+ "Border" option to set the title bar and border to "None".
+
+ * several memory leaks fixed, optimized drawing performance.
+
+ + smoother resizing in skinned and transparent mode
+
+ + added a status floater (activate it in the contact lists context menu -> appearance.
+ The floater shows the same status as the global status mode button (most online
+ status mode) and the icon. The floater allows you to access:
+
+ * the status menu (left click the icon)
+ * the main menu (right click the floater anywhere).
+
+ The floater can be skinned by defining its skin item (Background+ page). It can be
+ transparent, have rounded corners and so on. You can drag the floater around with
+ the left mouse button, its size, however, is automatically calculated so that the
+ longest status mode text will "fit" on it.
+ You can also set the floater to auto hide (context menu->Appearance->Auto Hide
+ Floater) in which case it will only be visible when the contact list is minimized
+ or hidden.
+ And finally, the floater can show a copy of the event area.
+
+ + changed RTL behaviour a bit. When rtl alignment is set to "Never", RTL text will
+ be printed left to right, that is, no RTL alignment will be made in any case and the
+ contact list will look like normal (left to right aligned) for all contacts.
+ A new option "RTL TEXT only" has been added to the alignment options which will,
+ when active, only align the text label, but not "mirror" the entire contact.
+
+ RTL text is still autodetected, but the formatting depends on the setting of the
+ "Right align" combo box.
+
+ + added UNICODE_AWARE flag so that the clist will load with new unicode cores
+
+0.5.1.14 - 2005/10/15
+
+ ! fixed misising status messages (rarely happening, but still possible)
+
+ ! some skin items were ignoring margin settings (frame titles, event area).
+
+ You can also specifiy the colors which will be used to draw the 3d border for the
+ "Raised" and "Sunken" border styles.
+
+ ! corrected docking with active border clipping (no more gaps between the clist window
+ and the screen edge).
+
+ * the import/export function now imports and exports more skin-related settings.
+
+ * View Modes: new group entry -> Ungrouped contacts. Check if you want to include
+ ungrouped contacts in the current view mode. Uncheck it, if ungrouped contacts should
+ be filtered out.
+
+ * cvs synced with clist_classic (minor translation fixes)
+
+ ! fixed ugly tray tooltip on 9x systems (when using mTooltip)
+
+ + added toolbar buttons for accessing the view mode functions (select, modify, clear).
+ Remember, you can configure the toolbar by right clicking on any toolbar button and
+ choosing the buttons you want to see from the button submenu.
+
+ + added button skinning. There are 4 new items on the Background+ page. Toolbar buttons
+ pressed/not pressed and UI buttons pressed/not pressed. The first is only used for the
+ toolbar, the latter is used for all other buttons (the menu and status button at the
+ bottom and the buttons in the view mode frame).
+ Note that in order to get UI buttons skinned, you need to activate the "Set all
+ buttons to skinned mode" option on the Background+ page. Also, for best results,
+ enable the "Skin entire background" setting on the Background option page.
+
+ With the two color boxes "3D border bright / dark" on the Background+ button you
+ can configure the colors for 3d highlighting of skin items (when the border style
+ is set to either "Raised" or "Sunken".
+
+ * fixed small alignment bug (right aligned avatars and extra icons)
+
+ * fixed several hittesting bugs for the extra icons when avatars are set to right
+ aligned.
+
+ * fixed bug when creating subgroup (garbage groupnames appearing) (unicode version
+ only).
+
+ + added separate row height value for group items (Options->Contact List->List).
+
+ + improved performance - While connecting the protocols, the clist sorts and
+ redraws less frequently than normal. Also, some minor improvements in the painting
+ handler will skip things which don't need to be drawn more effectively.
+
+ + added "drag on toolbar" - you can now drag the contact list window using any empty
+ space on the toolbar. Effectively, the toolbar behaves like a title bar now.
+
+ * fixed group name display (alignments, unneeded ellipsis appearing, quicksearch with
+ centered group names).
+
+ * put xstatus menu(s) directly as submenus below the the protocol menus. So they are
+ now available from the status bar menus aswell.
+
+ + many improvements added for fist time users. Using clist_nicer+ with a fresh profile
+ now gives much better results. Frames are created properly, button bar is configured
+ to only show the most important buttons and more.
+
+ ! fixed the long standing bug which sometimes made a scrollbar appear on the title
+ bar of the contact list frame.
+
+ + improved and fixed fading - now fades the entire clist frame, including all subframes
+ smoothly, also works together with transparent contact lists of all sorts.
+
+ + added RTL support - UNICODE version ONLY (sorry, won't make it into the non-unicode
+ build).
+
+ This works automatically. When the contact list detects a nickname with hebrew or
+ arabic characters, it displays the nickname RTL formatted. Same happens for status
+ messages. On the "Advanced Options" page, you can set an option named "Reverse entire
+ contact display for RTL" - what it does is basically simple. For RTL contacts, the
+ entire layout of that contact will be flipped horizontally, that is, the icon appears
+ on the right side, the nickname is printed RTL and so on. It just "mirrors" the
+ contact display by using a mirrored device context.
+
+ When editing a RTL nickname, you get a RTL aligned text edit box aswell.
+
+ RTL also works for group names (again, automatically, no need for configuring anything).
+
+ + the GDI+ renderer now produces better text output by using antialising and gamma
+ correction for much smoother text. However, this CAN BE SLOW and if you have a full
+ featured contact list, including avatars, extra icons, you may experience noticeable
+ performance drops when using the GDI+ option. The text output DOES look better, though.
+ You should only use it on fast systems.
+
+ + added new toolbar buttons:
+ ) 3 view mode buttons (select, configure, clear)
+ ) button to open miranda main menu
+
+ To configure visible buttons right click the button bar and select the buttons you wish
+ to see from the submenu.
+
+0.5.1.13 - 2005/10/15
+
+ * view modes which have been set to auto-expire won't expire as long as the mouse
+ pointer is over the contact list
+
+ * added a debuggin message when the "Hidden" value of a contact is set to 1 (causing
+ the contact to be hidden on the clist). This is temporary and only to find out why
+ somtimes contacts are set to hidden.
+
+0.5.1.12 - 2005/10/15
+
+ ! fixed internal font dialog.
+
+ ! fixed deleting last view mode from list creating "strange" view mode name.
+
+ * contacts local time is now only shown when it actually differs from your own time-
+ zone to keep the clist "cleaner" (there is an option for this, so you can still have
+ local time display for all contacts with a valid time zone).
+
+ * fixed: adding/removing subcontacts should now update the clist properly (still, make
+ sure you have the latest MetaContacts plugin installed as clist_nicer+ relies on
+ some of the newer features).
+
+ ! fixed: last protocol did not appear in the skin configuration.
+
+ ! fixed: hide per group wasn't working
+
+ ! don't clip icon on the status button - only status text is clipped (when needed)
+
+ ! fixed: redrawing issues when "Pin to desktop" is active.
+
+ ! more redrawing issues with fading active etc..
+
+ ! fixed a few bugs with the menu bar
+
+ ! fixed file dropping on contact list main window.
+
+ * changed: View mode configuration.
+
+ * Empty protocol or group selection boxes are now ignored.
+ * Stickies can use their own status modes (per contact). To configure stickies,
+ select the global status mode for sticky contacts using the status icons in
+ the "*** All Contacts ***" row. You can then change each status mode for
+ individual contacts. Remember that only checked contacts will be examined
+ by the sticky filter, unchecked contacts will follow the global ruleset.
+
+ * moved ICQ custom status menu from the main menu to the status menu (patch by
+ nullbie - only works with recent ICQJ versions (alpha releases)).
+
+ ! when multiple tray icons are visible and you have hidden one or more protocols
+ (MetaContacts for example), flashing has been corrected (no icon will flash if
+ the protocol causing the event has been hidden in the contact lists protocol order
+ configuration).
+
+ + show xstatus icons on the status bar (optional, can be enabled/disabled on
+ Options->Contact List->Status bar
+
+0.5.1.11 - 2005/10/04 - beta and unicode build only.
+
+ ! status message wasn't properly clipped when visibility icon active.
+
+ * multiple tray icons now follow the protocol configuration (protocols which are
+ invisible in the status bar are now also invisible on the tray).
+
+ * connecting icon(s) are now visible on the status button and in the tray.
+
+ ! the row gap does no longer affect the minimum row height (the latter is enforced,
+ even with a row gap in effect)
+
+ ! improved meta support. clist_nicer+ does no longer use the "Meta Contacts hidden
+ group hack", instead it detects subcontacts in another way. This needs a recent
+ version of the MC protocol (0.9.13.4 MINIMUM) and improves the behaviour with
+ server side contact lists, where the "hidden group hack" could cause strange
+ effects.
+
+ + added mTooltips over statusbar panels showing protocol name + statusmode. Requires
+ a mToolTip plugin with service API (0.0.1.5 or later). Also, the tray tooltip has
+ been replaced with a mTooltip (if mTooltip with service api is present). This removes
+ the limitation of 127 characters for the tray tooltip which might be a problem when
+ lots of protocols are installed.
+
+ * NOTE FOR DEVELOPERS:
+
+ * MS_CLIST_GETCONTACTDISPLAYNAME supports the GCDNF_UNICODE flag in lParam to get
+ the contact name as wide string (compatible with clist_classic).
+
+ * MS_CLIST_SYSTRAY_NOTIFY supports a NIIF_INTERN_UNICODE flag in MIRANDASYSTRAYNOTIFY.dwInfoFlags.
+ If set, the service will treat all strings in the MIRANDASYSTRAYNOTIFY structure
+ as wide strings (you'll probably have to cast the pointers to avoid compiler
+ warnings).
+
+ + added extra font setting for the event area.
+
+ + Importing and exporting themes (.clist files) now also import or export all font settings,
+ background configuration and the contact list window config.
+
+ + custom hittesting now allows to resize the clist window even when it does not have a visible
+ resizing border (e.g. when the border has been removed by TweakUI or the "Clip border"
+ option.
+
+ + option to disable the tray icon tooltips when hovering the contact list tray icon(s)
+ (Options->Contact List)
+
+ + added a first (and simple) versions of the "view modes" extension. A view mode is a
+ contact filter, currently based on protocol, group and status mode and allows for quick
+ filtering in the contact list. A new multiwindow frame has been added with a few buttons
+ to select and configure available view modes.
+
+ + added option to scale the extra icons (Options->Contact List->Window->Extra icon size)
+ At the default value of 16 pixels (which is the default icon size), the icons won't be scaled.
+ You can scale them down to 8 and up to 20 pixels if you want (of course, at a loss of
+ quality - scaling small images like 16x16 icons won't give very beautiful results).
+ NOTE: status icons are not affected by icon scaling, only the "extra" (right aligned)
+ icons are (to save some space on the clist...)
+
+ + ability to show contacts local time on the contact list. The following requirements must
+ be fulfilled:
+
+ * a timezone needs to be present (either set by the protocol (ICQ only) or set as user
+ info using UserInfoEx or tabSRMMs per contact preferences dialog.
+ * contact list must be in dual row mode (either forced or by using avatars large enough
+ to make enough space for 2 lines of text).
+ * the option to show local time needs to be enabled (Options->Contact List->Advanced options,
+ where you set the dual row display options).
+
+ NOTE: local timestamps are refreshed once per minute (which is enough and the time stamp
+ is formatted according to your regional language settings.
+
+ a new font setting (Contact list local time) has been added to the font configuration
+ options.
+
+ + added option: Contact List->Don't separate offline contacts (at the sorting options).
+ When enabled, offline contacts will be sorted together with contacts of other status mode(s).
+ This setting makes only real sense when using sort by protocol or by name.
+ Make sure to disable the "dividers" on the Options->Contact List->List page, or else
+ you'll get dividers when there shouldn't be any.
+
+ ! fixed: the option "If window is partially covered, bring it to front instead of hiding it"
+ now works when window clipping (clip border and rounded window options) are enabled.
+
+0.5.1.10 - 2005/09/29 - beta and unicode build only.
+
+ + new option: center status icons (Advanced option page, at the top).
+ Effect: status icons are vertically and horizontally centered within their
+ space. That works only when avatars are emabled. Use the "Always align icons and
+ text for missing avatars" option to get a consistent space for both avatars and
+ icons. This option also centers avatars horizontally within the available space
+ (that is, if the avatars width is less than its height).
+
+ * restored old behaviour of the "Always align icon and text for missing avatars"
+ option. It now again allows an "empty" avatar space.
+
+ ! fixed bug with subgroup indent
+
+ ! fixed - main menu didn't always update when using menu bar.
+
+ + ability to skin the status bar with a clist_nicer item. Eanble skinning on the status
+ bar option page and set up the skin item on the Background+ page.
+
+ + ability to skin the toolbar background (skin item on the Background+ page). To
+ enable/disable a skinned toolbar, right click any toolbar button and select "skinned
+ toolbar".
+
+ + added "per protocol" skin items. Enable it on the Background+ page and set the skin
+ items for each protocol.
+
+ Protocol skin items have priority over status skin items, however, the text color is, by
+ default taken from the status skin item. So you can have per-protocol background
+ skins mixed with per-status text colors. If you don't want to mix, then check "Override
+ per status text colors, so that items with a valid "per protocol" skin will not use the
+ per status text color.
+
+ For metacontacts: Unless the "Ignore all subcontact states" option is checked,
+ metacontacts will be skinned according to their "real" protocol. Otherwise, you can define
+ a protocol skin for the MetaContacts protocol.
+
+ ! "sort by proto" now uses the protocol order defined under Options->protocols. It also
+ properly sorts metacontacts according to their active subcontact (unless, the "Ignore all
+ subcontact states" option is checked.
+
+ + added the ability to show the "connecting" status for each protocol using a special icon
+ for the status bar panel of that protocol. The icon is visible while the connection is
+ "in progress".
+ If you are using IcoLib, you can configure one connecting icon for each installed protocol,
+ otherwise it is global and cannot be changed (unless, you edit the DLL).
+
+ ! fixed all option pages so that the "Apply" button isn't enabled when the dialog opens.
+
+ + support for the GCDNF_UNICODE flag added to the MS_CLIST_GETCONTACTDISPLAYNAME service.
+ If this flag is set in the lParam, the service returns a widestring contact name.
+ (Unicode build only).
+
+ * the setting to configure the minimum row height has been moved away from the font
+ configuration page and is now on the "List" page, because clist_nicer hides the font
+ configuration page when the font service plugin is available.
+
+0.5.1.9 - 2005/09/22
+
+ * Non-Unicode build should now again work with Miranda 0.4.0.1.
+
+ * status bar doesn't look weird when "Make sections equal width" is unchecked
+
+ * many internal code robustness updates
+
+ + merged one critical unicode / group related bugfix from clist_classic
+
+ * When sorting contacts by protocol, metacontacts are sorted by their current
+ "real" protocol (the protocol which determines the most online contact).
+ Note: Uncheck "Ignore all subcontact states" on the advanced option page to
+ make this work. If the setting is checked, the contact list will ignore all
+ subcontact state values and only use the master contact information.
+ NOTE: this feature is incomplete, it does not react to protocol changes (yet).
+
+ + new, experimental, autosizing optimization. Much less repainting and flickering
+ when a large number of contacts go online/offline (e.g. while conncting a
+ protocol).
+
+ * changed the way selective status icons work a bit. The setting does no longer
+ depend on "Show status icons" being off, and the "Always align..." option being
+ on. Note that selective status icons only work with the avatar alignment set to
+ "Far left".
+
+0.5.1.8 - 2005/09/20
+
+ * Critical bug (hangup when status bar disabled) solved.
+
+0.5.1.7 - 2005/09/20
+
+ ! items in protocol ordering dialog were not dragable (unicode build).
+
+ ! The option "Automatically fill background with wallpaper" was crashing the plugin
+ in the unicode build.
+
+0.5.1.6 - 2005/09/19 - released as UNICODE only build (for testing).
+
+ + added status bar protocol sorting
+
+ + added new option on the Background+ page: Apply group indent to background drawing.
+ When enabled, the indentation values for grouped contacts will also affect the background
+ of the items, not only the contents.
+
+ + BIG unicode changes. All clist_classic changes to allow Unicode contact and group names
+ have been merged. This should, however, be considered experimental alpha code. There
+ are probably bugs and it may crash. BACKUP your db before using the unicode build (that's
+ generally a good idea when testing bleeding edge builds, including the nightly builds
+ of the unicode core).
+
+ + ability to show the ICQ extended status menu on the status menu. Patch by Nullbie - this
+ feature requires a slightly modified ICQJ. Maybe, this code will make it into the
+ official ICQJ version.
+
+ ! fix: Move to Group->Root Group actually made the contact invisible, because it set the
+ Group to an empty string (wrong, the Group entry needs to be deleted in the db).
+
+0.5.1.5 - 2005/09/15
+
+ + added TweakUI - like full transparency. Setting is on the Window page (same place
+ where you can set normal transparency). This setting can be mixed with active/
+ inactive transparency values, which will then control the transparency of the
+ remaining parts of the window (fonts etc..).
+
+ + added: double clicking the avatar opens the user info dialog.
+ Enable it on Options->Contact List->List.
+
+ * somewhat smoother and less "jumpy" resizing (new bugs/small visual glitches possible,
+ especially with autosizing enabled).
+ This includes "fast resizing" for manual resize operations (dragging the window border).
+ Certain "expensive" paint operations are skipped to speed up resizing. A full window
+ repaint is executed at the end of a resizing cycle.
+
+ * fix: minor visual glitch with sunken frame and bottom buttons enabled.
+
+ + added pflagnum_5 support to the status menu builder...
+
+ ! fixed: status bar default setting was ignored for fresh profiles
+
+0.5.1.4 - 2005/09/13
+
+ + added "move to group" contact menu entry
+
+ + client icon update from clist_mw. Should be all there now.
+
+ + "Automatically fill background with wallpaper" now also works with the new setting
+ on the background page (use background for entire window).
+
+ * The "Plus" page has been renamed to "Advanced options". Reason: "Plus" conflicts with
+ a similar page of the popup plugin, and with some language packs the resulting trans-
+ lation can be confusing - for example, in german language pack, plus is translated to
+ "smilies and skins" (for the popup+ plugin) which doesn't really match the purpose
+ of clist_nicer's former "Plus" page. "Advanaced options" is neutral and not confusing
+ at all.
+
+ + added the 2 new font settings for status messages and frame titles to the font service
+ configuration. Consequently, when the font service plugin is installed and detected,
+ clist_nicer+ disables its internal font configuration dialog. Also, the internal font
+ configuration dialog has been moved to the "Customize" section.
+
+ + added the genmenu group menu stuff (group, subgroup etc.)
+
+0.5.1.3 - 2005/09/13
+
+ ! fix for status detection not working in some cases (too much optimizations done)
+
+0.5.1.2 - 2005/09/13
+
+ ! row gap value wasn't loaded at startup.
+
+ ! fixed problem with ICQ xstatus modes & messages
+
+ * strip cr/lf sequences from status messages to avoid unreadable chars.
+
+ * reorganized client icons and id strings
+
+ * fixed dimmed avatar for idle contacts when using GDI+
+
+ + new setting on the "Advanced Options" page.
+ "Don't request avatars for offline contacts". This option will, when enabled, prevent
+ the contact list from requesting avatars using the avatar service when a contact is
+ offline.
+ The option is useful if your contact list is very large and the initial request for
+ all avatars may cause a delay or if you have set your clist to display all contacts
+ (including offline). Avatars will then be requested when a contact comes online. This
+ option might also save quite some memory on large contact lists, because most of the
+ time only a fraction of your contacts will be actually online.
+
+ ! fixed hit-test (double click on extra icons...)
+
+ * changed database paths for menu item configuration. Unfortunately, you may have to
+ redo your menus :/ Reason: collisions when switching clists (mw, modern, nicer) may
+ cause troubles with the menu system. clist_mw and _modern are already using different
+ database paths, so clist_nicer also has to do so.
+
+ + added a skin item for the event area. Also, the button is now gone and the entire
+ event area is now clickable. The button just didn't look well with a skinned event
+ area.
+
+ ! fixed "not on list" font color was ignored.
+
+ + added icon to show activity in irc channels, based on the visiblity setting. You need to
+ have "Show visibility icons" enabled in order to show it.
+ Icon is configureable via IcoLib, as always.
+
+ * the detection for the "most online" protocol now ignores protocols which are not fully IM
+ capable (like RSSNews) and don't support away status mode(s). This prevents the status
+ button from showing always "Online", when a protocol cannot go into away mode (like RSS).
+
+0.5.1.1 - 2005/09/09
+
+ ! fixed a few mw bugs (frame gap, some redraw issues). Additional pointer checks in AddFrame()
+
+ ! fixed possible on exit crash (using deleted critical section)
+
+ + added clist_nicer+ skin item for the frame title bar background.
+
+ * some optimizations to resizing (clui frame mainly).
+
+ + added extra icons (mail, sms, homepage + one reserved). Options
+ are in Contact List->Window. The icons are clickable and open your default browser
+ or email client respectively (double click needed).
+
+ + frame title bar can now be fully skinned. A new font setting has been added to set
+ the font + color for frame titles.
+
+ + new setting: Clip border by (Window page). Will clip the main window border by
+ x pixels on each side which can effectively be used to completely get rid of the
+ contact lists border. This can work in combination with the "rounded window" setting
+ on the same page. Note: may not fully work when autosizing is enabled.
+
+ + new setting: Row gap (List page). Insert x pixels of gap after each contact on the
+ list. The gap is transparent, so the background image (or color) will be visible here.
+ This is somewhat different from the Background+ item configuration where a margin can
+ be set for each side of a contact list item. The row gap is considered when calculating
+ row heights, the individual item margins are not.
+
+ * removed clist_nicers own copy of ICQ xstatus icons. These icons are now obtained by
+ using the extraimages api (like clist_mw does). The ICQ protocol sends these icons
+ on request.
+
+ * the options to show extra and client icons were moved to the "Window" page, where you
+ can also configure the other extra icons (email, homepage, URL etc..).
+ In order to see mBirthday icons, you need to activate the "Reserved" and "Reserved2"
+ entries.
+
+ * the event area is now a frame of its own and can be moved anywhere you want it. Autohide
+ feature does still work.
+
+0.5.0.7 - 2005/08/30 - not officially released, for testing purpose only
+
+ * GDI+ rendering added. Requires gdi+ installed - it is on all XP and most Win2K systems,
+ others can get it here:
+
+ http://www.microsoft.com/downloads/details.aspx?FamilyID=6a63ab9c-df12-4d41-933c-be590feaa05a&DisplayLang=en
+
+ Using GDI+ for rendering the avatars gives better quality, especially for fully alpha-
+ blended PNG images, but even normal bitmaps look better because of the higher quality
+ image rescaling in gdi+.
+
+ + the toolbar button for toggling sounds has now 2 icons showing the actual state of the
+ sounds setting.
+
+ + updated toolbar icons with the latest ttb icon set by Angeli-Ka
+
+ * show xstatus (if set) on the status button (patch submitted by nullbie)
+
+ + more GDI+ rendering - background items are now also rendered with GDI+ using antialiasing,
+ so rounded contact list items should look better now. GDI+ is optional and needs to be
+ enabled on the "Plus" page in the options tree. It cannot be enabled, if it isn't installed
+ though. GDI+ is used with "delayed" linkage, so it shouldn't give you an error if the
+ gdiplus.dll is not installed on your system.
+
+ ! small bug with "far right" aligned avatars corrected (text overdrawing the avatars).
+
+ + added customizable menus (main menu, status menu and contact menu only) - code from clist_mw,
+ slightly changed because some _mw features are not in clist_nicer.
+
+ + added multiwindow API, so all multiwindow plugins should work now, including top toolbar
+ of course.
+
+ * client icons are loaded "on demand" to save gdi resources
+
+0.5.0.6 - 2005/08/27
+
+ + option to disable the expand/collapse icons for groups (Options->Contact List->List)
+ If enabled, you'll have to double click the group label in order to expand/collapse
+ a group.
+
+ + added more client icons - thanks to Angeli-Ka for the icon set.
+
+ + some performance optimizations (about +5k code size)
+
+ * changed the status icon on the bottom status selection button. If you don't have set
+ a preferred system tray icon on Options->contact list, the button will now show your
+ "most online" status, using the global status icon.
+
+ * visual corrections for multiline-status messages. only full rows of text are visible.
+
+ ! fixed and added a few border styles for contact list items (Background+ page)
+
+0.5.0.5 - 2005/08/25
+
+ + added rounded window frame
+
+ + added support for database-cached Yahoo and GG status messages. Also, ICQ
+ extended status messages can be shown on the contact list, since they are
+ also saved to the database.
+
+ - removed the "unknown" avatar feature. Since the avatar service now supports
+ per protocol default images, it's rather pointless to have a fallback
+ image in the clist itself.
+
+ * reduced database reads and writes a lot (caching some configuration data).
+
+ * slightly changed the way the clist determines if a second line of text is
+ needed. There are now 4 modes availble, selectable via a combo
+ box and they are considered in the following order:
+
+ * Never - the 2nd line will never be visible, no matter how much space is
+ available. If an avatar requires a larger row size, the nickname will be
+ centered and the remaining space will be left empty.
+
+ * Always - each contact will have a second row of text.
+
+ * If space allows - The second row will be visible when the row height is already
+ large enough (e.g. due to the avatar using a considerable amount of vertical
+ space).
+
+ * If needed - The second row will be visible if there is useful information to
+ display, that is, the contact has set a status message or extended status mode
+ (for ICQ contacts). The normal protocol status is not considered here.
+
+ + some tweaks to avatar drawing - better clipping with rounded avatars, region based
+ borders.
+
+ + another memory overflow found and fixed in the DrawAlpha() function
+
+0.5.0.4 - 2005/08/25
+
+ + bugfix for startup crash
+
+0.5.0.3 - 2005/08/22
+
+ ! bugfix: when starting hidden/minimized, some buttons did not show up after
+ restoring the clist until it was resized.
+
+ * delete group warning dialog now shows the name of the group which is about to
+ be deleted in the title bar (useful, if the delete group service was called by
+ another plugin, and you therefore cannot know which group is affected).
+
+ * embedded contact lists can now display avatars and use dual row mode.
+
+ ! fixed quicksearch problems with avatars and dual row display.
+
+ ! Background+ page was not translateable (inherited bug from original clist_nicer).
+
+ + added option ("Plus page") to show the status msg instead of the status mode. Note
+ that this only shows cached "CList" status messages and does NOT retrieve them
+ actively. Also, you need to enable "Allow two rows of text" to show them.
+
+ The order of tings shown in the 2nd line is (depending on availability):
+ 1) Clist status message (if enabled on the option page)
+ 2) Custom status mode name (ICQ only)
+ 3) protocol status mode name (online, offline, away and so on...)
+
+ ! fixed incorrect display of some contacts.
+
+ + added "overlay" status icons which can be superimposed over avatars. Customization
+ possible via IcoLib plugin. Enable them on the "Plus" option page.
+ Thanks to Faith Healer for permission to use the icons.
+
+ + added "selective status icon" support. This is a bit tricky. Basically, it fills
+ the empty space for missing avatars with the protocol status icon. Selective status
+ icons require the following:
+
+ * option enabled (plus page)
+ * Status icons switched off (plus page)
+ * Avatars enabled
+ * "Always align icons and text for missing avatars" enabled
+
+ If these settings are in effect, then the empty space showing up if a contact has
+ no avatar is filled with the protocol status icon.
+
+ + added variable row heights. Thanks to pescuma for a really nice and clean
+ implementation of this feature with minimal impact on the contact list core code.
+ As a result, the avatar height is now a separate value and does no longer depend
+ on the row height (set it on the "Plus" page - default are 28 pixels in height).
+
+ + added support for the updater plugin by sje. Future versions of clist_nicer+ may
+ be available by automatic updates ONLY ("major" releases will still be available
+ in the file listing).
+
+0.5.0.2 - 2005/08/06
+
+ * changed API of loadavatars. You need to update both .DLLs not only the
+ clist_nicer_plus.dll. If you don't, it will crash.
+
+ * better quality for "rounded" avatars.
+
+ + option to always align nicknames and/or icons, even if there is NO avatar for
+ a contact (just leave an empty space then).
+
+ * if an extended status mode (ICQ) is set, it will be shown in the second line,
+ instead of the normal protocol status.
+
+ ! center group names now also works with the contact count numbers enabled. Also,
+ draw lines along group names works with centered group names.
+
+ + avatar alignment now supports 3 modes:
+ * far left (avatar at the left edge of the contact list)
+ * far right (avatar at the right edge)
+ * with nickname (avatar just in front of the nickname, but right of the status
+ icon).
+
+ + some fixes to hottracking (works for ignored items). The option "ignore selection
+ for group names" is now working.
+
+0.5.0.1 - 2005/08/05
+
+ * hottrack item config moved to the item list. It can now be configured like any
+ other item, except that it inherits the following stats from the underlying
+ item.
+
+ * corners
+ * gradient TYPE (colors can be set)
+ * margins
+
+ colors and transparency value can be set for the hottracking item, but shape
+ (corners), margins and gradient type cannot, because they need to be inherited
+ from the item which is currently "hottracked".
+
+ ! another bugfix with window layout when autosizing is enabled
+
+ * changed sorting method. It now uses sorting based on current locale
+ settings, which means it peroperly handles language specific characters like
+ german umlauts. That also fixes wrong sortings with cyrillic nicknames.
+
+ + avatars added. Yes, I don't like avatars on the contact list, but since it is
+ requested so often... really, I need someone who can explain me why avatars are
+ SO important in instant messaging... :)
+
+ The options are, as always, in the context
+ menu of the contact list. Avatars can be switched off, they can be ordered to left
+ align (normally, they are just left of the nickname, but after the status icon)
+ and they can have a border.
+
+ Avatars follow the row height, so in order to get a reasonable avatar size, you
+ should increase the row height (a value of 28 or more pixels already gives decent
+ quality). They are also drawn with the alpha value of the background item, so they
+ can be partially transparent.
+
+ Avatars require the plugin LOADAVATARS.DLL, which is a separate plugin and works
+ as some kind of avatar service in the background.
+
+ + dual row mode added. When the row height allows for more than a single line of text
+ (given the current fonts), a second line is added showing the status mode. Also, some
+ icon position are changed in dual row mode and the visibility icon is moved to the
+ 2nd row so it won't take space from the nickname.
+
+ + some options to tweak the layout added. It is now possible to make the status icons
+ optional, for example.
+
+ + status icons are now optional (enable them via the context menu or use the new "Plus"
+ option page.
+
+ + new option page added (Contact List->Plus). Contains all the new settings for tweaking
+ the layout and other stuff.
+
+0.4.0.4 - 2005/07/13
+
+ * better client icon update
+
+ ! evemt area only groups message events
+
+ + timer based clist sorting added. This saves A LOT of sorting, especially while
+ connecting multiple protocols and filling the contact list. It can reduce the
+ number of sorting runs by a factor of 10. The disadvantage are very small delays
+ in the range of 100 - 150 milliseconds. In most cases, you won't notice it.
+
+ The timer based sorting can be disabled by creating a DWORD value in the CLC
+ module. Name it "SortTimer" and set its value to 0.
+ Alternatively, you can set the timer value in milliseconds, using the same db
+ setting. Default is 150 ms and you can set it to any value between 50 and 500.
+ Smaller and larger values will be ignored as they don't make sense.
+
+ NOTE: restart required after changing the db setting.
+
+ + added right margin indent value. Affects text, right-aligned icons only, but not
+ the background (they already have individual margins for each item type).
+ Options->Contact List->List. Basically, it prevents the client or extended status
+ icon(s) to "touch" the right window border (which may look ugly).
+
+ + added "full row selection". Simple, you don't HAVE to click on the contacts text
+ any longer in order to select it. This conflicts with the "easy move" feature,
+ unless you have some free space in your contact list. To disable full row select
+ hold the SHIFT key while using the mouse, so you can still "easy drag" the contact
+ list window around.
+
+ You can enable/disable full row select under Options->Contact List->List
+ Note: full row selection also impacts hottracking of items.
+
+ + added hottracking with changing background color. Two new color fields are on
+ the Background+ page which allow you to set the (background) colors for hottracked
+ items. If a gradient has been set for an item type, hottracking uses both colors
+ to build the new gradient, otherwise, only the first color is active.
+
+ ! fixed a few redrawing/layout problems with the new window elements.
+
+ ! fixed autosize-related focus stealing (ugly)
+
+ + added a new skin item "First group on list" - allows to draw the first group header
+ with a different skin.
+
+0.4.0.3 - 2005/07/13
+
+ ! don't draw additional icons in "embedded" mode (e.g. if the clist control
+ is being used in a dialog box like typing notify options.
+
+ ! only show the toolbar config menu when right clicking over the toolbar.
+
+ ! some visual glitches fixed when autosizing is on.
+
+0.4.0.2 - 2005/07/09
+
+ ! fixed bug with fade in/out contact list
+
+ ! fixed "sorting by name" bug (inherited from clist_classic, rather old bug)
+
+ ! fixed metacontacts not disappearing from group when going offline
+
+ - removed "simple" font configuration dialog.
+
+ + added a context menu to allow configuration of some aspects of the button bar.
+ You can increase/decrease the size of the buttons, can set them as flat or 3d,
+ and you can disable visual styles for the buttons (may look better with some
+ visual styles as they have problems to draw very small buttons).
+ Also, you can now decide which buttons you want to see on the button bar,
+ and which buttons you don't (that may be an opportunity to add some more
+ buttons in the future).
+
+ + added option to the contact list context menu -> use meta protocol icons. If
+ enabled, icons for the meta protocol will be shown for metacontacts (instead of
+ the actual protocol icons).
+
+ ! some visual glitches fixed (especially, when TweakUI is enabled).
+
+ ! another old bug fixed. Groups are now using the colors from the "Background+"
+ page.
+
+ + added the "Event Area". This is a small area at the bottom of the contact list
+ which will show you the most recent contact list event (received message, file
+ and so on...). If more than one event is waiting, a list of unhandled event is
+ opened when you click the button in that area.
+ This feature is, of course, optional. Right click the contact list and you'll find
+ the options in the context menu. You can disable the event area or set it to auto-
+ hide so it will only be visible when needed.
+
+ + feature added: "Move events on top" - contacts with unread or
+ "unhandled" events (simply, all flashing contacts) will stick on top of their group
+ (or the entire contact list, if no groups are in use).
+
+ This is optinonal, and can be configured at the "Contact List" main page (where you
+ set other sorting options.
+
+0.4.0.1 - 2005/07/08 - first public release
diff --git a/plugins/Clist_ng/docs/README b/plugins/Clist_ng/docs/README new file mode 100644 index 0000000000..399028ab4d --- /dev/null +++ b/plugins/Clist_ng/docs/README @@ -0,0 +1,111 @@ +
+ Clist Nicer modified
+ --------------------
+
+This is a modification of the original clist_nicer, written by Pixel based on
+Mirandas classic contact list with added skinning features.
+
+The following things were changed by me:
+----------------------------------------
+
+* ability to show client icons in the contact list. Does only work with the ICQJ or
+ ISee protocols for Miranda.
+
+* ability to show extended status icons and modes.
+
+* ability to show visibility icons in the contact list. A read eye means that you've
+ set this contact on your INVISIBILITY list (ICQ jargon) or the contact has been
+ blocked (MSN or Yahoo). You'll never be visible to this contact. A green eye means
+ that you've put this contact on your VISIBLE list, so you'll always be visible to
+ him/her, no matter what your status is (unless, you're really offline, of course).
+ Note that such "explicitely visible" lists do not exist in all protocols - it's
+ basically an "icq thing".
+
+* Added a toolbar for some commonly used operations. Check the tooltips on the toolbar
+ for more information.
+
+* added 2 buttons at the bottom for a "ICQ style" look. The left one opens the main menu
+ and the right one opens the status menu.
+
+* added some items to the contact list context menu (RIGHT click the contact list while
+ the pointer is NOT hovering a contact or its icon). The menu allows you to quickly
+ enable/disable some of the new features.
+
+* added codepage encoding for nicknames on the contact list. Currently, you can only set
+ "per contact" codepages with tabSRMM. If a codepage is present, it will be used to
+ encode the nickname. The result will be a widestring (unicode).
+
+* ability to show avatars and extended user information, like status
+ messages, on the contact list
+
+* multiwindow and genmenu support.
+
+
+ REQUIREMENTS:
+ ============
+
+* Miranda IM 0.8.1.x or later
+* Windows 2000 or later (ANSI version may work on Windows 98/SE, but this is totally
+ unsupported)..
+
+ INSTALLATION:
+ =============
+
+* Copy the .DLL to your miranda Plugins folder, while Miranda is not running.
+
+ A FEW PERFORMANCE TIP
+ =====================
+
+Clist_nicer+ can be graphic intense so it has the potential to eat quite some CPU
+cycles. This shouldn't be a problem on modern systems as they are generally fast
+enough, no matter what settings you apply. On slower systems, however, a few
+rules may improve performance significantly.
+
+* don't overuse the "overlay" skin items. All the odd/even/first/last/single skin
+ items use overdrawing to get the desired effect. This can easily double or even
+ triple the required calculations for color and transparency mixing, applying
+ shapes (rounded corners) and more. It gets even worse when each item has alpha
+ values less than 100%.
+
+* avoid the setting "Inherit transparency from background items" in the avatar
+ section of the "Advanced options" page. Transparent images need to be rendered
+ using the AlphaBlend() API which is slower than StretchBlt(). Additionally,
+ AlphaBlend()'s image rescaling "quality" is crappy. As a workaround, clist_nicer+
+ uses 2-stage rendering - it uses AlphaBlend() for applying transparency (both constant
+ and per-pixel) on the *unscaled* image and then renders the final image using
+ StretchBlt(). So the setting for transparent avatars can really hurt on slower
+ machines (but the 2-stage rendering does improve quality, of course).
+
+* avoid disabling the "Scroll with text" option for a background image. It can really
+ hurt the scrolling performance with smooth scrolling enabled.
+
+* avoid active view modes when you connect and your contact list is still empty. The
+ view mode filtering requires additional processing time, and when you connect
+ multiple protocols and a few dozen contacts are coming online, this can be notice-
+ able, even on faster machines.
+
+
+ SUPPORT:
+ ========
+
+Direct all your questions at my forum at http://www.miranda.or.at/forums/ This is also
+the support forum for my other plugin (tabSRMM)
+
+License: This program is licensed under the terms of the GNU gneral public license
+ Version 2 or any later version.
+
+ You should find a copy of the license in this archive, if you cannot find it,
+ please visit http://www.gnu.org/licenses/gpl.html
+
+
+Copyrights: This program is based on the work of others. The original clist code is
+ copyrighted by the Miranda IM development team (http://www.miranda-im.org).
+ Most of the skinning modifications were written by Pixel.
+
+ The toolbar icons were made by Angeli-Ka. Thanks for permission to use them :)
+ ICQ client icons also (C) by Angeli-Ka.
+ Overlay status icons made by Faith, permission to use them was granted. Thanks :)
+
+Contact: MSN & email: silvercircle AT gmail DOT com
+ http://miranda.or.at
+
diff --git a/plugins/Clist_ng/docs/README.SOURCE b/plugins/Clist_ng/docs/README.SOURCE new file mode 100644 index 0000000000..a8628eecf5 --- /dev/null +++ b/plugins/Clist_ng/docs/README.SOURCE @@ -0,0 +1,27 @@ +Source code for the clist_nicer plugin is availble via Miranda official SVN
+repository at:
+
+https://svn.sourceforge.net/svnroot/miranda/trunk/miranda/plugins/clist_nicer
+
+You need a SVN client to access this, I recommend TortoiseSVN for Windows which
+is easy to use and provides a good UI.
+
+To compile, you need a complete checkout of Mirandas main source repository and
+Visual C++ 6 with service pack 6 + the latest platform SDK installed. Compiling
+with Visual Studio 2005 is also supported.
+
+Project files are provided for Visual C++ 6 and Visual Studio 2005 (aka Visual
+C++ 8). Compilation with Mingw32/GCC is currently not supported.
+
+This plugin for the Miranda Instant messenger is licensed under the GNU
+General Public License Version 2.
+
+If you distribute binaries based on this source code, please included the
+provided license.txt.
+
+(c) 2006 by Nightwish + the Miranda IM project. Contact at silvercircle@gmail.com
+
+The clist_nicer+ plugin is based on the original clist_nicer plugin written in 2004
+by pixel. This is derived work from the original Miranda contact list plugin
+(by now known as clist_classic) which was written by many contributors to the
+Miranda project since 2000.
diff --git a/plugins/Clist_ng/docs/Skinning.HOWTO b/plugins/Clist_ng/docs/Skinning.HOWTO new file mode 100644 index 0000000000..f089b43477 --- /dev/null +++ b/plugins/Clist_ng/docs/Skinning.HOWTO @@ -0,0 +1,58 @@ +
+Purpose of this document: Describe the skinning system of clist_nicer+,
+provide help for some common problems when using the various skinning options.
+
+First of all: While adding a lot of possibilites to skin the contact list,
+clist_nicer+ skinning is still not as advanced as it is in clist_modern.
+Some effects (like glassy transparency on borders) isn't possible without
+converting the plugin to a "layered" application, which I don't want at
+the moment. The advantage is that clist_nicer+ still supports the "old way"
+of skinning and can, in fact, work without any skinning at all.
+
+It allows a very broad range of look - from pure classic look where everything
+looks to fit the operating systems theme up to a system where various elements
+of the contact list are skinned with partial transparent .PNG images.
+
+Beginning with version 0.5.1.15, quite a few changes were introduced in
+clist_nicer+ skinning system.
+
+1. Rounded window corners and border clipping.
+----------------------------------------------
+
+ This feature was changed. Previously, it was using a window region to cut
+ certain areas from the clist window making it appear "rounded". Now, this
+ feature is implemented by color keying. This means that you need to activate
+ the "full transparent" mode to use rounded window corners or clip away parts
+ of the border. If you don't you will see strange purple window edges (this
+ is, because the color key for transparency is by default set to "magic magenta"
+ (RGB(255, 0, 255)).
+
+2. Window frame/border style
+-----------------------------
+
+ It is no longer necessary to use the "clip border" option to get rid of the
+ window border. In fact, it is not recommended. A new option has been added
+ to Options->Contact List->Window. A combo box allows to choose from 4
+ border styles:
+
+ * Normal (normal title bar, thick window frame)
+ * Tool style window (toolwindow title bar, thinner window frame)
+ * Thin border (no title bar, 1pixel thin black border)
+ * No border (NOTHING).
+
+3. Fully transparent contact lists:
+-----------------------------------
+
+ This is one of clist_nicers special features. It is still available. In order
+ to make the contact list fully transparent, you'll have to:
+
+ * DISABLE the options "Rounded window" and "Clip border by" (set the latter to
+ 0). If you don't do this, you won't get a fully transparent clist.
+ * ENABLE the "Fully transparent (like TweakUI)" option.
+ * On the "Background" page, set a background color to any value you want (the
+ color should match your desktop background color theme for best results).
+ * Also, you should activate the "Use these settings to skin the entire background"
+ option.
+ * Set the window border style to "None".
+
+
\ No newline at end of file diff --git a/plugins/Clist_ng/docs/license.txt b/plugins/Clist_ng/docs/license.txt new file mode 100644 index 0000000000..e58f908ca0 --- /dev/null +++ b/plugins/Clist_ng/docs/license.txt @@ -0,0 +1,351 @@ + NOTE: This copyright does *not* cover dynamically linked plugin libraries
+ that link to Miranda - this is merely considered normal use of the
+ programme, and does *not* fall under the heading of "derived work".
+ Also note that the GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (Miranda IM)
+ is copyrighted by me and others who actually wrote it.
+
+ Richard Hughes
+
+ -------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/plugins/Clist_ng/res/accounts.ico b/plugins/Clist_ng/res/accounts.ico Binary files differnew file mode 100644 index 0000000000..8144c2c275 --- /dev/null +++ b/plugins/Clist_ng/res/accounts.ico diff --git a/plugins/Clist_ng/res/addgoupp.ico b/plugins/Clist_ng/res/addgoupp.ico Binary files differnew file mode 100644 index 0000000000..6859bb2103 --- /dev/null +++ b/plugins/Clist_ng/res/addgoupp.ico diff --git a/plugins/Clist_ng/res/arrow-down.ico b/plugins/Clist_ng/res/arrow-down.ico Binary files differnew file mode 100644 index 0000000000..2dba804e4d --- /dev/null +++ b/plugins/Clist_ng/res/arrow-down.ico diff --git a/plugins/Clist_ng/res/blank.ico b/plugins/Clist_ng/res/blank.ico Binary files differnew file mode 100644 index 0000000000..7845f62fed --- /dev/null +++ b/plugins/Clist_ng/res/blank.ico diff --git a/plugins/Clist_ng/res/connecting.ico b/plugins/Clist_ng/res/connecting.ico Binary files differnew file mode 100644 index 0000000000..dd748681a1 --- /dev/null +++ b/plugins/Clist_ng/res/connecting.ico diff --git a/plugins/Clist_ng/res/delete.ico b/plugins/Clist_ng/res/delete.ico Binary files differnew file mode 100644 index 0000000000..c0e4bda111 --- /dev/null +++ b/plugins/Clist_ng/res/delete.ico diff --git a/plugins/Clist_ng/res/dragcopy.cur b/plugins/Clist_ng/res/dragcopy.cur Binary files differnew file mode 100644 index 0000000000..89c7c960d5 --- /dev/null +++ b/plugins/Clist_ng/res/dragcopy.cur diff --git a/plugins/Clist_ng/res/dropuser.cur b/plugins/Clist_ng/res/dropuser.cur Binary files differnew file mode 100644 index 0000000000..a84b19e28b --- /dev/null +++ b/plugins/Clist_ng/res/dropuser.cur diff --git a/plugins/Clist_ng/res/find.ico b/plugins/Clist_ng/res/find.ico Binary files differnew file mode 100644 index 0000000000..172f4e4603 --- /dev/null +++ b/plugins/Clist_ng/res/find.ico diff --git a/plugins/Clist_ng/res/groups.ico b/plugins/Clist_ng/res/groups.ico Binary files differnew file mode 100644 index 0000000000..be7409983a --- /dev/null +++ b/plugins/Clist_ng/res/groups.ico diff --git a/plugins/Clist_ng/res/hyperlin.cur b/plugins/Clist_ng/res/hyperlin.cur Binary files differnew file mode 100644 index 0000000000..f0f548c828 --- /dev/null +++ b/plugins/Clist_ng/res/hyperlin.cur diff --git a/plugins/Clist_ng/res/invisible.ico b/plugins/Clist_ng/res/invisible.ico Binary files differnew file mode 100644 index 0000000000..7094fd8abb --- /dev/null +++ b/plugins/Clist_ng/res/invisible.ico diff --git a/plugins/Clist_ng/res/menu.ico b/plugins/Clist_ng/res/menu.ico Binary files differnew file mode 100644 index 0000000000..0c9baa1657 --- /dev/null +++ b/plugins/Clist_ng/res/menu.ico diff --git a/plugins/Clist_ng/res/minimize.ico b/plugins/Clist_ng/res/minimize.ico Binary files differnew file mode 100644 index 0000000000..f042e170a6 --- /dev/null +++ b/plugins/Clist_ng/res/minimize.ico diff --git a/plugins/Clist_ng/res/notick.ico b/plugins/Clist_ng/res/notick.ico Binary files differnew file mode 100644 index 0000000000..4ff17dfa7b --- /dev/null +++ b/plugins/Clist_ng/res/notick.ico diff --git a/plugins/Clist_ng/res/notick1.ico b/plugins/Clist_ng/res/notick1.ico Binary files differnew file mode 100644 index 0000000000..d24d6adbbf --- /dev/null +++ b/plugins/Clist_ng/res/notick1.ico diff --git a/plugins/Clist_ng/res/online.ico b/plugins/Clist_ng/res/online.ico Binary files differnew file mode 100644 index 0000000000..29a2d2bc72 --- /dev/null +++ b/plugins/Clist_ng/res/online.ico diff --git a/plugins/Clist_ng/res/options.ico b/plugins/Clist_ng/res/options.ico Binary files differnew file mode 100644 index 0000000000..53ee2073f7 --- /dev/null +++ b/plugins/Clist_ng/res/options.ico diff --git a/plugins/Clist_ng/res/options_clvm.ico b/plugins/Clist_ng/res/options_clvm.ico Binary files differnew file mode 100644 index 0000000000..56d16ccb7a --- /dev/null +++ b/plugins/Clist_ng/res/options_clvm.ico diff --git a/plugins/Clist_ng/res/overlay/NA.ico b/plugins/Clist_ng/res/overlay/NA.ico Binary files differnew file mode 100644 index 0000000000..9290436f5d --- /dev/null +++ b/plugins/Clist_ng/res/overlay/NA.ico diff --git a/plugins/Clist_ng/res/overlay/away.ico b/plugins/Clist_ng/res/overlay/away.ico Binary files differnew file mode 100644 index 0000000000..1c0fac46f7 --- /dev/null +++ b/plugins/Clist_ng/res/overlay/away.ico diff --git a/plugins/Clist_ng/res/overlay/chat.ico b/plugins/Clist_ng/res/overlay/chat.ico Binary files differnew file mode 100644 index 0000000000..0239c56093 --- /dev/null +++ b/plugins/Clist_ng/res/overlay/chat.ico diff --git a/plugins/Clist_ng/res/overlay/dnd.ico b/plugins/Clist_ng/res/overlay/dnd.ico Binary files differnew file mode 100644 index 0000000000..e90c47f85c --- /dev/null +++ b/plugins/Clist_ng/res/overlay/dnd.ico diff --git a/plugins/Clist_ng/res/overlay/invisible.ico b/plugins/Clist_ng/res/overlay/invisible.ico Binary files differnew file mode 100644 index 0000000000..8b7a375e22 --- /dev/null +++ b/plugins/Clist_ng/res/overlay/invisible.ico diff --git a/plugins/Clist_ng/res/overlay/lunch.ico b/plugins/Clist_ng/res/overlay/lunch.ico Binary files differnew file mode 100644 index 0000000000..5567fe052a --- /dev/null +++ b/plugins/Clist_ng/res/overlay/lunch.ico diff --git a/plugins/Clist_ng/res/overlay/occupied.ico b/plugins/Clist_ng/res/overlay/occupied.ico Binary files differnew file mode 100644 index 0000000000..979cdbcaf1 --- /dev/null +++ b/plugins/Clist_ng/res/overlay/occupied.ico diff --git a/plugins/Clist_ng/res/overlay/offline.ico b/plugins/Clist_ng/res/overlay/offline.ico Binary files differnew file mode 100644 index 0000000000..3ca84bae0b --- /dev/null +++ b/plugins/Clist_ng/res/overlay/offline.ico diff --git a/plugins/Clist_ng/res/overlay/online.ico b/plugins/Clist_ng/res/overlay/online.ico Binary files differnew file mode 100644 index 0000000000..2aa071e738 --- /dev/null +++ b/plugins/Clist_ng/res/overlay/online.ico diff --git a/plugins/Clist_ng/res/overlay/phone.ico b/plugins/Clist_ng/res/overlay/phone.ico Binary files differnew file mode 100644 index 0000000000..50ca4e9cfd --- /dev/null +++ b/plugins/Clist_ng/res/overlay/phone.ico diff --git a/plugins/Clist_ng/res/rename.ico b/plugins/Clist_ng/res/rename.ico Binary files differnew file mode 100644 index 0000000000..fa8abc8785 --- /dev/null +++ b/plugins/Clist_ng/res/rename.ico diff --git a/plugins/Clist_ng/res/slist.ico b/plugins/Clist_ng/res/slist.ico Binary files differnew file mode 100644 index 0000000000..f677d5a7ca --- /dev/null +++ b/plugins/Clist_ng/res/slist.ico diff --git a/plugins/Clist_ng/res/sounds_off.ico b/plugins/Clist_ng/res/sounds_off.ico Binary files differnew file mode 100644 index 0000000000..08d85a296d --- /dev/null +++ b/plugins/Clist_ng/res/sounds_off.ico diff --git a/plugins/Clist_ng/res/sounds_on.ico b/plugins/Clist_ng/res/sounds_on.ico Binary files differnew file mode 100644 index 0000000000..6eddbdc901 --- /dev/null +++ b/plugins/Clist_ng/res/sounds_on.ico diff --git a/plugins/Clist_ng/res/tabsrmm_menu.ico b/plugins/Clist_ng/res/tabsrmm_menu.ico Binary files differnew file mode 100644 index 0000000000..93a9d324f6 --- /dev/null +++ b/plugins/Clist_ng/res/tabsrmm_menu.ico diff --git a/plugins/Clist_ng/res/visible.ico b/plugins/Clist_ng/res/visible.ico Binary files differnew file mode 100644 index 0000000000..9ea2aefcf6 --- /dev/null +++ b/plugins/Clist_ng/res/visible.ico diff --git a/plugins/Clist_ng/resource.rc b/plugins/Clist_ng/resource.rc new file mode 100644 index 0000000000..8d14ad7fb4 --- /dev/null +++ b/plugins/Clist_ng/resource.rc @@ -0,0 +1,856 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "include\resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include <winres.h>
+#include <statusmodes.h>
+#include <version.rc>
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_WARNING DIALOGEX 0, 0, 298, 105
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "",IDC_STATIC,0,0,298,76
+ CONTROL "Do not show this message again",IDC_DONTSHOWAGAIN,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,77,277,11
+ CONTROL "",IDC_WARNTEXT,"RichEdit20W",WS_VSCROLL | 0x1944,36,23,250,51
+ ICON "",IDC_WARNICON,6,8,24,24,SS_CENTERIMAGE
+ LTEXT "Static",IDC_CAPTION,36,5,252,16
+ DEFPUSHBUTTON "OK",IDOK,245,88,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,241,88,50,14
+ PUSHBUTTON "Yes",IDYES,136,88,50,14
+ PUSHBUTTON "No",IDNO,189,88,50,14
+ CONTROL "",IDC_WARNGROUP,"Static",SS_ENHMETAFILE,0,74,297,2
+END
+
+IDD_SKINITEMEDIT DIALOGEX 0, 0, 303, 197
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Skin items",IDC_STATIC,2,0,119,205
+ LISTBOX IDC_ITEMS,7,10,109,178,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "General",IDC_STATIC,125,0,174,61
+ CONTROL "Gradient",IDC_GRADIENT,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_GROUP | WS_TABSTOP,129,9,85,10
+ CONTROL "Left to right",IDC_GRADIENT_LR,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,139,19,75,10
+ CONTROL "Right to left",IDC_GRADIENT_RL,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,139,29,75,10
+ CONTROL "Top to bottom",IDC_GRADIENT_TB,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,139,39,75,10
+ CONTROL "Bottom to top",IDC_GRADIENT_BT,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,139,49,75,10
+ CONTROL "Round corners",IDC_CORNER,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_GROUP | WS_TABSTOP,218,9,75,10
+ CONTROL "Top-Left",IDC_CORNER_TL,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,228,19,65,10
+ CONTROL "Top-Right",IDC_CORNER_TR,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,228,29,65,10
+ CONTROL "Bottom-Right",IDC_CORNER_BR,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,228,39,65,10
+ CONTROL "Bottom-Left",IDC_CORNER_BL,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,228,49,65,10
+ GROUPBOX "Item colors",IDC_STATIC,126,62,174,53
+ LTEXT "First color",IDC_COLORLABLE,130,73,53,8,WS_DISABLED
+ CONTROL "",IDC_BASECOLOUR,"ColourPicker",WS_DISABLED | WS_TABSTOP,186,72,22,10
+ LTEXT "Alpha %",IDC_ALPHALABLE,213,74,44,8,WS_DISABLED
+ EDITTEXT IDC_ALPHA,260,71,33,13,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_ALPHASPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_DISABLED,287,72,11,14
+ LTEXT "Second color",IDC_COLOR2LABLE,130,88,53,8,WS_DISABLED
+ CONTROL "",IDC_BASECOLOUR2,"ColourPicker",WS_DISABLED | WS_TABSTOP,186,87,22,10
+ EDITTEXT IDC_ALPHA2,260,85,33,13,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_ALPHASPIN2,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_DISABLED,291,83,11,14
+ LTEXT "Textcolor",IDC_TEXTCOLOURLABLE,130,102,48,8,WS_DISABLED
+ CONTROL "",IDC_TEXTCOLOUR,"ColourPicker",WS_DISABLED | WS_TABSTOP,186,102,22,10
+ GROUPBOX "Item margins",IDC_STATIC,125,117,174,44
+ EDITTEXT IDC_MRGN_LEFT,144,135,26,14,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_MRGN_LEFT_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_DISABLED,171,131,10,14
+ EDITTEXT IDC_MRGN_TOP,198,125,26,14,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_MRGN_TOP_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_DISABLED,229,119,10,14
+ EDITTEXT IDC_MRGN_RIGHT,254,135,26,14,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_MRGN_RIGHT_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_DISABLED,279,131,10,14
+ EDITTEXT IDC_MRGN_BOTTOM,198,143,26,14,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_MRGN_BOTTOM_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_DISABLED,214,139,10,14
+ CONTROL "Item ignored",IDC_IGNORE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,9,191,103,10
+ LTEXT "Alpha %",IDC_ALPHALABLE2,214,87,44,8,WS_DISABLED
+ CONTROL "Skip gradient drawing and render image item",IDC_SKIP_UNDERLAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,127,163,171,12
+ CONTROL "Skip image item rendering",IDC_SKIP_IMAGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,127,176,171,12
+END
+
+IDD_IMAGEITEMEDIT DIALOGEX 0, 0, 303, 197
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CAPTION
+CAPTION "Dialog"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CTEXT "Not yet supported",IDC_STATIC,69,76,158,17
+END
+
+IDD_EXCEPTION DIALOGEX 0, 0, 370, 131
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "TabSRMM exception"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ EDITTEXT IDC_EXCEPTION_DETAILS,7,18,356,60,ES_MULTILINE | ES_READONLY
+ DEFPUSHBUTTON "Copy to clipboard",IDC_COPY_EXCEPTION,108,114,80,14
+ PUSHBUTTON "Continue",IDOK,196,114,80,14
+ PUSHBUTTON "Exit Miranda",IDCANCEL,284,114,80,14
+ LTEXT "",IDC_EX_REASON,7,5,354,9
+ LTEXT "Although the exception was caught and you may continue working with Miranda, you should restart the program as soon as possible. The exception may have damaged internal data structures and can have a serious impact on stability.",IDC_STATIC,7,83,352,26
+END
+
+IDD_OPT_FLOATING DIALOGEX 0, 0, 313, 251
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Floating contacts appearance",IDC_STATIC,3,4,307,131
+ CONTROL "Simple layout",IDC_FLT_SIMPLELAYOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,29,176,11
+ CONTROL "Show avatars",IDC_FLT_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,41,176,11
+ CONTROL "Show second text line",IDC_FLT_DUALROWS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,53,176,11
+ CONTROL "Show extra icons",IDC_FLT_EXTRAICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,65,176,11
+ GROUPBOX "Behaviour",IDC_STATIC,3,192,307,52
+ CONTROL "Synchronzie floater visibility with contact list",IDC_FLT_SYNCED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,202,292,11
+ CONTROL "Only show contact floaters when contact list is hidden or minimized",IDC_FLT_AUTOHIDE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,214,292,11
+ EDITTEXT IDC_FLT_PADLEFT,211,93,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_FLT_PADLEFTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,205,90,11,14
+ EDITTEXT IDC_FLT_PADRIGHT,274,93,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_FLT_PADRIGHTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,293,89,11,14
+ EDITTEXT IDC_FLT_PADTOP,243,87,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_FLT_PADTOPSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,262,82,11,14
+ EDITTEXT IDC_FLT_PADBOTTOM,243,98,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER
+ CONTROL "",IDC_FLT_PADBOTTOMSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK | WS_DISABLED,262,100,11,14
+ CTEXT "Padding",IDC_STATIC,217,74,80,10
+ CONTROL "Enable floating contacts (required restart)",IDC_FLT_ENABLED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,17,176,11
+ CONTROL "",IDC_FLT_OPACITY,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,231,43,45,12
+ RTEXT "000%",IDC_FLT_OPACITYVALUE,277,44,20,8
+ GROUPBOX "Opacity",IDC_STATIC,192,14,113,47
+ EDITTEXT IDC_FLT_WIDTH,211,115,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_FLT_WIDTHSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,239,114,11,14
+ CONTROL "Snap to edges (hold CTRL for snap between floaters)",IDC_FLT_SNAP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,226,292,11
+ RTEXT "Inactive",IDC_STATIC,193,44,36,8
+ CONTROL "",IDC_FLT_ACTIVEOPACITY,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,231,26,45,12
+ RTEXT "000%",IDC_FLT_ACTIVEOPACITYVALUE,277,28,20,8
+ RTEXT "Active",IDC_STATIC,193,28,36,8
+ CONTROL "Border",IDC_FLT_BORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,105,71,10
+ CONTROL "",IDC_FLT_BORDERCOLOUR,"ColourPicker",WS_TABSTOP,129,105,22,10
+ RTEXT "Colour",IDC_STATIC,90,106,34,8
+ CONTROL "Fill with contact list background color",IDC_FLT_FILLSTD,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,77,176,11
+ GROUPBOX "Tooltips",IDC_STATIC,3,138,307,40
+ CONTROL "Show tooltips",IDC_FLT_SHOWTOOLTIPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,150,90,10
+ RTEXT "Hover time",IDC_STATIC,115,151,90,8
+ EDITTEXT IDC_FLT_HOVERTIME,211,148,37,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_FLT_HOVERTIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,237,144,10,14
+ CONTROL "Use default",IDC_FLT_DEFHOVERTIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,211,164,96,10
+ LTEXT "ms",IDC_STATIC,254,151,42,8
+ LTEXT "Floater width",IDC_STATIC,13,118,193,11
+ CONTROL "Keep floating contacts on top",IDC_FLT_ONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,89,176,11
+END
+
+IDD_CLNABOUT DIALOGEX 0, 0, 228, 140
+STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "About CList Nicer+"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "",IDC_WHITERECT,0,0,228,116
+ DEFPUSHBUTTON "OK",IDOK,168,123,55,14
+ LTEXT "Clist Nicer+",IDC_CLNICER,5,7,150,15
+ CTEXT "Copyright © 2004-2009 by the Miranda IM project. More detailed copyright information can be found in the included README file.\n\nThis software is distributed and licensed under the terms of the GNU General Public License V2 or any later version.",IDC_COPYRIGHT,5,39,217,47
+ ICON 0,IDC_LOGO,201,2,20,20
+ LTEXT "Version",IDC_VERSION,5,19,150,15
+ CTEXT "build time",IDC_BUILDTIME,37,105,150,11
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,117,228,1
+ CONTROL "Support and latest version information",IDC_SUPPORT,
+ "Hyperlink",WS_TABSTOP | 0x1,18,91,192,12
+END
+
+IDD_DELETECONTACT DIALOGEX 0, 0, 284, 90
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Delete Contact"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "No",IDNO,162,38,65,14
+ PUSHBUTTON "Yes",IDYES,54,38,65,14
+ CONTROL "Hide from list only, in order to keep their history and ignore/visibility settings",IDC_HIDE,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,65,270,9
+ LTEXT "Use Options->Ignore (expert mode) to unhide contacts.",IDC_STATIC,20,78,257,8
+ CONTROL "Are you sure you want to delete %s?",IDC_TOPLINE,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,7,7,270,8
+ LTEXT "This will erase all history and settings for this contact!",IDC_STATIC,7,18,239,14
+END
+
+IDD_OPT_DSPPROFILES DIALOGEX 0, 0, 312, 247
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_OPTIONSTAB,"SysTabControl32",WS_TABSTOP,1,1,310,245
+END
+
+IDD_OPTIONSDIALOG DIALOGEX 0, 0, 312, 247
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_OPTIONSTAB,"SysTabControl32",WS_TABSTOP,1,1,310,245,WS_EX_ACCEPTFILES
+END
+
+IDD_OPT_CLIST DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Contact List",IDC_STCLISTGROUP,1,0,163,91
+ CONTROL "Hide offline users",IDC_HIDEOFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,12,147,10
+ CONTROL "Hide empty groups",IDC_HIDEEMPTYGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,25,147,10
+ CONTROL "Disable groups",IDC_DISABLEGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,38,147,10
+ CONTROL "Ask before deleting contacts",IDC_CONFIRMDELETE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,51,147,10
+ CONTROL "Disable icon blinking",IDC_ICONBLINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,64,147,10
+ CONTROL "Apply last active view mode ",IDC_APPLYLASTVIEWMODE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,77,147,10
+ GROUPBOX "Contact list layout",IDC_STATIC,169,0,133,91
+ CONTROL "Show menu and status buttons",IDC_SHOWBOTTOMBUTTONS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,176,25,121,10
+ CONTROL "Draw sunken edge",IDC_CLISTSUNKEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,176,38,121,10
+ GROUPBOX "System tray icon",IDC_STATIC,1,91,163,63
+ CONTROL "Single click interface",IDC_ONECLK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,101,147,10
+ CONTROL "Always show status in tooltip",IDC_ALWAYSSTATUS,"Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,10,113,147,10
+ CONTROL "Disable icon blinking",IDC_DISABLEBLINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,125,147,10
+ EDITTEXT IDC_BLINKTIME,69,136,57,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin5",IDC_BLINKSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,114,137,11,16
+ LTEXT "ms",IDC_STATIC,130,138,24,8
+ GROUPBOX "Event area",IDC_STATIC,169,91,133,63
+ LTEXT "Set base visiblity on the frames menu",IDC_STATIC,176,102,121,15
+ CONTROL "Auto mode",IDC_EVENTAREAAUTOHIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,176,125,121,10
+ GROUPBOX "System tray icon when using multiple protocols",IDC_STATIC,1,154,302,71
+ CONTROL "Show",IDC_DONTCYCLE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,10,166,92,10
+ COMBOBOX IDC_PRIMARYSTATUS,107,165,78,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "icon when statuses differ",IDC_STATIC,189,167,108,8,NOT WS_GROUP
+ CONTROL "Cycle icons every",IDC_CYCLE,"Button",BS_AUTORADIOBUTTON,10,180,92,10
+ EDITTEXT IDC_CYCLETIME,107,180,30,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_CYCLETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,127,181,10,14
+ LTEXT "seconds, when statuses differ",IDC_STATIC,145,182,150,8,NOT WS_GROUP
+ CONTROL "Show multiple icons",IDC_MULTITRAY,"Button",BS_AUTORADIOBUTTON,10,194,92,10
+ CONTROL "Only when statuses differ",IDC_ALWAYSMULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,194,186,10
+ CONTROL "Do not show system tray icon tooltips on mouse over",IDC_NOTRAYINFOTIPS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,208,284,12
+END
+
+IDD_OPT_DSPCLASSES DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ COMBOBOX IDC_DSPCLASS,12,18,279,13,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Show avatar",IDC_DSPCLASS_AVATAR,"Button",BS_AUTO3STATE | WS_TABSTOP,15,55,272,9
+ CONTROL "Show second text line",IDC_DSPCLASS_SECONDLINE,"Button",BS_AUTO3STATE | WS_TABSTOP,15,68,272,9
+ CONTROL "Show contact icon",IDC_DSPCLASS_ICON,"Button",BS_AUTO3STATE | WS_TABSTOP,15,81,272,9
+ GROUPBOX "Display class",IDC_STATIC,1,3,300,41
+ GROUPBOX "General display options",IDC_STATIC,1,44,300,56
+ GROUPBOX "General display options",IDC_STATIC,1,186,300,39
+ CONTROL "Enable row display change for selected contacts",IDC_DSPCLASS_ENABLE_SELECTED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,197,272,9
+ CONTROL "Enable row display change for hovered contacts",IDC_DSPCLASS_ENABLE_HOVERED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,210,272,9
+END
+
+IDD_OPT_DSPGROUPS DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Groups",IDC_STATIC,1,0,301,109
+ CONTROL "Draw a line alongside group names",IDC_LINEWITHGROUPS,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,8,284,12
+ CONTROL "Show number of contacts in a group",IDC_SHOWGROUPCOUNTS,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,20,285,12
+ CONTROL "Hide numbers when all offline",IDC_HIDECOUNTSWHENEMPTY,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,23,32,273,12
+ CONTROL "Sort groups alphabetically",IDC_SORTGROUPSALPHA,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,44,285,12
+ CONTROL "Quicksearch in open groups only",IDC_QUICKSEARCHVISONLY,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,56,284,12
+ CONTROL "No expand/collapse icon",IDC_NOGROUPICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,68,288,12
+ CONTROL "Center groupnames horizontally",IDC_CENTERGROUPNAMES,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,80,286,12
+ LTEXT "Name alignment",IDC_STATIC,11,95,173,10
+ COMBOBOX IDC_GROUPALIGN,202,93,96,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Margins (left/right)",IDC_STATIC,11,121,113,8
+ EDITTEXT IDC_LEFTMARGIN,213,119,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_LEFTMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,225,119,11,14
+ EDITTEXT IDC_RIGHTMARGIN,250,119,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_RIGHTMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,282,119,11,14
+ LTEXT "Gap between contact rows",IDC_STATIC,11,135,193,11
+ EDITTEXT IDC_ROWGAP,250,133,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_ROWGAPSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,282,133,11,14
+ LTEXT "Minimum height of a contact row",IDC_STATIC,11,149,230,8
+ EDITTEXT IDC_ROWHEIGHT,250,147,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_ROWHEIGHTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,282,147,11,14
+ LTEXT "Minimum height of a group row",IDC_STATIC,11,161,229,8
+ EDITTEXT IDC_GROUPROWHEIGHT,250,161,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_GROUPROWHEIGHTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,282,161,11,14
+ LTEXT "Indent groups by this many pixels relative to their parent",IDC_STATIC,11,175,232,8
+ EDITTEXT IDC_GROUPINDENT,250,175,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_GROUPINDENTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,282,175,11,14
+ LTEXT "Inner vertical padding for contact rows",IDC_STATIC,11,189,230,9
+ EDITTEXT IDC_AVATARPADDING,250,189,31,12,ES_RIGHT | ES_AUTOHSCROLL
+ CONTROL "",IDC_AVATARPADDINGSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,282,189,11,14
+ GROUPBOX "Margins and spacing (all values in pixels)",IDC_STATIC,1,111,301,93
+END
+
+IDD_OPT_DSPITEMS DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Contact List Sorting",IDC_STATIC,1,0,298,109,WS_GROUP
+ LTEXT "First by",IDC_STATIC,5,11,169,9
+ COMBOBOX IDC_SORTPRIMARY,186,8,103,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Then by",IDC_STATIC,5,25,173,9
+ COMBOBOX IDC_SORTTHEN,186,23,103,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Finally by",IDC_STATIC,5,39,172,9
+ COMBOBOX IDC_SORTFINALLY,186,38,103,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Temporarily move flashing contacts to the top of their group",IDC_EVENTSONTOP,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,5,57,286,16
+ CONTROL "Do not separate offline contacts within a group",IDC_DONTSEPARATE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,76,285,10
+ LTEXT "Hide as offline",IDC_STATIC,6,111,73,8
+ CONTROL "Tree1",IDC_HIDEOFFLINEOPTS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,3,123,108,101
+ LTEXT "Right align contacts",IDC_STATIC,5,92,171,10
+ COMBOBOX IDC_CLISTALIGN,186,89,103,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_OPT_DSPADVANCED DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Avatars",IDC_STATIC,1,0,302,109
+ CONTROL "Show avatars",IDC_CLISTAVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,11,189,10
+ LTEXT "Height",IDC_STATIC,206,11,46,11
+ EDITTEXT IDC_AVATARHEIGHT,256,9,31,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_AVATARSIZESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,285,9,11,15
+ CONTROL "Draw a border around avatars",IDC_AVATARSBORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,25,233,10
+ CONTROL "",IDC_AVATARBORDERCLR,"ColourPicker",WS_TABSTOP,256,25,31,10
+ CONTROL "Always align icons and text for missing avatars",IDC_ALWAYSALIGNNICK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,60,289,10
+ LTEXT "Avatar alignment",IDC_STATIC,8,80,176,11
+ COMBOBOX IDC_ALIGNMENT,194,78,102,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Don't request avatars for offline contacts",IDC_NOAVATARSOFFLINE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,94,290,10
+ GROUPBOX "Second text line",IDC_STATIC,1,110,302,110
+ CONTROL "Display status message when available",IDC_SHOWSTATUSMSG,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,122,288,10
+ LTEXT "Show second text line:",IDC_STATIC,8,137,103,9
+ COMBOBOX IDC_DUALROWMODE,194,135,102,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Show contacts local time",IDC_SHOWLOCALTIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,150,286,10
+ CONTROL "Only when timezone differs",IDC_SHOWLOCALTIMEONLYWHENDIFFERENT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,164,276,10
+END
+
+IDD_OPT_XICONS DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Extra icons (drag items to reorder them)",IDC_STATIC,1,111,302,96
+ EDITTEXT IDC_EXICONSCALE,195,212,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_EXICONSCALESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,186,210,11,14
+ LTEXT "Extra icon size",IDC_STATIC,64,214,116,11
+ CONTROL "Show status icons",IDC_SHOWSTATUSICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,10,106,10
+ GROUPBOX "Icons",IDC_STATIC,5,0,298,108
+ CONTROL "Show visibility icons",IDC_SHOWVISIBILITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,35,288,10
+ CONTROL "When possible, draw status icons in avatar space",IDC_SELECTIVEICONS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,47,288,10
+ CONTROL "Centered when possible",IDC_STATUSICONSCENTERED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,20,278,11
+ CONTROL "Use Overlay icons on avatars",IDC_OVERLAYICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,71,289,10
+ CONTROL "Dim idle contacts",IDC_IDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,83,289,10
+ CONTROL "",IDC_EXTRAORDER,"SysTreeView32",TVS_NOTOOLTIPS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,22,122,261,64
+ PUSHBUTTON "Reset order and visibility to default",IDC_RESETXICONS,15,188,271,15
+END
+
+IDD_OPT_CLUI DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Window",IDC_STWINDOWGROUP,1,0,302,142
+ CONTROL "Always on top",IDC_ONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,11,126,10
+ CONTROL "Easy move",IDC_CLIENTDRAG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,35,126,10
+ CONTROL "Pin to desktop",IDC_ONDESKTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,48,128,10
+ CONTROL "Hide contact list after it has been idle for",IDC_AUTOHIDE,
+ "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,6,106,202,11
+ EDITTEXT IDC_HIDETIME,213,104,38,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_HIDETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,237,102,11,14
+ LTEXT "seconds",IDC_STATIC01,257,105,42,8
+ CONTROL "Automatically resize window to a maximum of ",IDC_AUTOSIZE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,62,192,10
+ EDITTEXT IDC_MAXSIZEHEIGHT,201,61,29,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_MAXSIZESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,209,64,10,14
+ LTEXT "% of screen height",IDC_STATIC22,233,62,64,8
+ CONTROL "Size upwards",IDC_AUTOSIZEUPWARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,75,271,10
+ CONTROL "If window is partially covered, bring to front instead of hiding",IDC_BRINGTOFRONT,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,6,88,284,16
+ LTEXT "Gap between frames",IDC_STATIC,15,122,87,11
+ EDITTEXT IDC_FRAMEGAP,214,120,38,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_FRAMEGAPSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,232,118,11,14
+ GROUPBOX "Translucency options",IDC_STATIC,1,145,302,79
+ CONTROL "Transparent contact list",IDC_TRANSPARENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,156,281,9
+ LTEXT "Inactive opacity:",IDC_STATIC11,11,172,122,8
+ CONTROL "Slider2",IDC_TRANSINACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,142,171,34,11
+ LTEXT "000%",IDC_INACTIVEPERC,179,172,24,8,SS_NOPREFIX
+ LTEXT "Active opacity:",IDC_STATIC12,11,185,124,8
+ CONTROL "Slider2",IDC_TRANSACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,142,185,34,11
+ LTEXT "000%",IDC_ACTIVEPERC,179,186,24,8,SS_NOPREFIX
+ CONTROL "Fade contact list in/out",IDC_FADEINOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,198,286,10
+ CONTROL "Always Hide On Taskbar",IDC_ALWAYSHIDEONTASKBAR,"Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,141,11,158,10
+ LTEXT "pixels",IDC_STATIC6,258,121,42,8
+ CONTROL "Use Aero when available",IDC_USEAERO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,210,286,10
+END
+
+IDD_OPT_CLC DIALOGEX 0, 0, 305, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Items",IDC_STATIC,1,0,302,110
+ CONTROL "Show divider between online and offline contacts",IDC_DIVIDERONOFF,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,12,282,10
+ CONTROL "Hot track items as mouse passes over",IDC_TRACKSELECT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,23,282,10
+ CONTROL "Disable drag and drop of items",IDC_DISABLEDRAGDROP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,34,282,10
+ CONTROL "Disable rename of items by clicking twice",IDC_NOTEDITLABELS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,45,282,10
+ CONTROL "Show selection even when list is not focused",IDC_SHOWSELALWAYS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,56,282,10
+ CONTROL "Make selection highlight translucent",IDC_NOTNOTRANSLUCENTSEL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,67,282,10
+ CONTROL "Use full row for selection and hottracking",IDC_FULLROWSELECT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,78,282,10
+ CONTROL "Double click on avatar opens userinfo",IDC_DBLCLKAVATARS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,98,282,10
+ GROUPBOX "Visual",IDC_STATIC,0,111,303,113
+ CONTROL "Scroll list smoothly",IDC_NOTNOSMOOTHSCROLLING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,123,282,10
+ LTEXT "Time:",IDC_STATIC11,21,137,39,8
+ EDITTEXT IDC_SMOOTHTIME,63,135,45,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_SMOOTHTIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,96,138,11,14
+ LTEXT "milliseconds",IDC_STATIC12,114,137,73,8,SS_CENTERIMAGE
+ CONTROL "Hide vertical scroll bar",IDC_NOSCROLLBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,152,282,10
+ CONTROL "Grey out entire list when:",IDC_GREYOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,168,282,10
+ CONTROL "Tree1",IDC_GREYOUTOPTS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_NONEVENHEIGHT | WS_BORDER | WS_HSCROLL | WS_TABSTOP,11,181,182,39
+END
+
+IDD_OPT_SBAR DIALOGEX 0, 0, 303, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Status Bar",IDC_STATIC,3,4,297,214
+ CONTROL "Show status bar",IDC_SHOWSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,17,275,10
+ CONTROL "Show icons",IDC_SHOWICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,33,265,10
+ CONTROL "Show protocol names",IDC_SHOWPROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,48,265,10
+ CONTROL "Show status text",IDC_SHOWSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,63,265,10
+ CONTROL "Right click opens status menu",IDC_RIGHTSTATUS,"Button",BS_AUTORADIOBUTTON,25,160,265,10
+ CONTROL "Right click opens Miranda IM menu",IDC_RIGHTMIRANDA,
+ "Button",BS_AUTORADIOBUTTON,25,147,265,10
+ CONTROL "Make sections equal width",IDC_EQUALSECTIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,78,265,10
+ CONTROL "Mark protocols locked from global status changes",IDC_MARKLOCKED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,200,275,9
+END
+
+IDD_OPT_VIEWMODES DIALOGEX 0, 0, 309, 295
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_TAB,"SysTabControl32",0x0,4,4,301,264
+ LTEXT "",IDC_STATIC7,6,22,297,244
+ GROUPBOX "Available view modes",IDC_STATIC1,9,20,158,85
+ LISTBOX IDC_VIEWMODES,12,30,123,55,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP,WS_EX_CLIENTEDGE
+ GROUPBOX "Include protocols",IDC_STATIC2,171,20,130,85
+ CONTROL "",IDC_PROTOCOLS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,175,30,121,72
+ PUSHBUTTON "+",IDC_ADDVIEWMODE,142,39,18,16
+ PUSHBUTTON "-",IDC_DELETEVIEWMODE,142,60,18,16
+ LTEXT "New",IDC_STATIC5,15,91,38,11,0,WS_EX_TRANSPARENT
+ EDITTEXT IDC_NEWVIEMODE,59,88,76,13,ES_AUTOHSCROLL
+ GROUPBOX "Include groups",IDC_STATIC3,8,105,159,89,0,WS_EX_TRANSPARENT
+ CONTROL "",IDC_GROUPS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,12,116,122,73
+ GROUPBOX "Include status modes",IDC_STATIC4,171,105,130,89,0,WS_EX_TRANSPARENT
+ CONTROL "",IDC_STATUSMODES,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,175,116,121,73
+ PUSHBUTTON "Ok",IDOK,106,275,62,16
+ PUSHBUTTON "Cancel",IDCANCEL,172,275,62,16
+ PUSHBUTTON "Apply",IDC_APPLY,242,275,62,16
+ CONTROL "",IDC_CLIST,"CListControl",0x24a,12,31,286,199,WS_EX_CLIENTEDGE
+ GROUPBOX "Sticky contacts",IDC_STATIC9,8,20,293,215
+ PUSHBUTTON "Clear all",IDC_CLEARALL,13,241,92,14
+ LTEXT "Using the contact list on the left side, you can select contacts which will be ""sticky"" for this view mode. These contacts will ignore the standard filter rules and only use the status mode filter below.",IDC_STATIC10,174,50,124,72,NOT WS_VISIBLE
+ LTEXT "Protocol",IDC_STATIC12,31,204,49,12
+ COMBOBOX IDC_PROTOGROUPOP,85,202,37,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CTEXT "Group",IDC_STATIC13,129,204,44,12
+ COMBOBOX IDC_GROUPSTATUSOP,177,202,37,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ RTEXT "Status mode",IDC_STATIC14,221,204,54,12
+ CONTROL "Automatically clear this view mode after",IDC_AUTOCLEAR,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,244,172,11
+ EDITTEXT IDC_AUTOCLEARVAL,222,243,29,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_AUTOCLEARSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,245,243,8,13
+ LTEXT "seconds",IDC_STATIC15,262,244,28,12
+ GROUPBOX "View mode options",IDC_STATIC16,8,195,293,68
+ LTEXT "Statisch",IDC_CURVIEWMODE2,164,245,121,14
+ CONTROL "Last message ",IDC_LASTMSG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,227,86,11
+ COMBOBOX IDC_LASTMESSAGEOP,106,227,81,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_LASTMSGVALUE,193,227,31,13,ES_AUTOHSCROLL
+ COMBOBOX IDC_LASTMESSAGEUNIT,229,227,68,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_OPT_SKIN DIALOGEX 0, 0, 303, 197
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Skin root folder",IDC_STATIC,3,1,297,36
+ LTEXT "Static",IDC_SKINROOTFOLDER,12,10,279,21
+ GROUPBOX "Selected skin",IDC_STATIC,3,41,297,53
+ COMBOBOX IDC_SKINNAME,12,52,183,14,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Rescan",IDC_RESCANSKIN,202,52,90,14
+ CONTROL "Help on this",IDC_HELP_GENERAL,"Hyperlink",WS_TABSTOP | 0x1,11,77,67,9
+ PUSHBUTTON "Unload skin",IDC_UNLOAD,202,75,90,14
+ GROUPBOX "Skin options",IDC_STATIC,3,93,297,106
+ CONTROL "Use per protocol/contact skinning",IDC_USEPERPROTO,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,103,155,10
+ CONTROL "Protocol skins override status text colors",IDC_OVERRIDEPERSTATUSCOLOR,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,114,155,10
+ CONTROL "Apply group indent values to background drawing",IDC_APPLYINDENTBG,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,126,286,10
+ CONTROL "Ignore selection for groups",IDC_IGNORESELFORGROUPS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,137,286,10
+ LTEXT "Group top padding",IDC_STATIC,7,158,68,10
+ EDITTEXT IDC_GRPTOPPADDING,80,157,29,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_GRPPADDINGSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,96,164,11,13
+ CONTROL "Set all buttons to skinned mode",IDC_SETALLBUTTONSKINNED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,168,103,128,10
+ LTEXT "Frame titlebar height",IDC_STATIC,149,158,85,10
+ EDITTEXT IDC_LASTITEMPADDING,258,157,29,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_LASTITEMPADDINGSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,274,164,11,13
+ LTEXT "Window mode",IDC_STATIC,8,182,136,10
+ COMBOBOX IDC_WINDOWSTYLE,138,180,149,14,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_OPT DIALOGEX 0, 0, 312, 247
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_OPTIONSTAB,"SysTabControl32",WS_TABSTOP,1,1,310,226,WS_EX_ACCEPTFILES
+ PUSHBUTTON "Export to skin file",IDC_EXPORT,2,229,114,15
+ PUSHBUTTON "Save as user modification",IDC_SAVEASMOD,125,228,183,15
+END
+
+IDD_QUICKIGNORE DIALOGEX 0, 0, 357, 247
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Ignore these events",IDC_STATIC,7,3,197,85
+ CONTROL "Messages",IDC_IGN_MSGEVENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,14,106,11
+ CONTROL "Incoming file transfers",IDC_IGN_FILEEVENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,26,106,11
+ CONTROL "URL events",IDC_IGN_URLEVENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,38,106,11
+ CONTROL "Suppress auth requests",IDC_IGN_AUTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,50,182,11
+ CONTROL "Suppress added notifications",IDC_IGN_ADD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,62,182,11
+ CONTROL "Suppress online notifications",IDC_IGN_ONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,74,182,11
+ PUSHBUTTON "Ignore all",IDC_IGN_ALL,129,11,71,15
+ PUSHBUTTON "Ignore none",IDC_IGN_NONE,129,33,71,15
+ GROUPBOX "Visibility",IDC_STATIC,7,89,197,35
+ CONTROL "Appear always online",IDC_IGN_ALWAYSONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,98,182,11
+ CONTROL "Appear always offline (block contact)",IDC_IGN_ALWAYSOFFLINE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,111,182,11
+ GROUPBOX "Other",IDC_STATIC,7,125,197,96
+ CONTROL "Hide this contact from the list",IDC_HIDECONTACT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,132,182,14
+ LTEXT "To show a previously hidden contact, navigate to Options->Events->Ignore, search the contact in the list and tick the checkbox next to its name.",IDC_STATIC,18,146,182,34
+ GROUPBOX "Display options",IDC_STATIC,209,3,143,218
+ CONTROL "Show contact with priority",IDC_IGN_PRIORITY,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,219,13,127,11
+ LTEXT "Show Avatar:",IDC_STATIC,225,28,94,11
+ COMBOBOX IDC_AVATARDISPMODE,219,38,127,56,CBS_DROPDOWNLIST | CBS_SORT | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Show 2nd line:",IDC_STATIC,225,54,94,11
+ COMBOBOX IDC_SECONDLINEMODE,219,64,127,56,CBS_DROPDOWNLIST | CBS_SORT | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",IDC_IGN_ADDPERMANENTLY,"CLCButtonClass",WS_TABSTOP,95,202,106,15,WS_EX_NOACTIVATE | 0x10000000L
+ PUSHBUTTON "Ok",IDOK,211,228,65,14
+ PUSHBUTTON "Cancel",IDCANCEL,284,228,65,14
+ CONTROL "Draw overlay icon on avatar",IDC_OVERLAYICON,"Button",BS_AUTO3STATE | WS_TABSTOP,219,82,127,10
+ CONTROL "Show local time",IDC_SHOWLOCALTIME1,"Button",BS_AUTO3STATE | WS_TABSTOP,219,94,127,10
+ GROUPBOX "Extra icons",IDC_STATIC,213,118,134,80
+ CONTROL "Client",IDC_EXTRA_ICON_CLIENT,"Button",BS_AUTO3STATE | WS_TABSTOP,219,129,64,11
+ CONTROL "E-Mail",IDC_EXTRA_ICON_EMAIL,"Button",BS_AUTO3STATE | WS_TABSTOP,219,140,64,11
+ CONTROL "Homepage",IDC_EXTRA_ICON_WEB,"Button",BS_AUTO3STATE | WS_TABSTOP,219,151,64,11
+ CONTROL "Telephone",IDC_EXTRA_ICON_SMS,"Button",BS_AUTO3STATE | WS_TABSTOP,219,162,64,11
+ CONTROL "Reserved",IDC_EXTRA_ICON_RES0,"Button",BS_AUTO3STATE | WS_TABSTOP,219,173,64,11
+ CONTROL "Advanced #1",IDC_EXTRA_ICON_ADV1,"Button",BS_AUTO3STATE | WS_TABSTOP,288,129,55,11
+ CONTROL "Advanced #2",IDC_EXTRA_ICON_ADV2,"Button",BS_AUTO3STATE | WS_TABSTOP,288,140,55,11
+ CONTROL "Advanced #3",IDC_EXTRA_ICON_ADV3,"Button",BS_AUTO3STATE | WS_TABSTOP,288,151,55,11
+ CONTROL "Advanced #4",IDC_EXTRA_ICON_ADV4,"Button",BS_AUTO3STATE | WS_TABSTOP,288,162,55,11
+ CONTROL "Reserved #1",IDC_EXTRA_ICON_RES1,"Button",BS_AUTO3STATE | WS_TABSTOP,288,173,55,11
+ CONTROL "Reserved #2",IDC_EXTRA_ICON_RES2,"Button",BS_AUTO3STATE | WS_TABSTOP,288,184,55,11
+ CONTROL "Show visibility icon",IDC_SHOWVISIBILITY,"Button",BS_AUTO3STATE | WS_TABSTOP,219,107,127,10
+ CONTROL "",IDC_DSP_LOADDEFAULT,"CLCButtonClass",WS_TABSTOP,213,202,135,15,WS_EX_NOACTIVATE | 0x10000000L
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "include\\resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include <windows.h>\r\n"
+ "#include <winres.h>\r\n"
+ "#include <statusmodes.h>\r\n"
+ "#include <version.rc>\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_OVL_OFFLINE ICON "res/overlay/offline.ico"
+IDI_OVL_ONLINE ICON "res/overlay/online.ico"
+IDI_OVL_AWAY ICON "res/overlay/away.ico"
+IDI_OVL_DND ICON "res/overlay/dnd.ico"
+IDI_OVL_NA ICON "res/overlay/na.ico"
+IDI_OVL_OCCUPIED ICON "res/overlay/occupied.ico"
+IDI_OVL_FREEFORCHAT ICON "res/overlay/chat.ico"
+IDI_OVL_INVISIBLE ICON "res/overlay/invisible.ico"
+IDI_OVL_ONTHEPHONE ICON "res/overlay/phone.ico"
+IDI_OVL_OUTTOLUNCH ICON "res/overlay/lunch.ico"
+IDI_CLVISIBLE ICON "res/visible.ico"
+IDI_CLINVISIBLE ICON "res/invisible.ico"
+IDI_PROTOCONNECTING ICON "res/connecting.ico"
+IDI_TBTOPMENU ICON "res/menu.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Cursor
+//
+
+IDC_HYPERLINKHAND CURSOR "res/hyperlin.cur"
+IDC_DROP CURSOR "res/DRAGCOPY.CUR"
+IDC_DROPUSER CURSOR "res/dropuser.cur"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_CLISTMENU MENU
+BEGIN
+ POPUP "&¤"
+ BEGIN
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_ICQ_EXIT
+ END
+ POPUP "&Status"
+ BEGIN
+ MENUITEM "&Offline\tCtrl+0", ID_STATUS_OFFLINE, CHECKED
+ MENUITEM "On&line\tCtrl+1", ID_STATUS_ONLINE
+ MENUITEM "&Away\tCtrl+2", ID_STATUS_AWAY
+ MENUITEM "&NA\tCtrl+3", ID_STATUS_NA
+ MENUITEM "Occ&upied\tCtrl+4", ID_STATUS_OCCUPIED
+ MENUITEM "&DND\tCtrl+5", ID_STATUS_DND
+ MENUITEM "&Free for chat\tCtrl+6", ID_STATUS_FREECHAT
+ MENUITEM "&Invisible\tCtrl+7", ID_STATUS_INVISIBLE
+ MENUITEM "On the &Phone\tCtrl+8", ID_STATUS_ONTHEPHONE
+ MENUITEM "Out to &Lunch\tCtrl+9", ID_STATUS_OUTTOLUNCH
+ END
+END
+
+IDR_CONTEXT MENU
+BEGIN
+ POPUP "Tray"
+ BEGIN
+ MENUITEM "&Hide/Show", 40038
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_TRAY_EXIT
+ END
+ POPUP "Nowhere"
+ BEGIN
+ MENUITEM "&New Group", POPUP_NEWGROUP
+ MENUITEM SEPARATOR
+ MENUITEM "&Hide Offline Users", POPUP_HIDEOFFLINE
+ MENUITEM "Hide &Offline Users out here", POPUP_HIDEOFFLINEROOT
+ MENUITEM "Hide &Empty Groups", POPUP_HIDEEMPTYGROUPS
+ MENUITEM "Disable &Groups", POPUP_DISABLEGROUPS
+ MENUITEM SEPARATOR
+ MENUITEM SEPARATOR
+ MENUITEM "Hide Miranda", POPUP_HIDEMIRANDA
+ END
+ POPUP "Group"
+ BEGIN
+ MENUITEM "&New Subgroup", POPUP_NEWSUBGROUP
+ MENUITEM "&Hide Offline Users in here", POPUP_GROUPHIDEOFFLINE
+ MENUITEM SEPARATOR
+ MENUITEM "&Rename Group", POPUP_RENAMEGROUP
+ MENUITEM "&Delete Group", POPUP_DELETEGROUP
+ MENUITEM SEPARATOR
+ MENUITEM "Move marked Contacts to this Group", POPUP_MOVEMARKEDHERE, GRAYED
+ END
+ POPUP "Appearance"
+ BEGIN
+ MENUITEM "Show Status Icons", POPUP_SHOWSTATUSICONS
+ MENUITEM "Show Visibility Icons", POPUP_VISIBILITY
+ MENUITEM SEPARATOR
+ MENUITEM "Show additional Buttons", POPUP_BUTTONS
+ MENUITEM "Draw sunken Frame", POPUP_FRAME
+ MENUITEM SEPARATOR
+ MENUITEM "Use Status Floater", POPUP_FLOATER
+ MENUITEM "Auto-Hide Status Floater", POPUP_FLOATER_AUTOHIDE
+ MENUITEM "Show Event Area in Floater", POPUP_FLOATER_EVENTS
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// SKIN_GLYPH
+//
+
+IDR_SKIN_BASE SKIN_GLYPH "baseskin\\base.cng"
+IDR_SKIN_BACK SKIN_GLYPH "baseskin\\back.png"
+IDR_SKIN_GLYPHS SKIN_GLYPH "baseskin\\glyphs.png"
+IDR_SKIN_BACKAERO SKIN_GLYPH "baseskin\\AeroBack.png"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_SKINITEMEDIT, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 5373952
+ END
+
+ IDD_OPT_FLOATING, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1225129984
+ END
+
+ IDD_OPT_DSPPROFILES, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1347354624
+ END
+
+ IDD_OPTIONSDIALOG, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1598947328
+ END
+
+ IDD_OPT_CLIST, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1145634816
+ END
+
+ IDD_OPT_DSPCLASSES, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1598881792
+ END
+
+ IDD_OPT_DSPGROUPS, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1111556096
+ END
+
+ IDD_OPT_DSPITEMS, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1263730688
+ END
+
+ IDD_OPT_DSPADVANCED, DIALOG
+ BEGIN
+ , 50
+ , 4653056, 1414070272
+ END
+
+ IDD_OPT_XICONS, DIALOG
+ BEGIN
+ , 50
+ END
+
+ IDD_OPT_CLUI, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1936261120
+ END
+
+ IDD_OPT_CLC, DIALOG
+ BEGIN
+ , 50
+ , 268435456, -65536
+ END
+
+ IDD_OPT_SBAR, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1920204800
+ END
+
+ IDD_OPT_SKIN, DIALOG
+ BEGIN
+ , 50
+ , 268435456, 1935998976
+ END
+
+ IDD_OPT, DIALOG
+ BEGIN
+ , 50
+ , 7667712, 1397489767
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Clist_ng/skineditor/skinedit.cpp b/plugins/Clist_ng/skineditor/skinedit.cpp new file mode 100644 index 0000000000..c883f63c87 --- /dev/null +++ b/plugins/Clist_ng/skineditor/skinedit.cpp @@ -0,0 +1,902 @@ +/*
+ * 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
+ *
+ *
+ * This code was originally written by pixel for the clist_nicer plugin
+ * for Miranda many years ago. Adopted to clist_nicer+ and now
+ * clist_ng.
+ *
+ * $Id: skinedit.cpp 128 2010-09-26 12:12:56Z silvercircle $
+ *
+ */
+#include <commonheaders.h>
+
+#define ID_EXTBKSEPARATOR 40200
+
+TStatusItem *StatusItems;
+ChangedSItems_t ChangedSItems = {0};
+
+static int LastModifiedItem = -1;
+static int last_selcount = 0;
+static int last_indizes[64];
+static int ID_EXTBK_LAST = 0, ID_EXTBK_FIRST = 0;
+
+/*
+ * prototypes
+ */
+
+static void ChangeControlItems(HWND hwndDlg, int status, int except);
+static BOOL CheckItem(int item, HWND hwndDlg);
+
+static UINT _controls_to_refresh[] = {
+ IDC_MRGN_BOTTOM,
+ IDC_MRGN_LEFT,
+ IDC_ALPHASPIN,
+ IDC_CORNER,
+ IDC_MRGN_TOP_SPIN,
+ IDC_MRGN_RIGHT_SPIN,
+ IDC_MRGN_BOTTOM_SPIN,
+ IDC_MRGN_LEFT_SPIN,
+ IDC_GRADIENT,
+ IDC_GRADIENT_LR,
+ IDC_GRADIENT_RL,
+ IDC_GRADIENT_TB,
+ IDC_BASECOLOUR,
+ IDC_ALPHA,
+ IDC_MRGN_TOP,
+ IDC_MRGN_RIGHT,
+ IDC_GRADIENT_BT,
+ IDC_BASECOLOUR2,
+ IDC_TEXTCOLOUR,
+ IDC_CORNER_TL,
+ IDC_CORNER_TR,
+ IDC_CORNER_BR,
+ IDC_CORNER_BL,
+ IDC_IGNORE,
+ IDC_ALPHALABLE,
+ IDC_ALPHALABLE2,
+ IDC_COLOR2LABLE,
+ IDC_COLORLABLE,
+ IDC_TEXTCOLOURLABLE,
+ IDC_ALPHA2,
+ IDC_ALPHASPIN2,
+ IDC_SKIP_UNDERLAY,
+ IDC_SKIP_IMAGE,
+ 0
+};
+
+static UINT _controls_to_hide[] = {
+ IDC_ALPHASPIN,
+ IDC_CORNER,
+ IDC_GRADIENT,
+ IDC_GRADIENT_LR,
+ IDC_GRADIENT_RL,
+ IDC_GRADIENT_TB,
+ IDC_BASECOLOUR,
+ IDC_ALPHA,
+ IDC_GRADIENT_BT,
+ IDC_BASECOLOUR2,
+ IDC_TEXTCOLOUR,
+ IDC_CORNER_TL,
+ IDC_CORNER_TR,
+ IDC_CORNER_BR,
+ IDC_CORNER_BL,
+ IDC_ALPHALABLE,
+ IDC_ALPHALABLE2,
+ IDC_COLOR2LABLE,
+ IDC_COLORLABLE,
+ IDC_TEXTCOLOURLABLE,
+ IDC_ALPHA2,
+ IDC_ALPHASPIN2,
+ IDC_SKIP_UNDERLAY,
+ IDC_SKIP_IMAGE,
+ 0
+};
+
+static void RefreshControls(HWND hwnd)
+{
+ for(int i = 0; _controls_to_refresh[i]; i++)
+ InvalidateRect(GetDlgItem(hwnd, _controls_to_refresh[i]), NULL, FALSE);
+}
+
+static void ReActiveCombo(HWND hwndDlg)
+{
+ if (IsDlgButtonChecked(hwndDlg, IDC_IGNORE)) {
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_LR, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_RL, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_TB, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_BT, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TL, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TR, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BR, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BL, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ ChangeControlItems(hwndDlg, !IsDlgButtonChecked(hwndDlg, IDC_IGNORE), IDC_IGNORE);
+ } else {
+ ChangeControlItems(hwndDlg, !IsDlgButtonChecked(hwndDlg, IDC_IGNORE), IDC_IGNORE);
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_LR, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_RL, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_TB, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_BT, IsDlgButtonChecked(hwndDlg, IDC_GRADIENT));
+
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TL, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TR, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BR, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BL, IsDlgButtonChecked(hwndDlg, IDC_CORNER));
+ }
+}
+
+// enabled or disabled the whole status controlitems group (with exceptional control)
+static void ChangeControlItems(HWND hwndDlg, int status, int except)
+{
+ if (except != IDC_GRADIENT)
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT, status);
+ if (except != IDC_GRADIENT_LR)
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_LR, status);
+ if (except != IDC_GRADIENT_RL)
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_RL, status);
+ if (except != IDC_GRADIENT_TB)
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_TB, status);
+ if (except != IDC_GRADIENT_BT)
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_BT, status);
+ if (except != IDC_CORNER)
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER, status);
+ if (except != IDC_CORNER_TL)
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TL, status);
+ if (except != IDC_CORNER_TR)
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TR, status);
+ if (except != IDC_CORNER_BR)
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BR, status);
+ if (except != IDC_CORNER_BL)
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BL, status);
+ if (except != IDC_CORNER_TL)
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TL, status);
+ if (except != IDC_MARGINLABLE)
+ Utils::enableDlgControl(hwndDlg, IDC_MARGINLABLE, status);
+ if (except != IDC_MRGN_TOP)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_TOP, status);
+ if (except != IDC_MRGN_RIGHT)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_RIGHT, status);
+ if (except != IDC_MRGN_BOTTOM)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_BOTTOM, status);
+ if (except != IDC_MRGN_LEFT)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_LEFT, status);
+ if (except != IDC_MRGN_TOP_SPIN)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_TOP_SPIN, status);
+ if (except != IDC_MRGN_RIGHT_SPIN)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_RIGHT_SPIN, status);
+ if (except != IDC_MRGN_BOTTOM_SPIN)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_BOTTOM_SPIN, status);
+ if (except != IDC_MRGN_LEFT_SPIN)
+ Utils::enableDlgControl(hwndDlg, IDC_MRGN_LEFT_SPIN, status);
+ if (except != IDC_BASECOLOUR)
+ Utils::enableDlgControl(hwndDlg, IDC_BASECOLOUR, status);
+ if (except != IDC_COLORLABLE)
+ Utils::enableDlgControl(hwndDlg, IDC_COLORLABLE, status);
+ if (except != IDC_BASECOLOUR2)
+ Utils::enableDlgControl(hwndDlg, IDC_BASECOLOUR2, status);
+ if (except != IDC_COLOR2LABLE)
+ Utils::enableDlgControl(hwndDlg, IDC_COLOR2LABLE, status);
+ if (except != IDC_TEXTCOLOUR)
+ Utils::enableDlgControl(hwndDlg, IDC_TEXTCOLOUR, status);
+ if (except != IDC_TEXTCOLOURLABLE)
+ Utils::enableDlgControl(hwndDlg, IDC_TEXTCOLOURLABLE, status);
+
+ if (except != IDC_ALPHA)
+ Utils::enableDlgControl(hwndDlg, IDC_ALPHA, status);
+ if (except != IDC_ALPHASPIN)
+ Utils::enableDlgControl(hwndDlg, IDC_ALPHASPIN, status);
+
+ if (except != IDC_ALPHA2)
+ Utils::enableDlgControl(hwndDlg, IDC_ALPHA2, status);
+ if (except != IDC_ALPHASPIN2)
+ Utils::enableDlgControl(hwndDlg, IDC_ALPHASPIN2, status);
+
+ if (except != IDC_ALPHALABLE)
+ Utils::enableDlgControl(hwndDlg, IDC_ALPHALABLE, status);
+ if (except != IDC_ALPHALABLE2)
+ Utils::enableDlgControl(hwndDlg, IDC_ALPHALABLE2, status);
+ if (except != IDC_IGNORE)
+ Utils::enableDlgControl(hwndDlg, IDC_IGNORE, status);
+
+ if (except != IDC_SKIP_UNDERLAY)
+ Utils::enableDlgControl(hwndDlg, IDC_SKIP_UNDERLAY, status);
+ if (except != IDC_SKIP_IMAGE)
+ Utils::enableDlgControl(hwndDlg, IDC_SKIP_IMAGE, status);
+
+}
+
+static void FillOptionDialogByStatusItem(HWND hwndDlg, TStatusItem *item)
+{
+ char itoabuf[15];
+ DWORD ret, cmdShow;
+ int i;
+
+ if(item->dwFlags & S_ITEM_IMAGE_ONLY)
+ cmdShow = SW_HIDE;
+ else
+ cmdShow = SW_SHOW;
+
+ for(i = 0; _controls_to_hide[i]; i++)
+ Utils::showDlgControl(hwndDlg, _controls_to_hide[i], cmdShow);
+
+ if(item->dwFlags & S_ITEM_IMAGE_ONLY)
+ return;
+
+ CheckDlgButton(hwndDlg, IDC_IGNORE, (item->IGNORED) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_GRADIENT, (item->GRADIENT & GRADIENT_ACTIVE) ? BST_CHECKED : BST_UNCHECKED);
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_LR, item->GRADIENT & GRADIENT_ACTIVE);
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_RL, item->GRADIENT & GRADIENT_ACTIVE);
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_TB, item->GRADIENT & GRADIENT_ACTIVE);
+ Utils::enableDlgControl(hwndDlg, IDC_GRADIENT_BT, item->GRADIENT & GRADIENT_ACTIVE);
+ CheckDlgButton(hwndDlg, IDC_GRADIENT_LR, (item->GRADIENT & GRADIENT_LR) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_GRADIENT_RL, (item->GRADIENT & GRADIENT_RL) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_GRADIENT_TB, (item->GRADIENT & GRADIENT_TB) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_GRADIENT_BT, (item->GRADIENT & GRADIENT_BT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_CORNER, (item->CORNER & CORNER_ACTIVE) ? BST_CHECKED : BST_UNCHECKED);
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TL, item->CORNER & CORNER_ACTIVE);
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_TR, item->CORNER & CORNER_ACTIVE);
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BR, item->CORNER & CORNER_ACTIVE);
+ Utils::enableDlgControl(hwndDlg, IDC_CORNER_BL, item->CORNER & CORNER_ACTIVE);
+
+ CheckDlgButton(hwndDlg, IDC_CORNER_TL, (item->CORNER & CORNER_TL) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CORNER_TR, (item->CORNER & CORNER_TR) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CORNER_BR, (item->CORNER & CORNER_BR) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CORNER_BL, (item->CORNER & CORNER_BL) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_SKIP_UNDERLAY, (item->dwFlags & S_ITEM_SKIP_UNDERLAY) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SKIP_IMAGE, (item->dwFlags & S_ITEM_SKIP_IMAGE) ? BST_CHECKED : BST_UNCHECKED);
+
+ ret = item->COLOR;
+ SendDlgItemMessage(hwndDlg, IDC_BASECOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_COLOR);
+ SendDlgItemMessage(hwndDlg, IDC_BASECOLOUR, CPM_SETCOLOUR, 0, ret);
+
+ ret = item->COLOR2;
+ SendDlgItemMessage(hwndDlg, IDC_BASECOLOUR2, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_COLOR2);
+ SendDlgItemMessage(hwndDlg, IDC_BASECOLOUR2, CPM_SETCOLOUR, 0, ret);
+
+ ret = item->TEXTCOLOR;
+ SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_TEXTCOLOR);
+ SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOUR, CPM_SETCOLOUR, 0, ret);
+
+ if (item->ALPHA == -1) {
+ SetDlgItemTextA(hwndDlg, IDC_ALPHA, "");
+ } else {
+ ret = item->ALPHA;
+ _itoa(ret, itoabuf, 10);
+ SetDlgItemTextA(hwndDlg, IDC_ALPHA, itoabuf);
+ }
+
+ if (item->ALPHA2 == -1) {
+ SetDlgItemTextA(hwndDlg, IDC_ALPHA2, "");
+ } else {
+ ret = item->ALPHA2;
+ _itoa(ret, itoabuf, 10);
+ SetDlgItemTextA(hwndDlg, IDC_ALPHA2, itoabuf);
+ }
+
+ if (item->MARGIN_LEFT == -1)
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_LEFT, "");
+ else {
+ ret = item->MARGIN_LEFT;
+ _itoa(ret, itoabuf, 10);
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_LEFT, itoabuf);
+ }
+
+ if (item->MARGIN_TOP == -1)
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_TOP, "");
+ else {
+ ret = item->MARGIN_TOP;
+ _itoa(ret, itoabuf, 10);
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_TOP, itoabuf);
+ }
+
+ if (item->MARGIN_RIGHT == -1)
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_RIGHT, "");
+ else {
+ ret = item->MARGIN_RIGHT;
+ _itoa(ret, itoabuf, 10);
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_RIGHT, itoabuf);
+ }
+
+ if (item->MARGIN_BOTTOM == -1)
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_BOTTOM, "");
+ else {
+ ret = item->MARGIN_BOTTOM;
+ _itoa(ret, itoabuf, 10);
+ SetDlgItemTextA(hwndDlg, IDC_MRGN_BOTTOM, itoabuf);
+ }
+ ReActiveCombo(hwndDlg);
+}
+// update dlg with selected item
+static void FillOptionDialogByCurrentSel(HWND hwndDlg)
+{
+ int index = SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_GETCURSEL, 0, 0);
+ int itemData = SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_GETITEMDATA, index, 0);
+ if(itemData != ID_EXTBKSEPARATOR) {
+ LastModifiedItem = itemData - ID_EXTBK_FIRST;
+
+ if (CheckItem(itemData - ID_EXTBK_FIRST, hwndDlg)) {
+ FillOptionDialogByStatusItem(hwndDlg, &StatusItems[itemData - ID_EXTBK_FIRST]);
+ }
+ }
+}
+
+
+// enabled all status controls if the selected item is a separator
+static BOOL CheckItem(int item, HWND hwndDlg)
+{
+ if (StatusItems[item].statusID == ID_EXTBKSEPARATOR) {
+ ChangeControlItems(hwndDlg, 0, 0);
+ return FALSE;
+ } else {
+ ChangeControlItems(hwndDlg, 1, 0);
+ return TRUE;
+ }
+}
+
+static void SetChangedStatusItemFlag(WPARAM wParam, HWND hwndDlg)
+{
+ if (LOWORD(wParam) != IDC_ITEMS
+ && (GetDlgItem(hwndDlg, LOWORD(wParam)) == GetFocus() || HIWORD(wParam) == CPN_COLOURCHANGED)
+ && (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == CPN_COLOURCHANGED)) {
+ switch (LOWORD(wParam)) {
+ case IDC_IGNORE:
+ ChangedSItems.bIGNORED = TRUE; break;
+ case IDC_GRADIENT:
+ ChangedSItems.bGRADIENT = TRUE; break;
+ case IDC_GRADIENT_LR:
+ ChangedSItems.bGRADIENT = TRUE;break;
+ case IDC_GRADIENT_RL:
+ ChangedSItems.bGRADIENT = TRUE; break;
+ case IDC_GRADIENT_BT:
+ ChangedSItems.bGRADIENT = TRUE; break;
+ case IDC_GRADIENT_TB:
+ ChangedSItems.bGRADIENT = TRUE; break;
+
+ case IDC_CORNER:
+ ChangedSItems.bCORNER = TRUE; break;
+ case IDC_CORNER_TL:
+ ChangedSItems.bCORNER = TRUE; break;
+ case IDC_CORNER_TR:
+ ChangedSItems.bCORNER = TRUE; break;
+ case IDC_CORNER_BR:
+ ChangedSItems.bCORNER = TRUE; break;
+ case IDC_CORNER_BL:
+ ChangedSItems.bCORNER = TRUE; break;
+
+ case IDC_BASECOLOUR:
+ ChangedSItems.bCOLOR = TRUE; break;
+ case IDC_BASECOLOUR2:
+ ChangedSItems.bCOLOR2 = TRUE; break;
+ case IDC_TEXTCOLOUR:
+ ChangedSItems.bTEXTCOLOR = TRUE; break;
+
+ case IDC_ALPHA:
+ ChangedSItems.bALPHA = TRUE; break;
+ case IDC_ALPHASPIN:
+ ChangedSItems.bALPHA = TRUE; break;
+ case IDC_ALPHA2:
+ ChangedSItems.bALPHA2 = TRUE; break;
+ case IDC_ALPHASPIN2:
+ ChangedSItems.bALPHA2 = TRUE; break;
+
+ case IDC_MRGN_LEFT:
+ ChangedSItems.bMARGIN_LEFT = TRUE; break;
+ case IDC_MRGN_LEFT_SPIN:
+ ChangedSItems.bMARGIN_LEFT = TRUE; break;
+
+ case IDC_MRGN_TOP:
+ ChangedSItems.bMARGIN_TOP = TRUE; break;
+ case IDC_MRGN_TOP_SPIN:
+ ChangedSItems.bMARGIN_TOP = TRUE; break;
+
+ case IDC_MRGN_RIGHT:
+ ChangedSItems.bMARGIN_RIGHT = TRUE; break;
+ case IDC_MRGN_RIGHT_SPIN:
+ ChangedSItems.bMARGIN_RIGHT = TRUE; break;
+
+ case IDC_MRGN_BOTTOM:
+ ChangedSItems.bMARGIN_BOTTOM = TRUE; break;
+ case IDC_MRGN_BOTTOM_SPIN:
+ ChangedSItems.bMARGIN_BOTTOM = TRUE; break;
+
+ case IDC_SKIP_UNDERLAY:
+ case IDC_SKIP_IMAGE:
+ ChangedSItems.bFlags = TRUE;
+ break;
+ }
+ }
+}
+
+static BOOL isValidItem(void)
+{
+ if (StatusItems[LastModifiedItem].statusID == ID_EXTBKSEPARATOR)
+ return FALSE;
+
+ return TRUE;
+}
+
+// updates the struct with the changed dlg item
+static void UpdateStatusStructSettingsFromOptDlg(HWND hwndDlg, int index)
+{
+ char buf[15];
+
+ if (ChangedSItems.bIGNORED)
+ StatusItems[index]. IGNORED = IsDlgButtonChecked(hwndDlg, IDC_IGNORE);
+
+ if (ChangedSItems.bGRADIENT) {
+ StatusItems[index]. GRADIENT = GRADIENT_NONE;
+ if (IsDlgButtonChecked(hwndDlg, IDC_GRADIENT))
+ StatusItems[index].GRADIENT |= GRADIENT_ACTIVE;
+ if (IsDlgButtonChecked(hwndDlg, IDC_GRADIENT_LR))
+ StatusItems[index].GRADIENT |= GRADIENT_LR;
+ if (IsDlgButtonChecked(hwndDlg, IDC_GRADIENT_RL))
+ StatusItems[index].GRADIENT |= GRADIENT_RL;
+ if (IsDlgButtonChecked(hwndDlg, IDC_GRADIENT_TB))
+ StatusItems[index].GRADIENT |= GRADIENT_TB;
+ if (IsDlgButtonChecked(hwndDlg, IDC_GRADIENT_BT))
+ StatusItems[index].GRADIENT |= GRADIENT_BT;
+ }
+ if (ChangedSItems.bCORNER) {
+ StatusItems[index]. CORNER = CORNER_NONE;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CORNER))
+ StatusItems[index].CORNER |= CORNER_ACTIVE ;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CORNER_TL))
+ StatusItems[index].CORNER |= CORNER_TL ;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CORNER_TR))
+ StatusItems[index].CORNER |= CORNER_TR;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CORNER_BR))
+ StatusItems[index].CORNER |= CORNER_BR;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CORNER_BL))
+ StatusItems[index].CORNER |= CORNER_BL;
+ }
+
+ if (ChangedSItems.bCOLOR)
+ StatusItems[index]. COLOR = SendDlgItemMessage(hwndDlg, IDC_BASECOLOUR, CPM_GETCOLOUR, 0, 0);
+
+ if (ChangedSItems.bCOLOR2)
+ StatusItems[index]. COLOR2 = SendDlgItemMessage(hwndDlg, IDC_BASECOLOUR2, CPM_GETCOLOUR, 0, 0);
+
+ if (ChangedSItems.bALPHA2) {
+ GetWindowTextA(GetDlgItem(hwndDlg, IDC_ALPHA2), buf, 10); // can be removed now
+ if (lstrlenA(buf) > 0)
+ StatusItems[index].ALPHA2 = (BYTE) SendDlgItemMessage(hwndDlg, IDC_ALPHASPIN2, UDM_GETPOS, 0, 0);
+ }
+
+ if (ChangedSItems.bTEXTCOLOR)
+ StatusItems[index]. TEXTCOLOR = SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOUR, CPM_GETCOLOUR, 0, 0);
+
+ if (ChangedSItems.bALPHA) {
+ GetWindowTextA(GetDlgItem(hwndDlg, IDC_ALPHA), buf, 10); // can be removed now
+ if (lstrlenA(buf) > 0)
+ StatusItems[index]. ALPHA = (BYTE) SendDlgItemMessage(hwndDlg, IDC_ALPHASPIN, UDM_GETPOS, 0, 0);
+ }
+
+ if (ChangedSItems.bMARGIN_LEFT) {
+ GetWindowTextA(GetDlgItem(hwndDlg, IDC_MRGN_LEFT), buf, 10);
+ if (lstrlenA(buf) > 0)
+ StatusItems[index]. MARGIN_LEFT = (BYTE) SendDlgItemMessage(hwndDlg, IDC_MRGN_LEFT_SPIN, UDM_GETPOS, 0, 0);
+ }
+
+ if (ChangedSItems.bMARGIN_TOP) {
+ GetWindowTextA(GetDlgItem(hwndDlg, IDC_MRGN_TOP), buf, 10);
+ if (lstrlenA(buf) > 0)
+ StatusItems[index]. MARGIN_TOP = (BYTE) SendDlgItemMessage(hwndDlg, IDC_MRGN_TOP_SPIN, UDM_GETPOS, 0, 0);
+ }
+
+ if (ChangedSItems.bMARGIN_RIGHT) {
+ GetWindowTextA(GetDlgItem(hwndDlg, IDC_MRGN_RIGHT), buf, 10);
+ if (lstrlenA(buf) > 0)
+ StatusItems[index]. MARGIN_RIGHT = (BYTE) SendDlgItemMessage(hwndDlg, IDC_MRGN_RIGHT_SPIN, UDM_GETPOS, 0, 0);
+ }
+
+ if (ChangedSItems.bMARGIN_BOTTOM) {
+ GetWindowTextA(GetDlgItem(hwndDlg, IDC_MRGN_BOTTOM), buf, 10);
+ if (lstrlenA(buf) > 0)
+ StatusItems[index]. MARGIN_BOTTOM = (BYTE) SendDlgItemMessage(hwndDlg, IDC_MRGN_BOTTOM_SPIN, UDM_GETPOS, 0, 0);
+ }
+
+ if (ChangedSItems.bFlags) {
+ StatusItems[index].dwFlags = (IsDlgButtonChecked(hwndDlg, IDC_SKIP_UNDERLAY) ? StatusItems[index].dwFlags | S_ITEM_SKIP_UNDERLAY :
+ StatusItems[index].dwFlags & ~S_ITEM_SKIP_UNDERLAY);
+ StatusItems[index].dwFlags = (IsDlgButtonChecked(hwndDlg, IDC_SKIP_IMAGE) ? StatusItems[index].dwFlags | S_ITEM_SKIP_IMAGE :
+ StatusItems[index].dwFlags & ~S_ITEM_SKIP_IMAGE);
+ }
+
+ Skin::setupAGGItemContext(&StatusItems[index]);
+}
+
+static void SaveLatestChanges(HWND hwndDlg)
+{
+ int n, itemData;
+ // process old selection
+ if (last_selcount > 0) {
+ for (n = 0; n < last_selcount; n++) {
+ itemData = SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_GETITEMDATA, last_indizes[n], 0);
+ if (itemData != ID_EXTBKSEPARATOR) {
+ UpdateStatusStructSettingsFromOptDlg(hwndDlg, itemData - ID_EXTBK_FIRST);
+ }
+ }
+ }
+
+ // reset bChange
+ ChangedSItems.bALPHA = FALSE;
+ ChangedSItems.bGRADIENT = FALSE;
+ ChangedSItems.bCORNER = FALSE;
+ ChangedSItems.bCOLOR = FALSE;
+ ChangedSItems.bCOLOR2 = FALSE;
+ ChangedSItems.bALPHA2 = FALSE;
+ ChangedSItems.bTEXTCOLOR = FALSE;
+ ChangedSItems.bALPHA = FALSE;
+ ChangedSItems.bMARGIN_LEFT = FALSE;
+ ChangedSItems.bMARGIN_TOP = FALSE;
+ ChangedSItems.bMARGIN_RIGHT = FALSE;
+ ChangedSItems.bMARGIN_BOTTOM = FALSE;
+ ChangedSItems.bIGNORED = FALSE;
+ ChangedSItems.bFlags = FALSE;
+}
+
+static void OnListItemsChange(HWND hwndDlg)
+{
+ SendMessage(hwndDlg, WM_SETREDRAW, FALSE, 0);
+ SaveLatestChanges(hwndDlg);
+
+ // set new selection
+ last_selcount = SendMessage(GetDlgItem(hwndDlg, IDC_ITEMS), LB_GETSELCOUNT, 0, 0);
+ if (last_selcount > 0) {
+ int n, real_index, itemData, first_item;
+ TStatusItem DialogSettingForMultiSel;
+
+ // get selected indizes
+ SendMessage(GetDlgItem(hwndDlg, IDC_ITEMS), LB_GETSELITEMS, 64, (LPARAM) last_indizes);
+
+ // initialize with first items value
+
+ first_item = SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_GETITEMDATA, last_indizes[0], 0) - ID_EXTBK_FIRST;
+ DialogSettingForMultiSel = StatusItems[first_item];
+ for (n = 0; n < last_selcount; n++) {
+ itemData = SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_GETITEMDATA, last_indizes[n], 0);
+ if (itemData != ID_EXTBKSEPARATOR) {
+ real_index = itemData - ID_EXTBK_FIRST;
+ if (StatusItems[real_index].ALPHA != StatusItems[first_item].ALPHA)
+ DialogSettingForMultiSel.ALPHA = -1;
+ if (StatusItems[real_index].COLOR != StatusItems[first_item].COLOR)
+ DialogSettingForMultiSel.COLOR = CLCDEFAULT_COLOR;
+ if (StatusItems[real_index].COLOR2 != StatusItems[first_item].COLOR2)
+ DialogSettingForMultiSel.COLOR2 = CLCDEFAULT_COLOR2;
+ if (StatusItems[real_index].ALPHA2 != StatusItems[first_item].ALPHA2)
+ DialogSettingForMultiSel.ALPHA2 = -1;
+ if (StatusItems[real_index].TEXTCOLOR != StatusItems[first_item].TEXTCOLOR)
+ DialogSettingForMultiSel.TEXTCOLOR = CLCDEFAULT_TEXTCOLOR;
+ if (StatusItems[real_index].CORNER != StatusItems[first_item].CORNER)
+ DialogSettingForMultiSel.CORNER = CLCDEFAULT_CORNER;
+ if (StatusItems[real_index].GRADIENT != StatusItems[first_item].GRADIENT)
+ DialogSettingForMultiSel.GRADIENT = CLCDEFAULT_GRADIENT;
+ if (StatusItems[real_index].IGNORED != StatusItems[first_item].IGNORED)
+ DialogSettingForMultiSel.IGNORED = CLCDEFAULT_IGNORE;
+ if (StatusItems[real_index].MARGIN_BOTTOM != StatusItems[first_item].MARGIN_BOTTOM)
+ DialogSettingForMultiSel.MARGIN_BOTTOM = -1;
+ if (StatusItems[real_index].MARGIN_LEFT != StatusItems[first_item].MARGIN_LEFT)
+ DialogSettingForMultiSel.MARGIN_LEFT = -1;
+ if (StatusItems[real_index].MARGIN_RIGHT != StatusItems[first_item].MARGIN_RIGHT)
+ DialogSettingForMultiSel.MARGIN_RIGHT = -1;
+ if (StatusItems[real_index].MARGIN_TOP != StatusItems[first_item].MARGIN_TOP)
+ DialogSettingForMultiSel.MARGIN_TOP = -1;
+ if (StatusItems[real_index].dwFlags != StatusItems[first_item].dwFlags)
+ DialogSettingForMultiSel.dwFlags = -1;
+ }
+ }
+
+ if (last_selcount == 1 && StatusItems[first_item].statusID == ID_EXTBKSEPARATOR) {
+ ChangeControlItems(hwndDlg, 0, 0);
+ last_selcount = 0;
+ } else {
+
+ ChangeControlItems(hwndDlg, 1, 0);
+ }
+ FillOptionDialogByStatusItem(hwndDlg, &DialogSettingForMultiSel);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_ITEMS), NULL, FALSE);
+ }
+ SendMessage(hwndDlg, WM_SETREDRAW, TRUE, 0);
+ RefreshControls(hwndDlg);
+}
+
+// fills the combobox of the options dlg for the first time
+static void FillItemList(HWND hwndDlg)
+{
+ int n, iOff;
+ UINT item;
+
+ for (n = 0; n <= ID_EXTBK_LAST - ID_EXTBK_FIRST; n++) {
+ iOff = 0;
+ if(strstr(StatusItems[n].szName, "{-}")) {
+ item = SendDlgItemMessageA(hwndDlg, IDC_ITEMS, LB_ADDSTRING, 0, (LPARAM)"------------------------");
+ SendDlgItemMessageA(hwndDlg, IDC_ITEMS, LB_SETITEMDATA, item, ID_EXTBKSEPARATOR);
+ iOff = 3;
+ }
+ item = SendDlgItemMessageA(hwndDlg, IDC_ITEMS, LB_ADDSTRING, 0, (LPARAM)&StatusItems[n].szName[iOff]);
+ SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_SETITEMDATA, item, ID_EXTBK_FIRST + n);
+ }
+}
+
+static BOOL CALLBACK SkinEdit_ExtBkDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SKINDESCRIPTION *psd = (SKINDESCRIPTION *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ if(psd) {
+ ID_EXTBK_FIRST = psd->firstItem;
+ ID_EXTBK_LAST = psd->lastItem;
+ StatusItems = psd->StatusItems;
+ }
+ switch (msg) {
+ case WM_INITDIALOG:
+ psd = (SKINDESCRIPTION *)malloc(sizeof(SKINDESCRIPTION));
+ ZeroMemory(psd, sizeof(SKINDESCRIPTION));
+ CopyMemory(psd, (void *)lParam, sizeof(SKINDESCRIPTION));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)psd);
+
+ if(psd) {
+ ID_EXTBK_FIRST = psd->firstItem;
+ ID_EXTBK_LAST = psd->lastItem;
+ StatusItems = psd->StatusItems;
+ }
+
+ TranslateDialogDefault(hwndDlg);
+ FillItemList(hwndDlg);
+ SendMessage(hwndDlg, WM_USER + 101, 0, 0);
+
+ psd->hMenuItems = CreatePopupMenu();
+ AppendMenu(psd->hMenuItems, MF_STRING | MF_DISABLED, (UINT_PTR)0, _T("Copy from"));
+ AppendMenuA(psd->hMenuItems, MF_SEPARATOR, (UINT_PTR)0, NULL);
+
+ {
+ int i;
+
+ for(i = ID_EXTBK_FIRST; i <= ID_EXTBK_LAST; i++) {
+ int iOff = StatusItems[i - ID_EXTBK_FIRST].szName[0] == '{' ? 3 : 0;
+ if(iOff)
+ AppendMenuA(psd->hMenuItems, MF_SEPARATOR, (UINT_PTR)0, NULL);
+ AppendMenuA(psd->hMenuItems, MF_STRING, (UINT_PTR)i, &StatusItems[i - ID_EXTBK_FIRST].szName[iOff]);
+ }
+ }
+ return TRUE;
+ case WM_USER + 101:
+ {
+ SendDlgItemMessage(hwndDlg, IDC_MRGN_LEFT_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
+ SendDlgItemMessage(hwndDlg, IDC_MRGN_TOP_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
+ SendDlgItemMessage(hwndDlg, IDC_MRGN_RIGHT_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
+ SendDlgItemMessage(hwndDlg, IDC_MRGN_BOTTOM_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
+ SendDlgItemMessage(hwndDlg, IDC_ALPHASPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
+ SendDlgItemMessage(hwndDlg, IDC_ALPHASPIN2, UDM_SETRANGE, 0, MAKELONG(100, 0));
+
+ return 0;
+ }
+
+ case WM_DRAWITEM:
+ {
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam;
+ int iItem = dis->itemData;
+ TStatusItem *item = 0;
+
+ SetBkMode(dis->hDC, TRANSPARENT);
+ FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_WINDOW));
+
+ if(iItem >= ID_EXTBK_FIRST && iItem <= ID_EXTBK_LAST)
+ item = &StatusItems[iItem - ID_EXTBK_FIRST];
+
+ if (dis->itemState & ODS_SELECTED && iItem != ID_EXTBKSEPARATOR) {
+ FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ }
+ else {
+ FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_WINDOW));
+ if(item && item->IGNORED)
+ SetTextColor(dis->hDC, RGB(255, 0, 0));
+ else if(item && item->dwFlags & S_ITEM_IMAGE_ONLY)
+ SetTextColor(dis->hDC, RGB(0, 0, 255));
+ else
+ SetTextColor(dis->hDC, GetSysColor(COLOR_WINDOWTEXT));
+ }
+ if(iItem == ID_EXTBKSEPARATOR) {
+ HPEN hPen, hPenOld;
+ POINT pt;
+
+ hPen = CreatePen(PS_SOLID, 2, GetSysColor(COLOR_WINDOWTEXT));
+ hPenOld = (HPEN)SelectObject(dis->hDC, hPen);
+
+ MoveToEx(dis->hDC, dis->rcItem.left, (dis->rcItem.top + dis->rcItem.bottom) / 2, &pt);
+ LineTo(dis->hDC, dis->rcItem.right, (dis->rcItem.top + dis->rcItem.bottom) / 2);
+ SelectObject(dis->hDC, hPenOld);
+ DeleteObject((HGDIOBJ)hPen);
+ }
+ else if(dis->itemID >= 0 && item) {
+ char *szName = item->szName[0] == '{' ? &item->szName[3] : item->szName;
+
+ TextOutA(dis->hDC, dis->rcItem.left, dis->rcItem.top, szName, lstrlenA(szName));
+ }
+ return TRUE;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ POINT pt;
+ RECT rc;
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_ITEMS);
+
+ GetCursorPos(&pt);
+ GetWindowRect(hwndList, &rc);
+ if(PtInRect(&rc, pt)) {
+ int iSelection = (int)TrackPopupMenu(psd->hMenuItems, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+
+ if(iSelection >= ID_EXTBK_FIRST && iSelection <= ID_EXTBK_LAST) {
+ iSelection -= ID_EXTBK_FIRST;
+
+ for(int i = ID_EXTBK_FIRST; i <= ID_EXTBK_LAST; i++) {
+ if(SendMessage(hwndList, LB_GETSEL, i - ID_EXTBK_FIRST, 0) > 0) {
+ int iIndex = SendMessage(hwndList, LB_GETITEMDATA, i - ID_EXTBK_FIRST, 0);
+ iIndex -= ID_EXTBK_FIRST;
+
+ if(iIndex >= 0) {
+ StatusItems[iIndex].ALPHA = StatusItems[iSelection].ALPHA;
+ StatusItems[iIndex].COLOR = StatusItems[iSelection].COLOR;
+ StatusItems[iIndex].COLOR2 = StatusItems[iSelection].COLOR2;
+ StatusItems[iIndex].ALPHA2 = StatusItems[iSelection].ALPHA2;
+ StatusItems[iIndex].CORNER = StatusItems[iSelection].CORNER;
+ StatusItems[iIndex].GRADIENT = StatusItems[iSelection].GRADIENT;
+ StatusItems[iIndex].IGNORED = StatusItems[iSelection].IGNORED;
+ StatusItems[iIndex].imageItem = StatusItems[iSelection].imageItem;
+ StatusItems[iIndex].MARGIN_BOTTOM = StatusItems[iSelection].MARGIN_BOTTOM;
+ StatusItems[iIndex].MARGIN_LEFT = StatusItems[iSelection].MARGIN_LEFT;
+ StatusItems[iIndex].MARGIN_RIGHT = StatusItems[iSelection].MARGIN_RIGHT;
+ StatusItems[iIndex].MARGIN_TOP = StatusItems[iSelection].MARGIN_TOP;
+ StatusItems[iIndex].TEXTCOLOR = StatusItems[iSelection].TEXTCOLOR;
+ StatusItems[iIndex].dwFlags = StatusItems[iSelection].dwFlags;
+ }
+ }
+ }
+ OnListItemsChange(hwndDlg);
+ }
+ }
+ break;
+ }
+ case WM_COMMAND:
+ // this will check if the user changed some actual statusitems values
+ // if yes the flag bChanged will be set to TRUE
+ SetChangedStatusItemFlag(wParam, hwndDlg);
+ switch(LOWORD(wParam)) {
+ case IDC_ITEMS:
+ if (HIWORD(wParam) != LBN_SELCHANGE)
+ return FALSE;
+ {
+ int iItem = SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_ITEMS, LB_GETCURSEL, 0, 0), 0);
+ if(iItem == ID_EXTBKSEPARATOR)
+ return FALSE;
+ }
+ OnListItemsChange(hwndDlg);
+ if(psd->pfnClcOptionsChanged)
+ psd->pfnClcOptionsChanged();
+ break;
+ case IDC_SKIP_UNDERLAY:
+ case IDC_SKIP_IMAGE:
+ case IDC_GRADIENT:
+ case IDC_CORNER:
+ case IDC_IGNORE:
+ ReActiveCombo(hwndDlg);
+ break;
+ }
+ if ((LOWORD(wParam) == IDC_ALPHA || LOWORD(wParam) == IDC_ALPHA2 || LOWORD(wParam) == IDC_MRGN_LEFT || LOWORD(wParam) == IDC_MRGN_BOTTOM || LOWORD(wParam) == IDC_MRGN_TOP || LOWORD(wParam) == IDC_MRGN_RIGHT) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()))
+ return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ // save user made changes
+ SaveLatestChanges(hwndDlg);
+ // save struct to DB
+ if(psd->pfnSaveCompleteStruct)
+ psd->pfnSaveCompleteStruct();
+
+ if(psd->pfnClcOptionsChanged)
+ psd->pfnClcOptionsChanged();
+ if(psd->hwndCLUI) {
+ SendMessage(psd->hwndCLUI, WM_SIZE, 0, 0);
+ PostMessage(psd->hwndCLUI, WM_USER+100, 0, 0); // CLUIINTM_REDRAW
+ }
+ break;
+ }
+ }
+ break;
+ case WM_DESTROY:
+ DestroyMenu(psd->hMenuItems);
+ break;
+ case WM_NCDESTROY:
+ free(psd);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)0);
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ * unimplemented
+*/
+
+static BOOL CALLBACK SkinEdit_ImageItemEditProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return FALSE;
+}
+
+static INT_PTR SkinEdit_FillByCurrentSel(WPARAM wParam, LPARAM lParam)
+{
+ if(wParam)
+ FillOptionDialogByCurrentSel((HWND)wParam);
+ return 0;
+}
+
+/*
+ * service function
+ * creates additional tab pages under the given parent window handle
+ * expects a SKINDESCRIPTON * in lParam
+*/
+
+HWND SkinEdit_Invoke(WPARAM wParam, LPARAM lParam)
+{
+ SKINDESCRIPTION *psd = (SKINDESCRIPTION *)lParam;
+ TCITEM tci = {0};
+ RECT rcClient;
+ int iTabs;
+
+ if(psd->cbSize != sizeof(SKINDESCRIPTION))
+ return 0;
+
+ iTabs = TabCtrl_GetItemCount(psd->hWndTab);
+ GetClientRect(psd->hWndParent, &rcClient);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.lParam = (LPARAM)CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_SKINITEMEDIT), psd->hWndParent, (DLGPROC)SkinEdit_ExtBkDlgProc, (LPARAM)psd);
+
+ tci.pszText = TranslateT("Skin items");
+ TabCtrl_InsertItem(psd->hWndTab, iTabs++, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 65, 1);
+ psd->hwndSkinEdit = (HWND)tci.lParam;
+
+ tci.lParam = (LPARAM)CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_IMAGEITEMEDIT), psd->hWndParent, (DLGPROC)SkinEdit_ImageItemEditProc, (LPARAM)psd);
+ tci.pszText = TranslateT("Image items");
+ TabCtrl_InsertItem(psd->hWndTab, iTabs++, &tci);
+ MoveWindow((HWND)tci.lParam, 5, 25, rcClient.right - 9, rcClient.bottom - 65, 1);
+ psd->hwndImageEdit = (HWND)tci.lParam;
+
+ return(psd->hwndSkinEdit);
+}
diff --git a/plugins/Clist_ng/version.rc b/plugins/Clist_ng/version.rc new file mode 100644 index 0000000000..6d9738da6b --- /dev/null +++ b/plugins/Clist_ng/version.rc @@ -0,0 +1,46 @@ +#define VERSION_STRING "0.1.0.0"
+#define VER_MAJOR 0
+#define VER_MINOR 1
+#define VER_REVISION 0
+#define VER_BUILD 0
+
+
+#if defined(_WIN64)
+ #define RES_FILE_DESC "Clist NG Unicode (x86_amd64)"
+#else
+ #define RES_FILE_DESC "Clist NG Unicode (x86)"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VER_MAJOR,VER_MINOR,VER_REVISION,VER_BUILD
+ PRODUCTVERSION VER_MAJOR,VER_MINOR,VER_REVISION,VER_BUILD
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "Miranda IM project"
+ VALUE "FileDescription", RES_FILE_DESC
+ VALUE "FileVersion", VERSION_STRING
+ VALUE "InternalName", "clist NG"
+ VALUE "LegalCopyright", "Copyright (C) 2004-2010"
+ VALUE "LegalTrademarks", "Licensed under the Gnu general public license V2 or any later version."
+ VALUE "OriginalFilename", "clist_ng.dll"
+ VALUE "ProductName", "Contact list plugin for Miranda IM"
+ VALUE "ProductVersion", VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
|