added license GPL
[winnie] / src / pixmap.cc
1 /*
2 winnie - an experimental window system
3
4 Copyright (C) 2013 Eleni Maria Stea
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 Author: Eleni Maria Stea <elene.mst@gmail.com>
20 */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <errno.h>
25 #include "pixmap.h"
26
27 Pixmap::Pixmap()
28 {
29         width = height = 0;
30         pixels = 0;
31 }
32
33 Pixmap::Pixmap(const Pixmap &pixmap)
34 {
35         width = height = 0;
36         pixels = 0;
37         set_image(pixmap.width, pixmap.height, pixmap.pixels);
38 }
39
40 Pixmap &Pixmap::operator=(const Pixmap &pixmap)
41 {
42         if(this != &pixmap) {
43                 set_image(pixmap.width, pixmap.height, pixmap.pixels);
44         }
45
46         return *this;
47 }
48
49 Pixmap::~Pixmap()
50 {
51         if(pixels) {
52                 delete [] pixels;
53         }
54 }
55
56 int Pixmap::get_width() const
57 {
58         return width;
59 }
60
61 int Pixmap::get_height() const
62 {
63         return height;
64 }
65
66 Rect Pixmap::get_rect() const
67 {
68         Rect rect(0, 0, width, height);
69         return rect;
70 }
71
72 bool Pixmap::set_image(int x, int y, unsigned char *pix)
73 {
74         delete [] pixels;
75
76         pixels = new unsigned char[x * y * 4];
77         width = x;
78         height = y;
79
80         if(pix) {
81                 memcpy(pixels, pix, x * y * 4);
82         }
83         return true;
84 }
85
86 const unsigned char *Pixmap::get_image() const
87 {
88         return pixels;
89 }
90
91 unsigned char *Pixmap::get_image()
92 {
93         return pixels;
94 }
95
96 bool Pixmap::load(const char *fname)
97 {
98         FILE *fp;
99         int hdrline = 0;
100
101         if(!(fp = fopen(fname, "rb"))) {
102                 fprintf(stderr, "failed to open pixmap: %s: %s\n", fname, strerror(errno));
103                 return false;
104         }
105
106         /* read ppm header */
107         while(hdrline < 3) {
108                 char buf[64];
109
110                 if(!fgets(buf, sizeof buf, fp))
111                         goto err;
112                 
113                 /* skip comments */
114                 if(buf[0] == '#')
115                         continue;
116
117                 switch(hdrline++) {
118                 case 0:
119                         /* first header line should be P6 */
120                         if(strcmp(buf, "P6\n") != 0)
121                                 goto err;
122                         break;
123
124                 case 1:
125                         /* second header line contains the pixmap dimensions */
126                         if(sscanf(buf, "%d %d", &width, &height) != 2)
127                                 goto err;
128                         break;
129                 }
130         }
131
132         set_image(width, height, 0);
133
134         for(int i=0; i<width * height * 4; i++) {
135                 int c;
136                 if(i % 4 != 3) {
137                         c = fgetc(fp);
138                         if(c < 0)
139                                 goto err;
140                 }
141                 else {
142                         c = 255;
143                 }
144                 pixels[i] = c;
145         }
146         fclose(fp);
147         return true;
148
149 err:
150         fprintf(stderr, "failed to load pixmap: %s\n", fname);
151         fclose(fp);
152         return false;
153 }
154
155 bool Pixmap::save(const char *fname) const
156 {
157         if(!pixels) {
158                 return false;
159         }
160
161         FILE *fp = fopen(fname, "wb");
162         if(!fp) {
163                 fprintf(stderr, "failed to save pixmap: %s: %s\n", fname, strerror(errno));
164                 return false;
165         }
166
167         fprintf(fp, "P6\n%d %d\n255\n", width, height);
168
169         for(int i=0; i<width * height; i++) {
170                 fputc(pixels[i * 4], fp);
171                 fputc(pixels[i * 4 + 1], fp);
172                 fputc(pixels[i * 4 + 2], fp);
173         }
174
175         fclose(fp);
176         return true;
177 }