Start OLED support for ana-digi
[metawatch.git] / mw_utility.c
1 /*
2  * (c) 2011 Siegen, Germany by Nils Faerber <nils.faerber@kernelconcepts.de>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23
24 #include "mw_utility.h"
25 #include "metawatch.h"
26
27 #include "fonts.h"
28
29 /*
30  * The pixmap buffer has at least one byte per pixel, even for monochrome (bpp=1)
31  * bitmaps
32  */
33 mw_buffer *mw_alloc_pbuffer(unsigned int res_x, unsigned int res_y, unsigned int bpp)
34 {
35         mw_buffer *nmwbuf;
36         int pbuf_size;
37
38         nmwbuf = (mw_buffer *) malloc(sizeof(mw_buffer));
39         if (!nmwbuf)
40                 return NULL;
41
42         nmwbuf->res_x = res_x;
43         nmwbuf->res_y = res_y;
44         nmwbuf->bpp = bpp;
45
46         pbuf_size = nmwbuf->res_x * nmwbuf->res_y * ((nmwbuf->bpp / 8) + 1);
47         nmwbuf->pbuf = malloc(pbuf_size);
48         if (!nmwbuf->pbuf) {
49                 free(nmwbuf);
50                 return NULL;
51         } else {
52                 memset(nmwbuf->pbuf, 0, pbuf_size);
53                 return nmwbuf;
54         }
55 }
56
57 void mw_free_pbuffer(mw_buffer *mwbuf)
58 {
59         if (!mwbuf)
60                 return;
61
62         free(mwbuf->pbuf);
63         free(mwbuf);
64 }
65
66 /*
67  * makes a buffer for sending to the LCD watch from the drawing buffer, e.g.
68  * mw_send_bitmap(mw_fd, MW_SCREEN_MODE_IDLE, 96, 65, 31, bbuf, len);
69  *
70  * NOT reentrant !
71  */
72 unsigned char *mw_make_mw_buffer(mw_buffer *mwbuf, int *buflen)
73 {
74         static unsigned char wbuf[96*12];
75         int x, y;
76         unsigned char clr;
77
78         memset(wbuf, 0, 96*12);
79
80         for (y = 0; y < mwbuf->res_y; y++) {
81                 for (x = 0; x < mwbuf->res_x; x++) {
82                         clr = *(unsigned char *)(mwbuf->pbuf+((y*mwbuf->res_x)+x));
83                         if (clr) {
84                                 *(unsigned char *)(wbuf+((y*12)+(x/8))) |= 1 << (x%8);
85                         };
86                 };
87         };
88         *buflen = mwbuf->res_y * 12;
89
90         return wbuf;
91 }
92
93 unsigned char *mw_make_mw_oled_buffer(mw_buffer *mwbuf, int *buflen)
94 {
95         static unsigned char wbuf[2*80]; /* size of one OLED, two rows */
96         int x, y;
97         unsigned char clr;
98
99         memset(wbuf, 0, 2*80);
100
101         for (x=0; x<mwbuf->res_x; x++) {
102                 for (y=0; y<mwbuf->res_y; y++) {
103                         clr = *(unsigned char *)(mwbuf->pbuf+((y*mwbuf->res_x)+x));
104                         if (clr) {
105                                 *(unsigned char *)(wbuf+(x+80*(y/8))) |= 1 << (7-(y%8));
106                         }
107                 }
108         }
109         *buflen = (mwbuf->res_y / 8) * 80;
110
111         return wbuf;
112 }
113
114 void mw_dump_mw_buffer(mw_buffer *mwbuf)
115 {
116         int x, y;
117         unsigned char clr;
118
119         for (y = 0; y < mwbuf->res_y; y++) {
120                 for (x = 0; x < mwbuf->res_x; x++) {
121                         clr = *(unsigned char *)(mwbuf->pbuf+((y*mwbuf->res_x)+x));
122                         if (clr)
123                                 fprintf(stderr, ".");
124                         else
125                                 fprintf(stderr, " ");
126                 };
127                 fprintf(stderr, "\n");
128         };
129 }
130
131
132 /* clear/fill entire buffer with color */
133 void mw_buf_clear(mw_buffer *mwbuf, mw_color clr)
134 {
135         int pbuf_size;
136
137         if (!mwbuf)
138                 return;
139         if (clr == MW_TRANSPARENT)
140                 return;
141
142         pbuf_size = mwbuf->res_x * mwbuf->res_y * ((mwbuf->bpp / 8) + 1);
143         memset(mwbuf->pbuf, clr, pbuf_size);
144 }
145
146 /* draw a single pixel */
147 void mw_buf_draw_pixel(mw_buffer *mwbuf, unsigned int x, unsigned int y, mw_color clr)
148 {
149         if (!mwbuf)
150                 return;
151         if (clr == MW_TRANSPARENT)
152                 return;
153
154         *(unsigned char *)(mwbuf->pbuf+((y*mwbuf->res_x)+x)) = clr;
155 }
156
157 void mw_buf_print(mw_buffer *mwbuf, unsigned int x, unsigned int y, char *text, unsigned char fsize, mw_color fgclr, mw_color bgclr)
158 {
159         unsigned int  i,j,z;
160         const unsigned char *data, *font_style;
161         unsigned char mask,xme,yme,offset;
162
163         if (text==NULL || strlen(text) == 0)
164                 return;
165
166         switch (fsize) {
167                 case 0:
168                         data = (const unsigned char *)FONT6x8;
169                         font_style = (const unsigned char *)FONT6x8;
170                         break;
171                 case 1:
172                         data = (const unsigned char *)FONT8x8F;
173                         font_style = (const unsigned char *)FONT8x8F;
174                         break;
175                 case 2:
176                         data = (const unsigned char *)FONT8x16;
177                         font_style = (const unsigned char *)FONT8x16;
178                         break;
179                 default:
180                         data = (const unsigned char *)FONT6x8;
181                         font_style = (const unsigned char *)FONT6x8;
182                         break;
183         };
184         xme = *data++;
185         yme = *data++;
186         offset = *data;
187
188         do {
189                 mask = 0x00;
190                 data =  (font_style + offset) + (offset * (int)(*text - 32));
191                 for (i=0; i < yme; i++) {
192                         mask |=0x80;
193                         for (j=x; j < (x + xme); j++) {
194                                 z = y + i;
195                                 if ((z < mwbuf->res_y) && (j < mwbuf->res_x)) {
196                                         if (*data & mask) {
197                                                 mw_buf_draw_pixel(mwbuf, j, z, fgclr);
198                                         } else {
199                                                 mw_buf_draw_pixel(mwbuf, j, z, bgclr);
200                                         }
201                                 }
202                                 mask >>= 1;
203                         }
204                         data++;
205                 }
206                 x += xme;
207                 text++;
208         } while (*text != '\0');
209 }
210
211 void mw_buf_draw_line_bresenham(mw_buffer *mwbuf, unsigned int xstart, unsigned int ystart, unsigned int xend, unsigned int yend, mw_color clr)
212 {
213         int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
214  
215         dx = xend - xstart;
216         dy = yend - ystart;
217  
218         incx = (dx >= 0) ? 1 : -1;
219         incy = (dy >= 0) ? 1 : -1;
220
221         if (dx<0)
222                 dx = -dx;
223         if (dy<0)
224                 dy = -dy;
225  
226         if (dx>dy) {
227                 pdx = incx; pdy = 0;
228                 ddx=incx; ddy=incy;
229                 es =dy;   el =dx;
230         } else {
231                 pdx=0;    pdy=incy;
232                 ddx=incx; ddy=incy;
233                 es =dx;   el =dy;
234         }
235  
236         x = xstart;
237         y = ystart;
238         err = el/2;
239         mw_buf_draw_pixel(mwbuf, x, y, clr);
240  
241         for (t = 0; t < el; ++t) {
242                 err -= es; 
243                 if (err < 0) {
244                         err += el;
245                         x += ddx;
246                         y += ddy;
247                 } else {
248                         x += pdx;
249                         y += pdy;
250                 }
251                 mw_buf_draw_pixel(mwbuf, x, y, clr);
252         }
253 }
254