diff options
Diffstat (limited to 'firmware/drivers/lcd-bitmap-common.c')
-rw-r--r-- | firmware/drivers/lcd-bitmap-common.c | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index a71f5b2862..22430d4e50 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c | |||
@@ -316,15 +316,19 @@ static struct scrollinfo* find_scrolling_line(int x, int y) | |||
316 | 316 | ||
317 | void LCDFN(scroll_fn)(struct scrollinfo* s) | 317 | void LCDFN(scroll_fn)(struct scrollinfo* s) |
318 | { | 318 | { |
319 | /* with line == NULL when scrolling stops. This scroller | ||
320 | * maintains no userdata so there is nothing left to do */ | ||
321 | if (!s->line) | ||
322 | return; | ||
319 | /* Fill with background/backdrop to clear area. | 323 | /* Fill with background/backdrop to clear area. |
320 | * cannot use clear_viewport_rect() since stops scrolling as well */ | 324 | * cannot use clear_viewport_rect() since would stop scrolling as well */ |
321 | LCDFN(set_drawmode)(DRMODE_SOLID|DRMODE_INVERSEVID); | 325 | LCDFN(set_drawmode)(DRMODE_SOLID|DRMODE_INVERSEVID); |
322 | LCDFN(fillrect)(s->x, s->y, s->width, s->height); | 326 | LCDFN(fillrect)(s->x, s->y, s->width, s->height); |
323 | LCDFN(set_drawmode)(DRMODE_SOLID); | 327 | LCDFN(set_drawmode)(DRMODE_SOLID); |
324 | LCDFN(putsxyofs)(s->x, s->y, s->offset, s->line); | 328 | LCDFN(putsxyofs)(s->x, s->y, s->offset, s->line); |
325 | } | 329 | } |
326 | 330 | ||
327 | static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | 331 | static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, |
328 | int x_offset, | 332 | int x_offset, |
329 | bool linebased, | 333 | bool linebased, |
330 | void (*scroll_func)(struct scrollinfo *), | 334 | void (*scroll_func)(struct scrollinfo *), |
@@ -336,7 +340,7 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
336 | bool restart; | 340 | bool restart; |
337 | 341 | ||
338 | if (!string) | 342 | if (!string) |
339 | return; | 343 | return false; |
340 | 344 | ||
341 | /* prepare rectangle for scrolling. x and y must be calculated early | 345 | /* prepare rectangle for scrolling. x and y must be calculated early |
342 | * for find_scrolling_line() to work */ | 346 | * for find_scrolling_line() to work */ |
@@ -347,32 +351,25 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
347 | width = current_vp->width - x; | 351 | width = current_vp->width - x; |
348 | 352 | ||
349 | if (y >= current_vp->height) | 353 | if (y >= current_vp->height) |
350 | return; | 354 | return false; |
351 | 355 | ||
352 | s = find_scrolling_line(x, y); | 356 | s = find_scrolling_line(x, y); |
353 | restart = !s; | 357 | restart = !s; |
354 | 358 | ||
355 | if (restart) { | ||
356 | /* remove any previously scrolling line at the same location */ | ||
357 | LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height); | ||
358 | LCDFN(putsxyofs)(x, y, x_offset, string); | ||
359 | |||
360 | if (LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | /* get width (pixeks) of the string */ | 359 | /* get width (pixeks) of the string */ |
365 | LCDFN(getstringsize)(string, &w, &h); | 360 | LCDFN(getstringsize)(string, &w, &h); |
366 | 361 | ||
367 | /* check if scrolling is actually necessary (consider the actual start | 362 | /* Remove any previously scrolling line at the same location. If |
368 | * of the line) */ | 363 | * the string width is too small to scroll the scrolling line is |
369 | if (width >= w) | 364 | * cleared as well */ |
370 | return; | 365 | if (w < width || restart) { |
371 | 366 | LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height); | |
372 | if (restart) { | 367 | LCDFN(putsxyofs)(x, y, x_offset, string); |
373 | /* prepare scroll line */ | 368 | /* nothing to scroll, or out of scrolling lines. Either way, get out */ |
369 | if (w < width || LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) | ||
370 | return false; | ||
371 | /* else restarting: prepare scroll line */ | ||
374 | s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines]; | 372 | s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines]; |
375 | s->start_tick = current_tick + LCDFN(scroll_info).delay; | ||
376 | } | 373 | } |
377 | 374 | ||
378 | /* copy contents to the line buffer */ | 375 | /* copy contents to the line buffer */ |
@@ -385,9 +382,6 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
385 | else | 382 | else |
386 | s->bidir = false; | 383 | s->bidir = false; |
387 | 384 | ||
388 | s->scroll_func = scroll_func; | ||
389 | s->userdata = data; | ||
390 | |||
391 | if (restart) { | 385 | if (restart) { |
392 | s->offset = x_offset; | 386 | s->offset = x_offset; |
393 | s->backward = false; | 387 | s->backward = false; |
@@ -397,26 +391,41 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
397 | s->width = width; | 391 | s->width = width; |
398 | s->height = height; | 392 | s->height = height; |
399 | s->vp = current_vp; | 393 | s->vp = current_vp; |
394 | s->start_tick = current_tick + LCDFN(scroll_info).delay; | ||
400 | LCDFN(scroll_info).lines++; | 395 | LCDFN(scroll_info).lines++; |
401 | } else { | 396 | } else { |
402 | /* if only the text was updated render immediately */ | 397 | /* not restarting, however we are about to assign new userdata; |
403 | LCDFN(scroll_now(s)); | 398 | * therefore tell the scroller that it can release the previous userdata */ |
399 | s->line = NULL; | ||
400 | s->scroll_func(s); | ||
404 | } | 401 | } |
402 | |||
403 | s->scroll_func = scroll_func; | ||
404 | s->userdata = data; | ||
405 | |||
406 | /* if only the text was updated render immediately */ | ||
407 | if (!restart) | ||
408 | LCDFN(scroll_now(s)); | ||
409 | |||
410 | return true; | ||
405 | } | 411 | } |
406 | 412 | ||
407 | void LCDFN(putsxy_scroll_func)(int x, int y, const unsigned char *string, | 413 | bool LCDFN(putsxy_scroll_func)(int x, int y, const unsigned char *string, |
408 | void (*scroll_func)(struct scrollinfo *), | 414 | void (*scroll_func)(struct scrollinfo *), |
409 | void *data, int x_offset) | 415 | void *data, int x_offset) |
410 | { | 416 | { |
417 | bool retval = false; | ||
411 | if (!scroll_func) | 418 | if (!scroll_func) |
412 | LCDFN(putsxyofs)(x, y, x_offset, string); | 419 | LCDFN(putsxyofs)(x, y, x_offset, string); |
413 | else | 420 | else |
414 | LCDFN(puts_scroll_worker)(x, y, string, x_offset, false, scroll_func, data); | 421 | retval = LCDFN(puts_scroll_worker)(x, y, string, x_offset, false, scroll_func, data); |
422 | |||
423 | return retval; | ||
415 | } | 424 | } |
416 | 425 | ||
417 | void LCDFN(puts_scroll)(int x, int y, const unsigned char *string) | 426 | bool LCDFN(puts_scroll)(int x, int y, const unsigned char *string) |
418 | { | 427 | { |
419 | LCDFN(puts_scroll_worker)(x, y, string, 0, true, LCDFN(scroll_fn), NULL); | 428 | return LCDFN(puts_scroll_worker)(x, y, string, 0, true, LCDFN(scroll_fn), NULL); |
420 | } | 429 | } |
421 | 430 | ||
422 | #if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) | 431 | #if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) |