summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/lcd-16bit-common.c78
-rw-r--r--firmware/drivers/lcd-16bit-vert.c110
-rw-r--r--firmware/drivers/lcd-16bit.c107
-rw-r--r--firmware/drivers/lcd-1bit-vert.c121
-rw-r--r--firmware/drivers/lcd-24bit.c186
-rw-r--r--firmware/drivers/lcd-2bit-horz.c144
-rw-r--r--firmware/drivers/lcd-2bit-vert.c145
-rw-r--r--firmware/drivers/lcd-2bit-vi.c145
-rw-r--r--firmware/drivers/lcd-bitmap-common.c110
-rw-r--r--firmware/drivers/lcd-color-common.c16
10 files changed, 214 insertions, 948 deletions
diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c
index 523354d5d2..ad41485dfe 100644
--- a/firmware/drivers/lcd-16bit-common.c
+++ b/firmware/drivers/lcd-16bit-common.c
@@ -133,31 +133,9 @@ void lcd_fillrect(int x, int y, int width, int height)
133 fb_data *dst, *dst_end; 133 fb_data *dst, *dst_end;
134 int len, step; 134 int len, step;
135 135
136 /******************** In viewport clipping **********************/ 136 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, NULL, NULL))
137 /* nothing to draw? */
138 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
139 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
140 return; 137 return;
141 138
142 if (x < 0)
143 {
144 width += x;
145 x = 0;
146 }
147 if (y < 0)
148 {
149 height += y;
150 y = 0;
151 }
152 if (x + width > lcd_current_viewport->width)
153 width = lcd_current_viewport->width - x;
154 if (y + height > lcd_current_viewport->height)
155 height = lcd_current_viewport->height - y;
156
157 /* adjust for viewport */
158 x += lcd_current_viewport->x;
159 y += lcd_current_viewport->y;
160
161 /* drawmode and optimisation */ 139 /* drawmode and optimisation */
162 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) 140 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
163 { 141 {
@@ -235,33 +213,9 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
235 int src_y, int stride, int x, int y, 213 int src_y, int stride, int x, int y,
236 int width, int height) 214 int width, int height)
237{ 215{
238 /******************** Image in viewport clipping **********************/ 216 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
239 /* nothing to draw? */
240 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
241 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
242 return; 217 return;
243 218
244 if (x < 0)
245 {
246 width += x;
247 src_x -= x;
248 x = 0;
249 }
250 if (y < 0)
251 {
252 height += y;
253 src_y -= y;
254 y = 0;
255 }
256 if (x + width > lcd_current_viewport->width)
257 width = lcd_current_viewport->width - x;
258 if (y + height > lcd_current_viewport->height)
259 height = lcd_current_viewport->height - y;
260
261 /* convert to viewport coordinates */
262 x += lcd_current_viewport->x;
263 y += lcd_current_viewport->y;
264
265 /* move starting point */ 219 /* move starting point */
266 src += stride * (src_y >> 3) + src_x; 220 src += stride * (src_y >> 3) + src_x;
267 src_y &= 7; 221 src_y &= 7;
@@ -465,35 +419,13 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
465 fb_data *dst, *dst_row; 419 fb_data *dst, *dst_row;
466 unsigned dmask = 0x00000000; 420 unsigned dmask = 0x00000000;
467 int drmode = lcd_current_viewport->drawmode; 421 int drmode = lcd_current_viewport->drawmode;
468 /* nothing to draw? */ 422
469 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || 423 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
470 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
471 return; 424 return;
425
472 /* initialize blending */ 426 /* initialize blending */
473 BLEND_INIT; 427 BLEND_INIT;
474 428
475 /* clipping */
476 if (x < 0)
477 {
478 width += x;
479 src_x -= x;
480 x = 0;
481 }
482 if (y < 0)
483 {
484 height += y;
485 src_y -= y;
486 y = 0;
487 }
488 if (x + width > lcd_current_viewport->width)
489 width = lcd_current_viewport->width - x;
490 if (y + height > lcd_current_viewport->height)
491 height = lcd_current_viewport->height - y;
492
493 /* adjust for viewport */
494 x += lcd_current_viewport->x;
495 y += lcd_current_viewport->y;
496
497 /* the following drawmode combinations are possible: 429 /* the following drawmode combinations are possible:
498 * 1) COMPLEMENT: just negates the framebuffer contents 430 * 1) COMPLEMENT: just negates the framebuffer contents
499 * 2) BG and BG+backdrop: draws _only_ background pixels with either 431 * 2) BG and BG+backdrop: draws _only_ background pixels with either
diff --git a/firmware/drivers/lcd-16bit-vert.c b/firmware/drivers/lcd-16bit-vert.c
index 166af02791..c721ef6302 100644
--- a/firmware/drivers/lcd-16bit-vert.c
+++ b/firmware/drivers/lcd-16bit-vert.c
@@ -54,46 +54,23 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
54 int stride_image, int stride_src); 54 int stride_image, int stride_src);
55 55
56#include "lcd-color-common.c" 56#include "lcd-color-common.c"
57#include "lcd-16bit-common.c"
58#include "lcd-bitmap-common.c" 57#include "lcd-bitmap-common.c"
58#include "lcd-16bit-common.c"
59 59
60/*** drawing functions ***/ 60/*** drawing functions ***/
61 61
62/* Draw a horizontal line (optimised) */ 62/* Draw a horizontal line (optimised) */
63void lcd_hline(int x1, int x2, int y) 63void lcd_hline(int x1, int x2, int y)
64{ 64{
65 int x;
66 fb_data *dst, *dst_end; 65 fb_data *dst, *dst_end;
67 int stride_dst; 66 int stride_dst;
68 67
69 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; 68 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
70 69
71 /* direction flip */ 70 if (!lcd_clip_viewport_hline(&x1, &x2, &y))
72 if (x2 < x1)
73 {
74 x = x1;
75 x1 = x2;
76 x2 = x;
77 }
78
79 /******************** In viewport clipping **********************/
80 /* nothing to draw? */
81 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) ||
82 (x1 >= lcd_current_viewport->width) ||
83 (x2 < 0))
84 return; 71 return;
85 72
86 if (x1 < 0) 73 dst = FBADDR(x1, y);
87 x1 = 0;
88 if (x2 >= lcd_current_viewport->width)
89 x2 = lcd_current_viewport->width-1;
90
91 /* Adjust x1 and y to viewport */
92 x1 += lcd_current_viewport->x;
93 x2 += lcd_current_viewport->x;
94 y += lcd_current_viewport->y;
95
96 dst = FBADDR(x1 , y );
97 stride_dst = lcd_current_viewport->buffer->stride; 74 stride_dst = lcd_current_viewport->buffer->stride;
98 dst_end = dst + (x2 - x1) * stride_dst; 75 dst_end = dst + (x2 - x1) * stride_dst;
99 76
@@ -108,36 +85,14 @@ void lcd_hline(int x1, int x2, int y)
108/* Draw a vertical line (optimised) */ 85/* Draw a vertical line (optimised) */
109void lcd_vline(int x, int y1, int y2) 86void lcd_vline(int x, int y1, int y2)
110{ 87{
111 int y, height; 88 int height;
112 unsigned bits = 0; 89 unsigned bits = 0;
113 enum fill_opt fillopt = OPT_NONE; 90 enum fill_opt fillopt = OPT_NONE;
114 fb_data *dst, *dst_end; 91 fb_data *dst, *dst_end;
115 92
116 /* direction flip */ 93 if(!lcd_clip_viewport_vline(&x, &y1, &y2))
117 if (y2 < y1)
118 {
119 y = y1;
120 y1 = y2;
121 y2 = y;
122 }
123
124 /******************** In viewport clipping **********************/
125 /* nothing to draw? */
126 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) ||
127 (y1 >= lcd_current_viewport->height) ||
128 (y2 < 0))
129 return; 94 return;
130 95
131 if (y1 < 0)
132 y1 = 0;
133 if (y2 >= lcd_current_viewport->height)
134 y2 = lcd_current_viewport->height-1;
135
136 /* adjust for viewport */
137 x += lcd_current_viewport->x;
138 y1 += lcd_current_viewport->y;
139 y2 += lcd_current_viewport->y;
140
141 height = y2 - y1 + 1; 96 height = y2 - y1 + 1;
142 97
143 /* drawmode and optimisation */ 98 /* drawmode and optimisation */
@@ -194,33 +149,9 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
194{ 149{
195 fb_data *dst; 150 fb_data *dst;
196 int stride_dst; 151 int stride_dst;
197 /******************** Image in viewport clipping **********************/
198 /* nothing to draw? */
199 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
200 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
201 return;
202 152
203 if (x < 0) 153 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
204 { 154 return;
205 width += x;
206 src_x -= x;
207 x = 0;
208 }
209 if (y < 0)
210 {
211 height += y;
212 src_y -= y;
213 y = 0;
214 }
215
216 if (x + width > lcd_current_viewport->width)
217 width = lcd_current_viewport->width - x;
218 if (y + height > lcd_current_viewport->height)
219 height = lcd_current_viewport->height - y;
220
221 /* adjust for viewport */
222 x += lcd_current_viewport->x;
223 y += lcd_current_viewport->y;
224 155
225 src += stride * src_x + src_y; /* move starting point */ 156 src += stride * src_x + src_y; /* move starting point */
226 dst = FBADDR(x, y); 157 dst = FBADDR(x, y);
@@ -244,34 +175,9 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
244 fb_data *dst, *dst_end; 175 fb_data *dst, *dst_end;
245 int stride_dst; 176 int stride_dst;
246 177
247 /******************** Image in viewport clipping **********************/ 178 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
248 /* nothing to draw? */
249 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
250 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
251 return; 179 return;
252 180
253 if (x < 0)
254 {
255 width += x;
256 src_x -= x;
257 x = 0;
258 }
259 if (y < 0)
260 {
261 height += y;
262 src_y -= y;
263 y = 0;
264 }
265
266 if (x + width > lcd_current_viewport->width)
267 width = lcd_current_viewport->width - x;
268 if (y + height > lcd_current_viewport->height)
269 height = lcd_current_viewport->height - y;
270
271 /* adjust for viewport */
272 x += lcd_current_viewport->x;
273 y += lcd_current_viewport->y;
274
275 src += stride * src_x + src_y; /* move starting point */ 181 src += stride * src_x + src_y; /* move starting point */
276 dst = FBADDR(x, y); 182 dst = FBADDR(x, y);
277 stride_dst = lcd_current_viewport->buffer->stride; 183 stride_dst = lcd_current_viewport->buffer->stride;
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index 6dff6f3b50..fd032c0956 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -62,36 +62,14 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
62/* Draw a horizontal line (optimised) */ 62/* Draw a horizontal line (optimised) */
63void lcd_hline(int x1, int x2, int y) 63void lcd_hline(int x1, int x2, int y)
64{ 64{
65 int x, width; 65 int width;
66 unsigned bits = 0; 66 unsigned bits = 0;
67 enum fill_opt fillopt = OPT_NONE; 67 enum fill_opt fillopt = OPT_NONE;
68 fb_data *dst, *dst_end; 68 fb_data *dst, *dst_end;
69 69
70 /* direction flip */ 70 if (!lcd_clip_viewport_hline(&x1, &x2, &y))
71 if (x2 < x1)
72 {
73 x = x1;
74 x1 = x2;
75 x2 = x;
76 }
77
78 /******************** In viewport clipping **********************/
79 /* nothing to draw? */
80 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) ||
81 (x1 >= lcd_current_viewport->width) ||
82 (x2 < 0))
83 return; 71 return;
84 72
85 if (x1 < 0)
86 x1 = 0;
87 if (x2 >= lcd_current_viewport->width)
88 x2 = lcd_current_viewport->width-1;
89
90 /* Adjust x1 and y to viewport */
91 x1 += lcd_current_viewport->x;
92 x2 += lcd_current_viewport->x;
93 y += lcd_current_viewport->y;
94
95 width = x2 - x1 + 1; 73 width = x2 - x1 + 1;
96 74
97 /* drawmode and optimisation */ 75 /* drawmode and optimisation */
@@ -144,37 +122,14 @@ void lcd_hline(int x1, int x2, int y)
144/* Draw a vertical line (optimised) */ 122/* Draw a vertical line (optimised) */
145void lcd_vline(int x, int y1, int y2) 123void lcd_vline(int x, int y1, int y2)
146{ 124{
147 int y;
148 fb_data *dst, *dst_end; 125 fb_data *dst, *dst_end;
149 int stride_dst; 126 int stride_dst;
150 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; 127 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
151 128
152 /* direction flip */ 129 if (!lcd_clip_viewport_vline(&x, &y1, &y2))
153 if (y2 < y1)
154 {
155 y = y1;
156 y1 = y2;
157 y2 = y;
158 }
159
160 /******************** In viewport clipping **********************/
161 /* nothing to draw? */
162 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) ||
163 (y1 >= lcd_current_viewport->height) ||
164 (y2 < 0))
165 return; 130 return;
166 131
167 if (y1 < 0) 132 dst = FBADDR(x, y1);
168 y1 = 0;
169 if (y2 >= lcd_current_viewport->height)
170 y2 = lcd_current_viewport->height-1;
171
172 /* adjust for viewport */
173 x += lcd_current_viewport->x;
174 y1 += lcd_current_viewport->y;
175 y2 += lcd_current_viewport->y;
176
177 dst = FBADDR(x , y1);
178 stride_dst = lcd_current_viewport->buffer->stride; 133 stride_dst = lcd_current_viewport->buffer->stride;
179 dst_end = dst + (y2 - y1) * stride_dst; 134 dst_end = dst + (y2 - y1) * stride_dst;
180 135
@@ -194,34 +149,9 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
194 fb_data *dst; 149 fb_data *dst;
195 int stride_dst; 150 int stride_dst;
196 151
197 /******************** Image in viewport clipping **********************/ 152 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
198 /* nothing to draw? */
199 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
200 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
201 return; 153 return;
202 154
203 if (x < 0)
204 {
205 width += x;
206 src_x -= x;
207 x = 0;
208 }
209 if (y < 0)
210 {
211 height += y;
212 src_y -= y;
213 y = 0;
214 }
215
216 if (x + width > lcd_current_viewport->width)
217 width = lcd_current_viewport->width - x;
218 if (y + height > lcd_current_viewport->height)
219 height = lcd_current_viewport->height - y;
220
221 /* adjust for viewport */
222 x += lcd_current_viewport->x;
223 y += lcd_current_viewport->y;
224
225 src += stride * src_y + src_x; /* move starting point */ 155 src += stride * src_y + src_x; /* move starting point */
226 dst = FBADDR(x, y); 156 dst = FBADDR(x, y);
227 stride_dst = lcd_current_viewport->buffer->stride; 157 stride_dst = lcd_current_viewport->buffer->stride;
@@ -244,34 +174,9 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
244 unsigned fg = lcd_current_viewport->fg_pattern; 174 unsigned fg = lcd_current_viewport->fg_pattern;
245 int stride_dst = lcd_current_viewport->buffer->stride; 175 int stride_dst = lcd_current_viewport->buffer->stride;
246 176
247 /******************** Image in viewport clipping **********************/ 177 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
248 /* nothing to draw? */
249 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
250 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
251 return; 178 return;
252 179
253 if (x < 0)
254 {
255 width += x;
256 src_x -= x;
257 x = 0;
258 }
259 if (y < 0)
260 {
261 height += y;
262 src_y -= y;
263 y = 0;
264 }
265
266 if (x + width > lcd_current_viewport->width)
267 width = lcd_current_viewport->width - x;
268 if (y + height > lcd_current_viewport->height)
269 height = lcd_current_viewport->height - y;
270
271 /* adjust for viewport */
272 x += lcd_current_viewport->x;
273 y += lcd_current_viewport->y;
274
275 src += stride * src_y + src_x; /* move starting point */ 180 src += stride * src_y + src_x; /* move starting point */
276 dst = FBADDR(x, y); 181 dst = FBADDR(x, y);
277 182
diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c
index 49c15c041e..e1b65ca9c0 100644
--- a/firmware/drivers/lcd-1bit-vert.c
+++ b/firmware/drivers/lcd-1bit-vert.c
@@ -92,6 +92,8 @@ static void *LCDFN(frameaddress_default)(int x, int y)
92 return fb->FBFN(ptr) + element;/*(element % fb->elems);*/ 92 return fb->FBFN(ptr) + element;/*(element % fb->elems);*/
93} 93}
94 94
95#include "lcd-bitmap-common.c"
96
95/* LCD init */ 97/* LCD init */
96void LCDFN(init)(void) 98void LCDFN(init)(void)
97{ 99{
@@ -272,10 +274,8 @@ void LCDFN(clear_viewport)(void)
272/* Set a single pixel */ 274/* Set a single pixel */
273void LCDFN(drawpixel)(int x, int y) 275void LCDFN(drawpixel)(int x, int y)
274{ 276{
275 if ( ((unsigned)x < (unsigned)CURRENT_VP->width) 277 if (LCDFN(clip_viewport_pixel)(&x, &y))
276 && ((unsigned)y < (unsigned)CURRENT_VP->height) 278 LCDFN(pixelfuncs)[CURRENT_VP->drawmode](x, y);
277 )
278 LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x + x, CURRENT_VP->y + y);
279} 279}
280 280
281/* Draw a line */ 281/* Draw a line */
@@ -287,6 +287,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
287 int d, dinc1, dinc2; 287 int d, dinc1, dinc2;
288 int x, xinc1, xinc2; 288 int x, xinc1, xinc2;
289 int y, yinc1, yinc2; 289 int y, yinc1, yinc2;
290 int x_vp, y_vp, w_vp, h_vp;
290 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode]; 291 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode];
291 292
292 deltax = abs(x2 - x1); 293 deltax = abs(x2 - x1);
@@ -341,12 +342,15 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
341 x = x1; 342 x = x1;
342 y = y1; 343 y = y1;
343 344
345 x_vp = CURRENT_VP->x;
346 y_vp = CURRENT_VP->y;
347 w_vp = CURRENT_VP->width;
348 h_vp = CURRENT_VP->height;
349
344 for (i = 0; i < numpixels; i++) 350 for (i = 0; i < numpixels; i++)
345 { 351 {
346 if ( ((unsigned)x < (unsigned)CURRENT_VP->width) 352 if (x >= 0 && y >= 0 && x < w_vp && y < h_vp)
347 && ((unsigned)y < (unsigned)CURRENT_VP->height) 353 pfunc(x + x_vp, y + y_vp);
348 )
349 pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y);
350 354
351 if (d < 0) 355 if (d < 0)
352 { 356 {
@@ -366,35 +370,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
366/* Draw a horizontal line (optimised) */ 370/* Draw a horizontal line (optimised) */
367void LCDFN(hline)(int x1, int x2, int y) 371void LCDFN(hline)(int x1, int x2, int y)
368{ 372{
369 int x, width; 373 int width;
370 unsigned char *dst, *dst_end; 374 unsigned char *dst, *dst_end;
371 unsigned mask; 375 unsigned mask;
372 LCDFN(blockfunc_type) *bfunc; 376 LCDFN(blockfunc_type) *bfunc;
373 377
374 /* direction flip */ 378 if (!LCDFN(clip_viewport_hline)(&x1, &x2, &y))
375 if (x2 < x1)
376 {
377 x = x1;
378 x1 = x2;
379 x2 = x;
380 }
381
382 /******************** In viewport clipping **********************/
383 /* nothing to draw? */
384 if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width)
385 || (x2 < 0))
386 return; 379 return;
387 380
388 if (x1 < 0)
389 x1 = 0;
390 if (x2 >= CURRENT_VP->width)
391 x2 = CURRENT_VP->width-1;
392
393 /* adjust to viewport */
394 x1 += CURRENT_VP->x;
395 x2 += CURRENT_VP->x;
396 y += CURRENT_VP->y;
397
398 width = x2 - x1 + 1; 381 width = x2 - x1 + 1;
399 382
400 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; 383 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
@@ -416,30 +399,9 @@ void LCDFN(vline)(int x, int y1, int y2)
416 unsigned mask, mask_bottom; 399 unsigned mask, mask_bottom;
417 LCDFN(blockfunc_type) *bfunc; 400 LCDFN(blockfunc_type) *bfunc;
418 401
419 /* direction flip */ 402 if (!LCDFN(clip_viewport_vline)(&x, &y1, &y2))
420 if (y2 < y1)
421 {
422 ny = y1;
423 y1 = y2;
424 y2 = ny;
425 }
426
427 /******************** In viewport clipping **********************/
428 /* nothing to draw? */
429 if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height)
430 || (y2 < 0))
431 return; 403 return;
432 404
433 if (y1 < 0)
434 y1 = 0;
435 if (y2 >= CURRENT_VP->height)
436 y2 = CURRENT_VP->height-1;
437
438 /* adjust for viewport */
439 y1 += CURRENT_VP->y;
440 y2 += CURRENT_VP->y;
441 x += CURRENT_VP->x;
442
443 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; 405 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
444 dst = LCDFB(x,y1>>3); 406 dst = LCDFB(x,y1>>3);
445 ny = y2 - (y1 & ~7); 407 ny = y2 - (y1 & ~7);
@@ -483,31 +445,9 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
483 LCDFN(blockfunc_type) *bfunc; 445 LCDFN(blockfunc_type) *bfunc;
484 bool fillopt = false; 446 bool fillopt = false;
485 447
486 /******************** In viewport clipping **********************/ 448 if (!LCDFN(clip_viewport_rect)(&x, &y, &width, &height, NULL, NULL))
487 /* nothing to draw? */
488 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
489 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
490 return; 449 return;
491 450
492 if (x < 0)
493 {
494 width += x;
495 x = 0;
496 }
497 if (y < 0)
498 {
499 height += y;
500 y = 0;
501 }
502 if (x + width > CURRENT_VP->width)
503 width = CURRENT_VP->width - x;
504 if (y + height > CURRENT_VP->height)
505 height = CURRENT_VP->height - y;
506
507 /* adjust for viewport */
508 x += CURRENT_VP->x;
509 y += CURRENT_VP->y;
510
511 if (CURRENT_VP->drawmode & DRMODE_INVERSEVID) 451 if (CURRENT_VP->drawmode & DRMODE_INVERSEVID)
512 { 452 {
513 if (CURRENT_VP->drawmode & DRMODE_BG) 453 if (CURRENT_VP->drawmode & DRMODE_BG)
@@ -582,34 +522,9 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
582 unsigned mask, mask_bottom; 522 unsigned mask, mask_bottom;
583 LCDFN(blockfunc_type) *bfunc; 523 LCDFN(blockfunc_type) *bfunc;
584 524
585 /******************** Image in viewport clipping **********************/ 525 if (!LCDFN(clip_viewport_rect)(&x, &y, &width, &height, &src_x, &src_y))
586 /* nothing to draw? */
587 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
588 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
589 return; 526 return;
590 527
591 /* clip image in viewport */
592 if (x < 0)
593 {
594 width += x;
595 src_x -= x;
596 x = 0;
597 }
598 if (y < 0)
599 {
600 height += y;
601 src_y -= y;
602 y = 0;
603 }
604 if (x + width > CURRENT_VP->width)
605 width = CURRENT_VP->width - x;
606 if (y + height > CURRENT_VP->height)
607 height = CURRENT_VP->height - y;
608
609 /* adjust for viewport */
610 x += CURRENT_VP->x;
611 y += CURRENT_VP->y;
612
613 src += stride * (src_y >> 3) + src_x; /* move starting point */ 528 src += stride * (src_y >> 3) + src_x; /* move starting point */
614 src_y &= 7; 529 src_y &= 7;
615 y -= src_y; 530 y -= src_y;
@@ -696,5 +611,3 @@ void LCDFN(bitmap)(const unsigned char *src, int x, int y, int width,
696{ 611{
697 LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height); 612 LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height);
698} 613}
699
700#include "lcd-bitmap-common.c"
diff --git a/firmware/drivers/lcd-24bit.c b/firmware/drivers/lcd-24bit.c
index 279ed5924a..d95415e957 100644
--- a/firmware/drivers/lcd-24bit.c
+++ b/firmware/drivers/lcd-24bit.c
@@ -173,31 +173,9 @@ void lcd_fillrect(int x, int y, int width, int height)
173 fb_data bits; 173 fb_data bits;
174 memset(&bits, 0, sizeof(fb_data)); 174 memset(&bits, 0, sizeof(fb_data));
175 175
176 /******************** In viewport clipping **********************/ 176 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, NULL, NULL))
177 /* nothing to draw? */
178 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
179 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
180 return; 177 return;
181 178
182 if (x < 0)
183 {
184 width += x;
185 x = 0;
186 }
187 if (y < 0)
188 {
189 height += y;
190 y = 0;
191 }
192 if (x + width > lcd_current_viewport->width)
193 width = lcd_current_viewport->width - x;
194 if (y + height > lcd_current_viewport->height)
195 height = lcd_current_viewport->height - y;
196
197 /* adjust for viewport */
198 x += lcd_current_viewport->x;
199 y += lcd_current_viewport->y;
200
201 /* drawmode and optimisation */ 179 /* drawmode and optimisation */
202 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) 180 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
203 { 181 {
@@ -287,33 +265,9 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
287 int drmode = lcd_current_viewport->drawmode; 265 int drmode = lcd_current_viewport->drawmode;
288 int row; 266 int row;
289 267
290 /******************** Image in viewport clipping **********************/ 268 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
291 /* nothing to draw? */
292 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
293 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
294 return; 269 return;
295 270
296 if (x < 0)
297 {
298 width += x;
299 src_x -= x;
300 x = 0;
301 }
302 if (y < 0)
303 {
304 height += y;
305 src_y -= y;
306 y = 0;
307 }
308 if (x + width > lcd_current_viewport->width)
309 width = lcd_current_viewport->width - x;
310 if (y + height > lcd_current_viewport->height)
311 height = lcd_current_viewport->height - y;
312
313 /* adjust for viewport */
314 x += lcd_current_viewport->x;
315 y += lcd_current_viewport->y;
316
317 src += stride * (src_y >> 3) + src_x; /* move starting point */ 271 src += stride * (src_y >> 3) + src_x; /* move starting point */
318 src_y &= 7; 272 src_y &= 7;
319 src_end = src + width; 273 src_end = src + width;
@@ -491,32 +445,9 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
491 fb_data *dst, *dst_row; 445 fb_data *dst, *dst_row;
492 unsigned dmask = 0x00000000; 446 unsigned dmask = 0x00000000;
493 int drmode = lcd_current_viewport->drawmode; 447 int drmode = lcd_current_viewport->drawmode;
494 /* nothing to draw? */
495 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
496 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
497 return;
498 448
499 /* clipping */ 449 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
500 if (x < 0) 450 return;
501 {
502 width += x;
503 src_x -= x;
504 x = 0;
505 }
506 if (y < 0)
507 {
508 height += y;
509 src_y -= y;
510 y = 0;
511 }
512 if (x + width > lcd_current_viewport->width)
513 width = lcd_current_viewport->width - x;
514 if (y + height > lcd_current_viewport->height)
515 height = lcd_current_viewport->height - y;
516
517 /* adjust for viewport */
518 x += lcd_current_viewport->x;
519 y += lcd_current_viewport->y;
520 451
521 /* the following drawmode combinations are possible: 452 /* the following drawmode combinations are possible:
522 * 1) COMPLEMENT: just negates the framebuffer contents 453 * 1) COMPLEMENT: just negates the framebuffer contents
@@ -758,38 +689,16 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
758/* Draw a horizontal line (optimised) */ 689/* Draw a horizontal line (optimised) */
759void lcd_hline(int x1, int x2, int y) 690void lcd_hline(int x1, int x2, int y)
760{ 691{
761 int x, width; 692 int width;
762 fb_data *dst, *dst_end; 693 fb_data *dst, *dst_end;
763 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; 694 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
764 695
765 /* direction flip */ 696 if (!lcd_clip_viewport_hline(&x1, &x2, &y))
766 if (x2 < x1)
767 {
768 x = x1;
769 x1 = x2;
770 x2 = x;
771 }
772
773 /******************** In viewport clipping **********************/
774 /* nothing to draw? */
775 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) ||
776 (x1 >= lcd_current_viewport->width) ||
777 (x2 < 0))
778 return; 697 return;
779 698
780 if (x1 < 0)
781 x1 = 0;
782 if (x2 >= lcd_current_viewport->width)
783 x2 = lcd_current_viewport->width-1;
784
785 /* Adjust x1 and y to viewport */
786 x1 += lcd_current_viewport->x;
787 x2 += lcd_current_viewport->x;
788 y += lcd_current_viewport->y;
789
790 width = x2 - x1 + 1; 699 width = x2 - x1 + 1;
791 700
792 dst = FBADDR(x1 , y); 701 dst = FBADDR(x1, y);
793 dst_end = dst + width; 702 dst_end = dst + width;
794 do 703 do
795 { 704 {
@@ -801,36 +710,13 @@ void lcd_hline(int x1, int x2, int y)
801/* Draw a vertical line (optimised) */ 710/* Draw a vertical line (optimised) */
802void lcd_vline(int x, int y1, int y2) 711void lcd_vline(int x, int y1, int y2)
803{ 712{
804 int y;
805 fb_data *dst, *dst_end; 713 fb_data *dst, *dst_end;
806 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; 714 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
807 715
808 /* direction flip */ 716 if (!lcd_clip_viewport_vline(&x, &y1, &y2))
809 if (y2 < y1)
810 {
811 y = y1;
812 y1 = y2;
813 y2 = y;
814 }
815
816 /******************** In viewport clipping **********************/
817 /* nothing to draw? */
818 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) ||
819 (y1 >= lcd_current_viewport->height) ||
820 (y2 < 0))
821 return; 717 return;
822 718
823 if (y1 < 0) 719 dst = FBADDR(x, y1);
824 y1 = 0;
825 if (y2 >= lcd_current_viewport->height)
826 y2 = lcd_current_viewport->height-1;
827
828 /* adjust for viewport */
829 x += lcd_current_viewport->x;
830 y1 += lcd_current_viewport->y;
831 y2 += lcd_current_viewport->y;
832
833 dst = FBADDR(x , y1);
834 dst_end = dst + (y2 - y1) * LCD_WIDTH; 720 dst_end = dst + (y2 - y1) * LCD_WIDTH;
835 721
836 do 722 do
@@ -848,34 +734,9 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
848{ 734{
849 fb_data *dst; 735 fb_data *dst;
850 736
851 /******************** Image in viewport clipping **********************/ 737 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
852 /* nothing to draw? */
853 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
854 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
855 return; 738 return;
856 739
857 if (x < 0)
858 {
859 width += x;
860 src_x -= x;
861 x = 0;
862 }
863 if (y < 0)
864 {
865 height += y;
866 src_y -= y;
867 y = 0;
868 }
869
870 if (x + width > lcd_current_viewport->width)
871 width = lcd_current_viewport->width - x;
872 if (y + height > lcd_current_viewport->height)
873 height = lcd_current_viewport->height - y;
874
875 /* adjust for viewport */
876 x += lcd_current_viewport->x;
877 y += lcd_current_viewport->y;
878
879 src += stride * src_y + src_x; /* move starting point */ 740 src += stride * src_y + src_x; /* move starting point */
880 dst = FBADDR(x, y); 741 dst = FBADDR(x, y);
881 742
@@ -896,34 +757,9 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
896 fb_data *dst; 757 fb_data *dst;
897 fb_data fg, transparent, replacewithfg; 758 fb_data fg, transparent, replacewithfg;
898 759
899 /******************** Image in viewport clipping **********************/ 760 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
900 /* nothing to draw? */
901 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
902 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
903 return; 761 return;
904 762
905 if (x < 0)
906 {
907 width += x;
908 src_x -= x;
909 x = 0;
910 }
911 if (y < 0)
912 {
913 height += y;
914 src_y -= y;
915 y = 0;
916 }
917
918 if (x + width > lcd_current_viewport->width)
919 width = lcd_current_viewport->width - x;
920 if (y + height > lcd_current_viewport->height)
921 height = lcd_current_viewport->height - y;
922
923 /* adjust for viewport */
924 x += lcd_current_viewport->x;
925 y += lcd_current_viewport->y;
926
927 src += stride * src_y + src_x; /* move starting point */ 763 src += stride * src_y + src_x; /* move starting point */
928 dst = FBADDR(x, y); 764 dst = FBADDR(x, y);
929 765
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c
index 1bc489247c..37125679ad 100644
--- a/firmware/drivers/lcd-2bit-horz.c
+++ b/firmware/drivers/lcd-2bit-horz.c
@@ -89,6 +89,8 @@ static void *lcd_frameaddress_default(int x, int y)
89 return fb->fb_ptr + element;/*(element % fb->elems);*/ 89 return fb->fb_ptr + element;/*(element % fb->elems);*/
90} 90}
91 91
92#include "lcd-bitmap-common.c"
93
92/* LCD init */ 94/* LCD init */
93void lcd_init(void) 95void lcd_init(void)
94{ 96{
@@ -418,10 +420,8 @@ void lcd_clear_viewport(void)
418/* Set a single pixel */ 420/* Set a single pixel */
419void lcd_drawpixel(int x, int y) 421void lcd_drawpixel(int x, int y)
420{ 422{
421 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) 423 if (lcd_clip_viewport_pixel(&x, &y))
422 && ((unsigned)y < (unsigned)lcd_current_viewport->height) 424 lcd_pixelfuncs[lcd_current_viewport->drawmode](x, y);
423 )
424 lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y);
425} 425}
426 426
427/* Draw a line */ 427/* Draw a line */
@@ -433,6 +433,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
433 int d, dinc1, dinc2; 433 int d, dinc1, dinc2;
434 int x, xinc1, xinc2; 434 int x, xinc1, xinc2;
435 int y, yinc1, yinc2; 435 int y, yinc1, yinc2;
436 int x_vp, y_vp, w_vp, h_vp;
436 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode]; 437 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode];
437 438
438 deltay = abs(y2 - y1); 439 deltay = abs(y2 - y1);
@@ -487,12 +488,15 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
487 x = x1; 488 x = x1;
488 y = y1; 489 y = y1;
489 490
491 x_vp = lcd_current_viewport->x;
492 y_vp = lcd_current_viewport->y;
493 w_vp = lcd_current_viewport->width;
494 h_vp = lcd_current_viewport->height;
495
490 for (i = 0; i < numpixels; i++) 496 for (i = 0; i < numpixels; i++)
491 { 497 {
492 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) 498 if (x >= 0 && y >= 0 && x < w_vp && y < h_vp)
493 && ((unsigned)y < (unsigned)lcd_current_viewport->height) 499 pfunc(x + x_vp, y + y_vp);
494 )
495 pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y);
496 500
497 if (d < 0) 501 if (d < 0)
498 { 502 {
@@ -517,30 +521,9 @@ void lcd_hline(int x1, int x2, int y)
517 unsigned mask, mask_right; 521 unsigned mask, mask_right;
518 lcd_blockfunc_type *bfunc; 522 lcd_blockfunc_type *bfunc;
519 523
520 /* direction flip */ 524 if (!lcd_clip_viewport_hline(&x1, &x2, &y))
521 if (x2 < x1)
522 {
523 nx = x1;
524 x1 = x2;
525 x2 = nx;
526 }
527
528 /******************** In viewport clipping **********************/
529 /* nothing to draw? */
530 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width)
531 || (x2 < 0))
532 return; 525 return;
533 526
534 if (x1 < 0)
535 x1 = 0;
536 if (x2 >= lcd_current_viewport->width)
537 x2 = lcd_current_viewport->width-1;
538
539 /* adjust to viewport */
540 x1 += lcd_current_viewport->x;
541 x2 += lcd_current_viewport->x;
542 y += lcd_current_viewport->y;
543
544 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; 527 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
545 dst = FBADDR(x1>>2,y); 528 dst = FBADDR(x1>>2,y);
546 nx = x2 - (x1 & ~3); 529 nx = x2 - (x1 & ~3);
@@ -559,36 +542,14 @@ void lcd_hline(int x1, int x2, int y)
559/* Draw a vertical line (optimised) */ 542/* Draw a vertical line (optimised) */
560void lcd_vline(int x, int y1, int y2) 543void lcd_vline(int x, int y1, int y2)
561{ 544{
562 int y;
563 unsigned char *dst, *dst_end; 545 unsigned char *dst, *dst_end;
564 int stride_dst; 546 int stride_dst;
565 unsigned mask; 547 unsigned mask;
566 lcd_blockfunc_type *bfunc; 548 lcd_blockfunc_type *bfunc;
567 549
568 /* direction flip */ 550 if (!lcd_clip_viewport_vline(&x, &y1, &y2))
569 if (y2 < y1)
570 {
571 y = y1;
572 y1 = y2;
573 y2 = y;
574 }
575
576 /******************** In viewport clipping **********************/
577 /* nothing to draw? */
578 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height)
579 || (y2 < 0))
580 return; 551 return;
581 552
582 if (y1 < 0)
583 y1 = 0;
584 if (y2 >= lcd_current_viewport->height)
585 y2 = lcd_current_viewport->height-1;
586
587 /* adjust for viewport */
588 y1 += lcd_current_viewport->y;
589 y2 += lcd_current_viewport->y;
590 x += lcd_current_viewport->x;
591
592 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; 553 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
593 dst = FBADDR(x>>2,y1); 554 dst = FBADDR(x>>2,y1);
594 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); 555 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0);
@@ -627,31 +588,9 @@ void lcd_fillrect(int x, int y, int width, int height)
627 unsigned mask, mask_right; 588 unsigned mask, mask_right;
628 lcd_blockfunc_type *bfunc; 589 lcd_blockfunc_type *bfunc;
629 590
630 /******************** In viewport clipping **********************/ 591 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, NULL, NULL))
631 /* nothing to draw? */
632 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || (y >= lcd_current_viewport->height)
633 || (x + width <= 0) || (y + height <= 0))
634 return; 592 return;
635 593
636 if (x < 0)
637 {
638 width += x;
639 x = 0;
640 }
641 if (y < 0)
642 {
643 height += y;
644 y = 0;
645 }
646 if (x + width > lcd_current_viewport->width)
647 width = lcd_current_viewport->width - x;
648 if (y + height > lcd_current_viewport->height)
649 height = lcd_current_viewport->height - y;
650
651 /* adjust for viewport */
652 x += lcd_current_viewport->x;
653 y += lcd_current_viewport->y;
654
655 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; 594 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
656 dst = FBADDR(x>>2,y); 595 dst = FBADDR(x>>2,y);
657 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); 596 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0);
@@ -706,32 +645,9 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
706 unsigned dst_mask; 645 unsigned dst_mask;
707 int drmode = lcd_current_viewport->drawmode; 646 int drmode = lcd_current_viewport->drawmode;
708 647
709 /******************** Image in viewport clipping **********************/ 648 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
710 /* nothing to draw? */
711 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
712 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
713 return; 649 return;
714 650
715 if (x < 0)
716 {
717 width += x;
718 src_x -= x;
719 x = 0;
720 }
721 if (y < 0)
722 {
723 height += y;
724 src_y -= y;
725 y = 0;
726 }
727 if (x + width > lcd_current_viewport->width)
728 width = lcd_current_viewport->width - x;
729 if (y + height > lcd_current_viewport->height)
730 height = lcd_current_viewport->height - y;
731
732 x += lcd_current_viewport->x; /* adjust for viewport */
733 y += lcd_current_viewport->y; /* adjust for viewport */
734
735 src += stride * (src_y >> 3) + src_x; /* move starting point */ 651 src += stride * (src_y >> 3) + src_x; /* move starting point */
736 src_y &= 7; 652 src_y &= 7;
737 src_end = src + width; 653 src_end = src + width;
@@ -894,33 +810,9 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x,
894 int stride_dst; 810 int stride_dst;
895 unsigned mask, mask_right; 811 unsigned mask, mask_right;
896 812
897 /******************** Image in viewport clipping **********************/ 813 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
898 /* nothing to draw? */
899 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
900 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
901 return; 814 return;
902 815
903 if (x < 0)
904 {
905 width += x;
906 src_x -= x;
907 x = 0;
908 }
909 if (y < 0)
910 {
911 height += y;
912 src_y -= y;
913 y = 0;
914 }
915 if (x + width > lcd_current_viewport->width)
916 width = lcd_current_viewport->width - x;
917 if (y + height > lcd_current_viewport->height)
918 height = lcd_current_viewport->height - y;
919
920 /* adjust for viewport */
921 x += lcd_current_viewport->x;
922 y += lcd_current_viewport->y;
923
924 stride = LCD_FBSTRIDE(stride, 0); /* convert to no. of bytes */ 816 stride = LCD_FBSTRIDE(stride, 0); /* convert to no. of bytes */
925 817
926 src += stride * src_y + (src_x >> 2); /* move starting point */ 818 src += stride * src_y + (src_x >> 2); /* move starting point */
@@ -971,5 +863,3 @@ void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height)
971{ 863{
972 lcd_bitmap_part(src, 0, 0, width, x, y, width, height); 864 lcd_bitmap_part(src, 0, 0, width, x, y, width, height);
973} 865}
974
975#include "lcd-bitmap-common.c"
diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c
index b206a2d816..5fd86c409a 100644
--- a/firmware/drivers/lcd-2bit-vert.c
+++ b/firmware/drivers/lcd-2bit-vert.c
@@ -91,6 +91,8 @@ static void *lcd_frameaddress_default(int x, int y)
91 return fb->fb_ptr + element; /*(element % fb->elems);*/ 91 return fb->fb_ptr + element; /*(element % fb->elems);*/
92} 92}
93 93
94#include "lcd-bitmap-common.c"
95
94/* LCD init */ 96/* LCD init */
95void lcd_init(void) 97void lcd_init(void)
96{ 98{
@@ -420,10 +422,8 @@ void lcd_clear_viewport(void)
420/* Set a single pixel */ 422/* Set a single pixel */
421void lcd_drawpixel(int x, int y) 423void lcd_drawpixel(int x, int y)
422{ 424{
423 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) 425 if (lcd_clip_viewport_pixel(&x, &y))
424 && ((unsigned)y < (unsigned)lcd_current_viewport->height) 426 lcd_pixelfuncs[lcd_current_viewport->drawmode](x, y);
425 )
426 lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y);
427} 427}
428 428
429/* Draw a line */ 429/* Draw a line */
@@ -435,6 +435,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
435 int d, dinc1, dinc2; 435 int d, dinc1, dinc2;
436 int x, xinc1, xinc2; 436 int x, xinc1, xinc2;
437 int y, yinc1, yinc2; 437 int y, yinc1, yinc2;
438 int x_vp, y_vp, w_vp, h_vp;
438 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode]; 439 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode];
439 440
440 deltax = abs(x2 - x1); 441 deltax = abs(x2 - x1);
@@ -489,12 +490,15 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
489 x = x1; 490 x = x1;
490 y = y1; 491 y = y1;
491 492
493 x_vp = lcd_current_viewport->x;
494 y_vp = lcd_current_viewport->y;
495 w_vp = lcd_current_viewport->width;
496 h_vp = lcd_current_viewport->height;
497
492 for (i = 0; i < numpixels; i++) 498 for (i = 0; i < numpixels; i++)
493 { 499 {
494 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) 500 if (x >= 0 && y >= 0 && x < w_vp && y < h_vp)
495 && ((unsigned)y < (unsigned)lcd_current_viewport->height) 501 pfunc(x + x_vp, y + y_vp);
496 )
497 pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y);
498 502
499 if (d < 0) 503 if (d < 0)
500 { 504 {
@@ -514,36 +518,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
514/* Draw a horizontal line (optimised) */ 518/* Draw a horizontal line (optimised) */
515void lcd_hline(int x1, int x2, int y) 519void lcd_hline(int x1, int x2, int y)
516{ 520{
517 int x;
518 int width; 521 int width;
519 fb_data *dst, *dst_end; 522 fb_data *dst, *dst_end;
520 unsigned mask; 523 unsigned mask;
521 lcd_blockfunc_type *bfunc; 524 lcd_blockfunc_type *bfunc;
522 525
523 /* direction flip */ 526 if (!lcd_clip_viewport_hline(&x1, &x2, &y))
524 if (x2 < x1)
525 {
526 x = x1;
527 x1 = x2;
528 x2 = x;
529 }
530
531 /******************** In viewport clipping **********************/
532 /* nothing to draw? */
533 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width)
534 || (x2 < 0))
535 return; 527 return;
536 528
537 if (x1 < 0)
538 x1 = 0;
539 if (x2 >= lcd_current_viewport->width)
540 x2 = lcd_current_viewport->width-1;
541
542 /* adjust x1 and y to viewport */
543 x1 += lcd_current_viewport->x;
544 x2 += lcd_current_viewport->x;
545 y += lcd_current_viewport->y;
546
547 width = x2 - x1 + 1; 529 width = x2 - x1 + 1;
548 530
549 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; 531 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
@@ -565,30 +547,9 @@ void lcd_vline(int x, int y1, int y2)
565 unsigned mask, mask_bottom; 547 unsigned mask, mask_bottom;
566 lcd_blockfunc_type *bfunc; 548 lcd_blockfunc_type *bfunc;
567 549
568 /* direction flip */ 550 if (!lcd_clip_viewport_vline(&x, &y1, &y2))
569 if (y2 < y1)
570 {
571 ny = y1;
572 y1 = y2;
573 y2 = ny;
574 }
575
576 /******************** In viewport clipping **********************/
577 /* nothing to draw? */
578 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height)
579 || (y2 < 0))
580 return; 551 return;
581 552
582 if (y1 < 0)
583 y1 = 0;
584 if (y2 >= lcd_current_viewport->height)
585 y2 = lcd_current_viewport->height-1;
586
587 /* adjust for viewport */
588 y1 += lcd_current_viewport->y;
589 y2 += lcd_current_viewport->y;
590 x += lcd_current_viewport->x;
591
592 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; 553 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
593 dst = FBADDR(x,y1>>2); 554 dst = FBADDR(x,y1>>2);
594 stride_dst = lcd_current_viewport->buffer->stride; 555 stride_dst = lcd_current_viewport->buffer->stride;
@@ -632,31 +593,9 @@ void lcd_fillrect(int x, int y, int width, int height)
632 lcd_blockfunc_type *bfunc; 593 lcd_blockfunc_type *bfunc;
633 bool fillopt = false; 594 bool fillopt = false;
634 595
635 /******************** In viewport clipping **********************/ 596 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, NULL, NULL))
636 /* nothing to draw? */
637 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width)
638 || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
639 return; 597 return;
640 598
641 if (x < 0)
642 {
643 width += x;
644 x = 0;
645 }
646 if (y < 0)
647 {
648 height += y;
649 y = 0;
650 }
651 if (x + width > lcd_current_viewport->width)
652 width = lcd_current_viewport->width - x;
653 if (y + height > lcd_current_viewport->height)
654 height = lcd_current_viewport->height - y;
655
656 /* adjust for viewport */
657 x += lcd_current_viewport->x;
658 y += lcd_current_viewport->y;
659
660 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) 599 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
661 { 600 {
662 if ((lcd_current_viewport->drawmode & DRMODE_BG) && !lcd_backdrop) 601 if ((lcd_current_viewport->drawmode & DRMODE_BG) && !lcd_backdrop)
@@ -732,33 +671,9 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
732 unsigned mask, mask_bottom; 671 unsigned mask, mask_bottom;
733 lcd_blockfunc_type *bfunc; 672 lcd_blockfunc_type *bfunc;
734 673
735 /******************** Image in viewport clipping **********************/ 674 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
736 /* nothing to draw? */
737 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
738 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
739 return; 675 return;
740 676
741 if (x < 0)
742 {
743 width += x;
744 src_x -= x;
745 x = 0;
746 }
747 if (y < 0)
748 {
749 height += y;
750 src_y -= y;
751 y = 0;
752 }
753 if (x + width > lcd_current_viewport->width)
754 width = lcd_current_viewport->width - x;
755 if (y + height > lcd_current_viewport->height)
756 height = lcd_current_viewport->height - y;
757
758 /* adjust for viewport */
759 x += lcd_current_viewport->x;
760 y += lcd_current_viewport->y;
761
762 src += stride * (src_y >> 3) + src_x; /* move starting point */ 677 src += stride * (src_y >> 3) + src_x; /* move starting point */
763 src_y &= 7; 678 src_y &= 7;
764 y -= src_y; 679 y -= src_y;
@@ -905,33 +820,9 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
905 int stride_dst; 820 int stride_dst;
906 unsigned mask, mask_bottom; 821 unsigned mask, mask_bottom;
907 822
908 /******************** Image in viewport clipping **********************/ 823 if (!lcd_clip_viewport_rect(&x, &y, &width, &height, &src_x, &src_y))
909 /* nothing to draw? */
910 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width)
911 || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
912 return; 824 return;
913 825
914 if (x < 0)
915 {
916 width += x;
917 src_x -= x;
918 x = 0;
919 }
920 if (y < 0)
921 {
922 height += y;
923 src_y -= y;
924 y = 0;
925 }
926 if (x + width > lcd_current_viewport->width)
927 width = lcd_current_viewport->width - x;
928 if (y + height > lcd_current_viewport->height)
929 height = lcd_current_viewport->height - y;
930
931 /* adjust for viewport */
932 x += lcd_current_viewport->x;
933 y += lcd_current_viewport->y;
934
935 src += stride * (src_y >> 2) + src_x; /* move starting point */ 826 src += stride * (src_y >> 2) + src_x; /* move starting point */
936 src_y &= 3; 827 src_y &= 3;
937 y -= src_y; 828 y -= src_y;
@@ -1014,5 +905,3 @@ void lcd_bitmap(const fb_data *src, int x, int y, int width, int height)
1014{ 905{
1015 lcd_bitmap_part(src, 0, 0, width, x, y, width, height); 906 lcd_bitmap_part(src, 0, 0, width, x, y, width, height);
1016} 907}
1017
1018#include "lcd-bitmap-common.c"
diff --git a/firmware/drivers/lcd-2bit-vi.c b/firmware/drivers/lcd-2bit-vi.c
index 0580705a05..b19fdba266 100644
--- a/firmware/drivers/lcd-2bit-vi.c
+++ b/firmware/drivers/lcd-2bit-vi.c
@@ -103,6 +103,8 @@ static void *LCDFN(frameaddress_default)(int x, int y)
103 return fb->FBFN(ptr) + element;/*(element % fb->elems);*/ 103 return fb->FBFN(ptr) + element;/*(element % fb->elems);*/
104} 104}
105 105
106#include "lcd-bitmap-common.c"
107
106/* LCD init */ 108/* LCD init */
107void LCDFN(init)(void) 109void LCDFN(init)(void)
108{ 110{
@@ -453,10 +455,8 @@ void LCDFN(clear_viewport)(void)
453/* Set a single pixel */ 455/* Set a single pixel */
454void LCDFN(drawpixel)(int x, int y) 456void LCDFN(drawpixel)(int x, int y)
455{ 457{
456 if ( ((unsigned)x < (unsigned)CURRENT_VP->width) 458 if (LCDFN(clip_viewport_pixel)(&x, &y))
457 && ((unsigned)y < (unsigned)CURRENT_VP->height) 459 LCDFN(pixelfuncs)[CURRENT_VP->drawmode](x, y);
458 )
459 LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x+x, CURRENT_VP->y+y);
460} 460}
461 461
462/* Draw a line */ 462/* Draw a line */
@@ -468,6 +468,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
468 int d, dinc1, dinc2; 468 int d, dinc1, dinc2;
469 int x, xinc1, xinc2; 469 int x, xinc1, xinc2;
470 int y, yinc1, yinc2; 470 int y, yinc1, yinc2;
471 int x_vp, y_vp, w_vp, h_vp;
471 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode]; 472 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode];
472 473
473 deltax = abs(x2 - x1); 474 deltax = abs(x2 - x1);
@@ -522,12 +523,15 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
522 x = x1; 523 x = x1;
523 y = y1; 524 y = y1;
524 525
526 x_vp = CURRENT_VP->x;
527 y_vp = CURRENT_VP->y;
528 w_vp = CURRENT_VP->width;
529 h_vp = CURRENT_VP->height;
530
525 for (i = 0; i < numpixels; i++) 531 for (i = 0; i < numpixels; i++)
526 { 532 {
527 if ( ((unsigned)x < (unsigned)CURRENT_VP->width) 533 if (x >= 0 && y >= 0 && x < w_vp && y < h_vp)
528 && ((unsigned)y < (unsigned)CURRENT_VP->height) 534 pfunc(x + x_vp, y + y_vp);
529 )
530 pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y);
531 535
532 if (d < 0) 536 if (d < 0)
533 { 537 {
@@ -547,36 +551,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
547/* Draw a horizontal line (optimised) */ 551/* Draw a horizontal line (optimised) */
548void LCDFN(hline)(int x1, int x2, int y) 552void LCDFN(hline)(int x1, int x2, int y)
549{ 553{
550 int x;
551 int width; 554 int width;
552 FBFN(data) *dst, *dst_end; 555 FBFN(data) *dst, *dst_end;
553 unsigned mask; 556 unsigned mask;
554 LCDFN(blockfunc_type) *bfunc; 557 LCDFN(blockfunc_type) *bfunc;
555 558
556 /* direction flip */ 559 if (!LCDFN(clip_viewport_hline)(&x1, &x2, &y))
557 if (x2 < x1)
558 {
559 x = x1;
560 x1 = x2;
561 x2 = x;
562 }
563
564 /******************** In viewport clipping **********************/
565 /* nothing to draw? */
566 if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width)
567 || (x2 < 0))
568 return; 560 return;
569 561
570 if (x1 < 0)
571 x1 = 0;
572 if (x2 >= CURRENT_VP->width)
573 x2 = CURRENT_VP->width-1;
574
575 /* adjust x1 and y to viewport */
576 x1 += CURRENT_VP->x;
577 x2 += CURRENT_VP->x;
578 y += CURRENT_VP->y;
579
580 width = x2 - x1 + 1; 562 width = x2 - x1 + 1;
581 563
582 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; 564 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
@@ -598,30 +580,9 @@ void LCDFN(vline)(int x, int y1, int y2)
598 unsigned mask, mask_bottom; 580 unsigned mask, mask_bottom;
599 LCDFN(blockfunc_type) *bfunc; 581 LCDFN(blockfunc_type) *bfunc;
600 582
601 /* direction flip */ 583 if (!LCDFN(clip_viewport_vline)(&x, &y1, &y2))
602 if (y2 < y1)
603 {
604 ny = y1;
605 y1 = y2;
606 y2 = ny;
607 }
608
609 /******************** In viewport clipping **********************/
610 /* nothing to draw? */
611 if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height)
612 || (y2 < 0))
613 return; 584 return;
614 585
615 if (y1 < 0)
616 y1 = 0;
617 if (y2 >= CURRENT_VP->height)
618 y2 = CURRENT_VP->height-1;
619
620 /* adjust for viewport */
621 y1 += CURRENT_VP->y;
622 y2 += CURRENT_VP->y;
623 x += CURRENT_VP->x;
624
625 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; 586 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
626 dst = LCDFB(x,y1>>3); 587 dst = LCDFB(x,y1>>3);
627 stride_dst = CURRENT_VP->buffer->stride; 588 stride_dst = CURRENT_VP->buffer->stride;
@@ -667,31 +628,9 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
667 LCDFN(blockfunc_type) *bfunc; 628 LCDFN(blockfunc_type) *bfunc;
668 bool fillopt = false; 629 bool fillopt = false;
669 630
670 /******************** In viewport clipping **********************/ 631 if (!LCDFN(clip_viewport_rect)(&x, &y, &width, &height, NULL, NULL))
671 /* nothing to draw? */
672 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
673 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
674 return; 632 return;
675 633
676 if (x < 0)
677 {
678 width += x;
679 x = 0;
680 }
681 if (y < 0)
682 {
683 height += y;
684 y = 0;
685 }
686 if (x + width > CURRENT_VP->width)
687 width = CURRENT_VP->width - x;
688 if (y + height > CURRENT_VP->height)
689 height = CURRENT_VP->height - y;
690
691 /* adjust for viewport */
692 x += CURRENT_VP->x;
693 y += CURRENT_VP->y;
694
695 if (CURRENT_VP->drawmode & DRMODE_INVERSEVID) 634 if (CURRENT_VP->drawmode & DRMODE_INVERSEVID)
696 { 635 {
697 if ((CURRENT_VP->drawmode & DRMODE_BG) && !backdrop) 636 if ((CURRENT_VP->drawmode & DRMODE_BG) && !backdrop)
@@ -769,33 +708,9 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x,
769 unsigned data, mask, mask_bottom; 708 unsigned data, mask, mask_bottom;
770 LCDFN(blockfunc_type) *bfunc; 709 LCDFN(blockfunc_type) *bfunc;
771 710
772 /******************** Image in viewport clipping **********************/ 711 if (!LCDFN(clip_viewport_rect)(&x, &y, &width, &height, &src_x, &src_y))
773 /* nothing to draw? */
774 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) ||
775 (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
776 return; 712 return;
777 713
778 if (x < 0)
779 {
780 width += x;
781 src_x -= x;
782 x = 0;
783 }
784 if (y < 0)
785 {
786 height += y;
787 src_y -= y;
788 y = 0;
789 }
790 if (x + width > CURRENT_VP->width)
791 width = CURRENT_VP->width - x;
792 if (y + height > CURRENT_VP->height)
793 height = CURRENT_VP->height - y;
794
795 /* adjust for viewport */
796 x += CURRENT_VP->x;
797 y += CURRENT_VP->y;
798
799 src += stride * (src_y >> 3) + src_x; /* move starting point */ 714 src += stride * (src_y >> 3) + src_x; /* move starting point */
800 src_y &= 7; 715 src_y &= 7;
801 y -= src_y; 716 y -= src_y;
@@ -913,33 +828,9 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x,
913 int stride_dst; 828 int stride_dst;
914 unsigned mask, mask_bottom; 829 unsigned mask, mask_bottom;
915 830
916 /******************** Image in viewport clipping **********************/ 831 if (!LCDFN(clip_viewport_rect)(&x, &y, &width, &height, &src_x, &src_y))
917 /* nothing to draw? */
918 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
919 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
920 return; 832 return;
921 833
922 if (x < 0)
923 {
924 width += x;
925 src_x -= x;
926 x = 0;
927 }
928 if (y < 0)
929 {
930 height += y;
931 src_y -= y;
932 y = 0;
933 }
934 if (x + width > CURRENT_VP->width)
935 width = CURRENT_VP->width - x;
936 if (y + height > CURRENT_VP->height)
937 height = CURRENT_VP->height - y;
938
939 /* adjust for viewport */
940 x += CURRENT_VP->x;
941 y += CURRENT_VP->y;
942
943 src += stride * (src_y >> 3) + src_x; /* move starting point */ 834 src += stride * (src_y >> 3) + src_x; /* move starting point */
944 src_y &= 7; 835 src_y &= 7;
945 y -= src_y; 836 y -= src_y;
@@ -1036,5 +927,3 @@ void LCDFN(bitmap)(const FBFN(data) *src, int x, int y, int width, int height)
1036{ 927{
1037 LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height); 928 LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height);
1038} 929}
1039
1040#include "lcd-bitmap-common.c"
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c
index 24b302b6d4..c867b214b5 100644
--- a/firmware/drivers/lcd-bitmap-common.c
+++ b/firmware/drivers/lcd-bitmap-common.c
@@ -53,6 +53,116 @@
53extern void viewport_set_buffer(struct viewport *vp, 53extern void viewport_set_buffer(struct viewport *vp,
54 struct frame_buffer_t *buffer, 54 struct frame_buffer_t *buffer,
55 const enum screen_type screen); /* viewport.c */ 55 const enum screen_type screen); /* viewport.c */
56
57/*
58 * In-viewport clipping functions:
59 *
60 * These clip a primitive (pixel, line, rect) given in
61 * viewport-relative coordinates to the current viewport,
62 * and translate it to screen coordinates. They return
63 * false if the resulting primitive would be off-screen.
64 */
65
66static bool LCDFN(clip_viewport_pixel)(int *x, int *y)
67{
68 struct viewport *vp = LCDFN(current_viewport);
69
70 if(*x >= vp->width || *y >= vp->height)
71 return false;
72
73 *x += vp->x;
74 *y += vp->y;
75 return true;
76}
77
78static bool LCDFN(clip_viewport_hline)(int *x1, int *x2, int *y)
79{
80 struct viewport *vp = LCDFN(current_viewport);
81
82 if (*y < 0 || *y > vp->height)
83 return false;
84
85 if (*x2 < *x1) {
86 int tmp = *x2;
87 *x2 = *x1;
88 *x1 = tmp;
89 }
90
91 if (*x1 < 0)
92 *x1 = 0;
93 else if (*x1 >= vp->width)
94 return false;
95
96 if (*x2 < 0)
97 return false;
98 else if (*x2 >= vp->width)
99 *x2 = vp->width - 1;
100
101 *x1 += vp->x;
102 *x2 += vp->x;
103 *y += vp->y;
104 return true;
105}
106
107static bool LCDFN(clip_viewport_vline)(int *x, int *y1, int *y2)
108{
109 struct viewport *vp = LCDFN(current_viewport);
110
111 if (*x < 0 || *x > vp->width)
112 return false;
113
114 if (*y2 < *y1) {
115 int tmp = *y2;
116 *y2 = *y1;
117 *y1 = tmp;
118 }
119
120 if (*y1 < 0)
121 *y1 = 0;
122 else if (*y1 >= vp->height)
123 return false;
124
125 if (*y2 < 0)
126 return false;
127 else if (*y2 >= vp->height)
128 *y2 = vp->height - 1;
129
130 *x += vp->x;
131 *y1 += vp->y;
132 *y2 += vp->y;
133 return true;
134}
135
136static bool LCDFN(clip_viewport_rect)(int *x, int *y, int *width, int *height,
137 int *src_x, int *src_y)
138{
139 struct viewport *vp = LCDFN(current_viewport);
140
141 if (*x < 0) {
142 *width += *x;
143 if (src_x)
144 *src_x -= *x;
145 *x = 0;
146 }
147
148 if (*y < 0) {
149 *height += *y;
150 if (src_y)
151 *src_y -= *y;
152 *y = 0;
153 }
154
155 if (*x + *width > vp->width)
156 *width = vp->width - *x;
157
158 if (*y + *height > vp->height)
159 *height = vp->height - *y;
160
161 *x += vp->x;
162 *y += vp->y;
163 return *width > 0 && *height > 0;
164}
165
56/* 166/*
57 * draws the borders of the current viewport 167 * draws the borders of the current viewport
58 **/ 168 **/
diff --git a/firmware/drivers/lcd-color-common.c b/firmware/drivers/lcd-color-common.c
index 72ce7c209f..8a9ef64cea 100644
--- a/firmware/drivers/lcd-color-common.c
+++ b/firmware/drivers/lcd-color-common.c
@@ -40,6 +40,7 @@ static fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]
40 IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); 40 IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16);
41 41
42static void *lcd_frameaddress_default(int x, int y); 42static void *lcd_frameaddress_default(int x, int y);
43static bool lcd_clip_viewport_pixel(int *x, int *y);
43 44
44static fb_data* lcd_backdrop = NULL; 45static fb_data* lcd_backdrop = NULL;
45static long lcd_backdrop_offset IDATA_ATTR = 0; 46static long lcd_backdrop_offset IDATA_ATTR = 0;
@@ -196,10 +197,8 @@ fb_data* lcd_get_backdrop(void)
196/* Set a single pixel */ 197/* Set a single pixel */
197void lcd_drawpixel(int x, int y) 198void lcd_drawpixel(int x, int y)
198{ 199{
199 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) 200 if (lcd_clip_viewport_pixel(&x, &y))
200 && ((unsigned)y < (unsigned)lcd_current_viewport->height) 201 lcd_fastpixelfuncs[lcd_current_viewport->drawmode](FBADDR(x, y));
201 )
202 lcd_fastpixelfuncs[lcd_current_viewport->drawmode](FBADDR(lcd_current_viewport->x+x, lcd_current_viewport->y+y));
203} 202}
204 203
205/* Draw a line */ 204/* Draw a line */
@@ -274,11 +273,8 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
274 273
275 for (i = 0; i < numpixels; i++) 274 for (i = 0; i < numpixels; i++)
276 { 275 {
277 if ((x >= 0 && y >= 0) 276 if (x >= 0 && y >= 0 && x < w_vp && y < h_vp)
278 && (x < w_vp) 277 pfunc(fbaddr(x + x_vp, y + y_vp));
279 && (y < h_vp)
280 )
281 pfunc(fbaddr( x + x_vp, y + y_vp));
282 278
283 if (d < 0) 279 if (d < 0)
284 { 280 {
@@ -401,7 +397,7 @@ void lcd_gradient_fillrect_part(int x, int y, int width, int height,
401 x1 = x; 397 x1 = x;
402 x2 = x + width; 398 x2 = x + width;
403 399
404 if (height == 0) return; 400 if (height <= 0) return;
405 401
406 step_mul = (1 << 16) / src_height; 402 step_mul = (1 << 16) / src_height;
407 int h_r = RGB_UNPACK_RED(start_rgb); 403 int h_r = RGB_UNPACK_RED(start_rgb);