initial commit, lordsawar source, slightly modified
[lordsawar] / src / PixMask.cpp
1 // Copyright (C) 2009 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
16 //  02110-1301, USA.
17
18 #include "PixMask.h"
19 #include <string.h>
20
21 PixMask::PixMask(Glib::RefPtr<Gdk::Pixbuf> pixbuf)
22      : width(0), height(0)
23 {
24   pixbuf->render_pixmap_and_mask(pixmap, mask, 1);
25   pixmap->get_size(width, height);
26   gc = Gdk::GC::create(pixmap);
27 }
28
29 PixMask::PixMask(Glib::RefPtr<Gdk::Pixmap> p, Glib::RefPtr<Gdk::Bitmap> m)
30     : width(0), height(0)
31 {
32   pixmap = p;
33   mask = m;
34   if (pixmap == true)
35     {
36       pixmap->get_size(width, height);
37       gc = Gdk::GC::create(pixmap);
38     }
39   else if (mask == true)
40     {
41       mask->get_size(width, height);
42       gc = Gdk::GC::create(mask);
43     }
44 }
45
46 PixMask::PixMask(const PixMask&p)
47 {
48   pixmap = 
49     Gdk::Pixmap::create(Glib::RefPtr<Gdk::Drawable>(0), p.width, p.height, 24);
50   gc = Gdk::GC::create(pixmap);
51   pixmap->draw_drawable(gc, p.pixmap, 0, 0, 0, 0, p.width, p.height);
52   int size = p.width * p.height / 8;
53   char *data = (char*)malloc(size);
54   memset(data, 0, size);
55   mask = 
56     Gdk::Bitmap::create(data, p.width, p.height);
57   mask->draw_drawable(Gdk::GC::create(p.mask), p.mask, 0, 0, 0, 0, p.width, p.height);
58   free(data);
59
60   width = p.width;
61   height = p.height;
62 }
63
64 PixMask::PixMask(std::string filename)
65      : width(0), height(0)
66 {
67   Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file(filename);
68   pixbuf->render_pixmap_and_mask(pixmap, mask, 1);
69   pixmap->get_size(width, height);
70   gc = Gdk::GC::create(pixmap);
71 }
72
73
74 PixMask* PixMask::create(std::string filename)
75 {
76   return new PixMask(filename);
77 }
78
79 PixMask* PixMask::create(Glib::RefPtr<Gdk::Pixbuf> pixbuf)
80 {
81   return new PixMask(pixbuf);
82 }
83
84 PixMask* PixMask::create(Glib::RefPtr<Gdk::Pixmap> pixmap, Glib::RefPtr<Gdk::Bitmap> mask)
85 {
86   return new PixMask(pixmap, mask);
87 }
88
89 PixMask* PixMask::copy()
90 {
91   return new PixMask(*this);
92 }
93
94 void PixMask::blit_centered(Glib::RefPtr<Gdk::Pixmap> dest, Vector<int> pos)
95 {
96   blit (dest, pos.x - (width/2), pos.y - (height/2));
97   return;
98 }
99 void PixMask::blit(Glib::RefPtr<Gdk::Pixmap> dest, Vector<int> pos)
100 {
101   blit (dest, pos.x, pos.y);
102   return;
103 }
104 void PixMask::blit(Glib::RefPtr<Gdk::Pixmap> dest, int dest_x, int dest_y)
105 {
106   gc->set_clip_origin(dest_x,dest_y);
107   gc->set_clip_mask(mask);
108   dest->draw_drawable(gc, pixmap, 0, 0, dest_x, dest_y, width, height);
109   gc->set_clip_mask(Glib::RefPtr<Gdk::Bitmap>(0));
110 }
111      
112 void PixMask::blit(Rectangle src, Glib::RefPtr<Gdk::Pixmap> p, Vector<int> dest)
113 {
114   if (src.x + src.w > get_width())
115     return;
116   if (src.y + src.h > get_height())
117     return;
118   //here we cleverly set the clip origin
119   gc->set_clip_origin(dest.x - src.x,dest.y - src.y);
120   gc->set_clip_mask(mask);
121   p->draw_drawable(gc, pixmap, src.x, src.y, dest.x, dest.y, src.w, src.h);
122   gc->set_clip_mask(Glib::RefPtr<Gdk::Bitmap>(0));
123 }
124
125 void PixMask::blit(Vector<int> tile, int ts, Glib::RefPtr<Gdk::Pixmap> pixmap, Vector<int> dest)
126 {
127   Vector<int> src = tile * ts;
128   blit (Rectangle(src.x, src.y, ts, ts), pixmap, dest);
129 }
130
131 void PixMask::scale(PixMask*& p, int xsize, int ysize, Gdk::InterpType interp)
132 {
133   PixMask *scaled = p->scale(xsize, ysize, interp);
134   delete p;
135   p = scaled;
136   return;
137 }
138
139 PixMask * PixMask::scale(int xsize, int ysize, Gdk::InterpType interp)
140 {
141   Glib::RefPtr<Gdk::Pixbuf> pixbuf = to_pixbuf();
142   return PixMask::create(pixbuf->scale_simple(xsize, ysize, interp));
143 }
144 Glib::RefPtr<Gdk::Pixbuf> PixMask::to_pixbuf()
145 {
146   Glib::RefPtr<Gdk::Pixmap> result = Gdk::Pixmap::create(Glib::RefPtr<Gdk::Drawable>(0), width, height, 24);
147   Gdk::Color transparent = Gdk::Color();
148   //fixme: check to see if this colour is already present somehow
149   transparent.set_rgb_p(255.0 /255.0 , 87.0 / 255.0, 204.0/255.0);
150   gc->set_rgb_fg_color(transparent);
151   result->draw_rectangle(gc, true, 0, 0, width, height);
152   blit(result, 0, 0);
153   Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Glib::RefPtr<Gdk::Drawable>(result), 0, 0, width, height);
154   Glib::RefPtr<Gdk::Pixbuf> alphabuf = buf->add_alpha(true, 255, 87, 204);
155   return alphabuf;
156 }
157       
158 void PixMask::draw_pixbuf(Glib::RefPtr<Gdk::Pixbuf> pixbuf, int src_x, int src_y, int dest_x, int dest_y, int width, int height)
159 {
160   pixmap->draw_pixbuf(gc, pixbuf, src_x, src_y, dest_x, dest_y, width, height,
161                       Gdk::RGB_DITHER_NONE, 0, 0);
162 }
163
164 int PixMask::get_depth()
165 {
166   if (pixmap == true)
167     return pixmap->get_depth();
168   else
169     return 0;
170 }
171 PixMask::~PixMask()
172 {
173   pixmap.clear();
174   mask.clear();
175   gc.clear();
176 }