source: npl/mediabox/lcdproc_edwin/src/server/render.c

Last change on this file was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 13.1 KB
RevLine 
[c5c522c]1/*
2  render.c
3
4  Draws screens on the LCD.
5
6  This needs to be greatly expanded and redone for greater flexibility.
7  For example, it should support multiple screen sizes, more flexible
8  widgets, and multiple simultaneous screens.
9
10  This will probably take a while to do.  :(
11
12
13  THIS FILE IS MESSY!  Anyone care to rewrite it nicely?  Please??  :)
14 
15 */
16
17
18#include <string.h>
19#include <stdio.h>
20
21#include "../shared/debug.h"
22#include "../shared/LL.h"
23
24#include "drivers/lcd.h"
25
26#include "screen.h"
27#include "screenlist.h"
28#include "widget.h"
29#include "render.h"
30
31
32
33int heartbeat=HEART_OPEN;
34int backlight=BACKLIGHT_OPEN;
35int backlight_state = BACKLIGHT_OPEN;
36int backlight_brightness=255;
37int backlight_off_brightness=0;
38int output_state = 0;
39
40static int reset;
41
42#define BUFSIZE 1024
43
44static int draw_frame(LL *list, char fscroll,
45                      int left, int top, int right, int bottom,
46                      int fwid, int fhgt,
47                      int fspeed, int timer);
48
49
50int draw_screen(screen *s, int timer)
51{
52   static screen *old_s=NULL;
53   int tmp=0;
54   
55   //debug("Render...\n");
56   //return 0;
57
58   reset = 1;
59
60   //debug("draw_screen: %8x, %i\n", (int)s, timer);
61   
62   if(!s) return -1;
63
64   if(s == old_s) reset = 0;
65   old_s = s;
66
67
68
69   lcd.clear();
70
71
72   switch(backlight_state)
73   {
74      case BACKLIGHT_OFF:
75         lcd.backlight(backlight_off_brightness);
76         break;
77      case BACKLIGHT_ON:
78         lcd.backlight(backlight_brightness);
79         break;
80      default:
81         if(backlight_state & BACKLIGHT_FLASH)
82         {
83            tmp = (!((timer&7) == 7));
84            if(backlight_state & 1)
85               lcd.backlight(tmp?backlight_brightness:backlight_off_brightness);
86               //lcd.backlight(backlight_brightness * (!((timer&7) == 7)));
87            else
88               lcd.backlight(!tmp?backlight_brightness:backlight_off_brightness);
89               //lcd.backlight(backlight_brightness * ((timer&7) == 7));
90         }
91         else if(backlight_state & BACKLIGHT_BLINK)
92         {
93            tmp = (!((timer&14) == 14));
94            if(backlight_state & 1)
95               lcd.backlight(tmp?backlight_brightness:backlight_off_brightness);
96               //lcd.backlight(backlight_brightness * (!((timer&14) == 14)));
97            else
98               lcd.backlight(!tmp?backlight_brightness:backlight_off_brightness);
99               //lcd.backlight(backlight_brightness * ((timer&14) == 14));
100         }
101         break;
102   }
103
104   lcd.output(output_state);
105
106   draw_frame(s->widgets, 'v',
107              0, 0, lcd.wid, lcd.hgt,
108              s->wid, s->hgt,
109              s->duration/s->hgt, timer);
110   
111   
112   //debug("draw_screen done\n");
113
114   
115   if(heartbeat)
116   {
117      if(s->heartbeat  ||  heartbeat == HEART_ON)
118      {
119         // Set this to pulsate like a real heart beat...
120         // (binary is fun...  :)
121         lcd.icon(!((timer+4)&5), 0);
122         lcd.chr(lcd.wid, 1, 0);
123      }
124   }
125   
126   lcd.flush();
127   
128   //debug("draw_screen: %8x, %i\n", s, timer);
129
130   return 0;
131   
132}
133
134static int draw_frame(LL *list, char fscroll,
135                      int left, int top, int right, int bottom,
136                      int fwid, int fhgt,
137                      int fspeed, int timer)
138{
139   char str[BUFSIZE];  // scratch buffer
140   char strmarq[(BUFSIZE*2)+3];  // scratch buffer
141   widget *w;
142   
143   int wid, hgt;  // Width and height of visible frame area
144   int x, y;
145   int fx, fy;  // Scrolling offset for the frame...
146   int length, speed;
147   //int lines;
148   
149   int reset = 1;
150
151   wid = right - left;  // This is the size of the visible frame area
152   hgt = bottom - top;
153
154   fx = 0;
155   fy = 0;
156   if(fscroll == 'v')
157   {
158     
159      if(fspeed > 0)
160         fy = (timer-fspeed) / fspeed;
161      if(fspeed < 0)
162         fy = (-fspeed) * timer;
163      if(fy < 0) fy = 0;
164
165      // Make sure the whole frame gets displayed, at least...
166      if(!screenlist_action) screenlist_action = RENDER_HOLD;
167      if((fy) > fhgt - 1)
168      {
169         // Release hold after it has been displayed
170         if(!screenlist_action  ||  screenlist_action == RENDER_HOLD)
171            screenlist_action = 0;
172      }
173
174      fy %= fhgt;
175      if(fy > fhgt - hgt) fy = fhgt - hgt;
176   }
177   else if (fscroll == 'h')
178   { // TODO:  Frames don't scroll horizontally yet!
179     
180   }
181   
182   //debug("draw_screen: %8x, %i\n", s, timer);
183   
184   if(!list) return -1;
185   
186   //debug("draw_frame: %8x, %i\n", frame, timer);
187
188   
189   
190   LL_Rewind(list);
191   do {
192      w = (widget *)LL_Get(list);
193      if(!w) return -1;
194
195      // TODO:  Make this cleaner and more flexible!
196      switch(w->type)
197      {
198         case WID_STRING:
199            if((w->x > 0) && (w->y > 0) && (w->text))
200            {
201               if((w->y <= hgt + fy)  &&
202                  (w->y > fy))
203               {
204                  strncpy(str, w->text, wid - w->x + 1);
205                  str[wid - w->x + 1] = 0;
206                  lcd.string(w->x + left,
207                             w->y + top - fy,
208                             str);
209               }
210            }
211            break;
212         case WID_HBAR:
213            if(reset)
214            {
215               lcd.init_hbar();
216               reset = 0;
217            }
218            if((w->x > 0) && (w->y > 0))
219            {
220               if((w->y <= hgt + fy)  &&
221                  (w->y > fy))
222               {
223                  if(w->length > 0)
224                  {
225                     if((w->length / lcd.cellwid) < wid - w->x + 1)
226                        lcd.hbar(w->x + left,
227                                 w->y + top - fy,
228                                 w->length);
229                     else
230                        lcd.hbar(w->x + left,
231                                 w->y + top - fy,
232                                 wid * lcd.cellwid);
233                  }
234                  else if(w->length < 0)
235                  {
236                     // TODO:  Rearrange stuff to get left-extending
237                     // hbars to draw correctly...
238                     // .. er, this'll require driver modifications,
239                     // so I'll leave it out for now.
240                  }
241               }
242            }
243            break;
244         case WID_VBAR:  // FIXME:  Vbars don't work in frames!
245            if(reset)
246            {
247               lcd.init_vbar();
248               reset = 0;
249            }
250            if((w->x > 0) && (w->y > 0))
251            {
252               if(w->length > 0)
253               {
254                  lcd.vbar(w->x, w->length);
255               }
256               else if(w->length < 0)
257               {
258                  // TODO:  Rearrange stuff to get down-extending
259                  // vbars to draw correctly...
260                  // .. er, this'll require driver modifications,
261                  // so I'll leave it out for now.
262               }
263            }
264            break;
265         case WID_ICON:  // FIXME:  Not implemented
266            break;
267         case WID_TITLE: // FIXME:  Doesn't work quite right in frames...
268            if(!w->text) break;
269            if(wid < 8) break;
270           
271            memset(str, 0xf8, wid); //#### 0xf8 was 255. (quickhack for ISE display!)
272            str[2] = ' ';
273            length = strlen(w->text);
274            if(length <= wid-6)
275            {
276               memcpy(str+3, w->text, length);
277               str[length+3] = ' ';
278            }
279            else // Scroll the title, if it doesn't fit...
280            {
281               speed = 1;
282               x = timer / speed;
283               y = x / length;
284
285               // Make sure the whole title gets displayed, at least...
286               if(!screenlist_action) screenlist_action = RENDER_HOLD;
287               if(x > length - 6)
288               {
289                  // Release hold after it has been displayed
290                  if(!screenlist_action  ||  screenlist_action == RENDER_HOLD)
291                     screenlist_action = 0;
292               }
293               x %= (length);
294               x -= 3;
295               if(x < 0) x = 0;
296               if(x > length - (wid-6)) x = length - (wid-6);
297               
298               if(y&1) // Scrolling backwards...
299               {
300                  x = (length-(wid-6)) - x;
301               }
302               strncpy(str+3, w->text+x, (wid-6));
303               str[wid-3] = ' ';
304            }
305            str[wid] = 0;
306           
307            lcd.string(1 + left, 1 + top, str);
308            break;
309         case WID_SCROLLER: // FIXME: doesn't work in frames...
310         {
311              int offset;
312              int screen_width;
313              if (!w->text) break;
314              if (w->right < w->left) break;
315              //printf("rendering: %s %d\n",w->text,timer);
316              screen_width = w->right - w->left + 1;
317              switch (w->length)
318              { // actually, direction...
319                 // FIXED:  Horz scrollers don't show the
320                 // last letter in the string...  (1-off error?)
321                 case 'h':
322                    length = strlen(w->text) + 1 ;
323                    if (length <= screen_width)
324                    {
325                       /* it fits within the box, just render it */
326                       lcd.string(w->left,w->top,w->text);
327                    }
328                    else
329                    {
330                       int effLength = length-1  +3; //(we add 3 chars because of wrapping around)
331                       int necessaryTimeUnits = 0;
332                       if (!screenlist_action) screenlist_action = RENDER_HOLD;
333                       if (w->speed > 0) {
334                          necessaryTimeUnits = effLength * w->speed;
335                          //if (((timer / (effLength*w->speed)) % 2) == 0) {
336                             //wiggle one way
337                             offset = (timer % (effLength*w->speed)) / w->speed;
338                          //}
339                          //else
340                          //{
341                             //wiggle the other
342                            // offset = (((timer % (effLength*w->speed))
343                        //              - (effLength*w->speed) + 1)
344                        //             / w->speed) * -1;
345                          //}
346                       }
347                       else if (w->speed < 0)
348                       {
349                          necessaryTimeUnits = effLength / (w->speed * -1);
350                         // if (((timer / (effLength/(w->speed*-1))) % 2) == 0)
351                          //{
352                             offset = (timer % (effLength/(w->speed*-1)))
353                                * w->speed * -1;
354                          //}
355                          //else
356                         // {
357                             offset = (((timer % (effLength/(w->speed*-1)))
358                                        * w->speed * -1) - effLength + 1) * -1;
359                          //}
360                       }
361                       else
362                       {
363                          offset = 0;
364                          if(screenlist_action == RENDER_HOLD)
365                             screenlist_action = 0;
366                       }
367                       if (timer > necessaryTimeUnits)
368                       {
369                          if(screenlist_action == RENDER_HOLD)
370                             screenlist_action = 0;
371                       }
372
373                       //just extend the text..
374                       strcpy(strmarq,w->text);
375                       strcat(strmarq," | ");
376                       strncat(strmarq,w->text,screen_width);
377                       
378                       //now offsets can be beyond normal range..
379                       str[0]='\0';
380                       strncat(str,&((strmarq)[offset]),screen_width);
381                       
382                       //if (offset <= length)
383                      // {
384                          //is offset still withing range?
385                          //if (offset<strlen(w->text))
386                         // {
387                          //}
388                          //do we have "space left" that we should fill?
389                          //strncat(str," | ", strlen(str)-screen_width);
390                          //strncat(str,w->text, strlen(str)-screen_width-3);
391//                        }
392                          //str[screen_width] = '\0';
393                          //printf("%s : %d\n",str,length-offset);
394                       //}
395                       //else
396                       //{
397                        // 
398                      // }
399                       lcd.string(w->left,w->top,str);
400                    }
401                    break;
402                 // FIXME:  Vert scrollers don't always seem to scroll
403                 // back up after hitting the bottom.  They jump back to
404                 // the top instead...  (nevermind?)
405                 case 'v':
406                 {
407                    int i=0;
408                    length = strlen(w->text);
409                    if (length <= screen_width)
410                    {
411                       /* no scrolling required...*/
412                       lcd.string(w->left,w->top,w->text);
413                    }
414                    else
415                    {
416                       int lines_required =
417                          (length / screen_width)
418                          + (length % screen_width ? 1 : 0);
419                       int available_lines = (w->bottom - w->top + 1);
420                       if (lines_required <= available_lines)
421                       {
422                          // easy...
423                          for(i=0;i<lines_required;i++)
424                          {
425                             strncpy(str,
426                                     &((w->text)[i*screen_width]),
427                                     screen_width);
428                             str[screen_width] = '\0';
429                             lcd.string(w->left,w->top + i,str);
430                          }
431                       }
432                       else
433                       {
434                          int necessaryTimeUnits = 0;
435                          int effLines = lines_required - available_lines + 1;
436                          int begin = 0;
437                          if (!screenlist_action)
438                             screenlist_action = RENDER_HOLD;
439                          //printf("length: %d sw: %d lines req: %d  avail lines: %d  effLines: %d \n",length,screen_width,lines_required,available_lines,effLines);
440                          if (w->speed > 0)
441                          {
442                             necessaryTimeUnits = effLines * w->speed;
443                             if (((timer / (effLines*w->speed)) % 2) == 0)
444                             {
445                                //printf("up ");
446                                begin = (timer % (effLines*w->speed))
447                                   / w->speed;
448                             }
449                             else
450                             {
451                                //printf("down ");
452                                begin = (((timer % (effLines*w->speed))
453                                          - (effLines*w->speed) + 1)/w->speed)
454                                   * -1;
455                             }
456                          }
457                          else if (w->speed < 0)
458                          {
459                             necessaryTimeUnits = effLines / (w->speed * -1);
460                             if (((timer / (effLines/(w->speed*-1))) % 2) == 0)
461                             {
462                                begin = (timer % (effLines/(w->speed*-1)))
463                                   * w->speed * -1;
464                             }
465                             else
466                             {
467                                begin = (((timer % (effLines/(w->speed*-1)))
468                                          * w->speed * -1) - effLines + 1)
469                                   * -1;
470                             }
471                          }
472                          else
473                          {
474                             begin = 0;
475                          }
476                          //printf("rendering begin: %d  timer: %d effLines: %d\n",begin,timer,effLines);
477                          for(i=begin;i<begin+available_lines;i++)
478                          {
479                             strncpy(str,
480                                     &((w->text)[i*(screen_width)]),
481                                     screen_width);
482                             str[screen_width] = '\0';
483                             //printf("rendering: '%s' of %s\n",
484                             //str,w->text);
485                             lcd.string(w->left,w->top + (i-begin),str);
486                          }
487                          if (timer > necessaryTimeUnits)
488                          {
489                             if(screenlist_action == RENDER_HOLD)
490                                screenlist_action = 0;
491                          }
492                       }
493                    }
494                    break;
495                 }
496              }
497              break;
498         }
499         case WID_FRAME:
500         {
501            // FIXME: doesn't handle nested frames quite right!
502            // doesn't handle scrolling in nested frames at all...
503            int new_left, new_top, new_right, new_bottom;
504            new_left = left + w->left - 1;
505            new_top = top + w->top - 1;
506            new_right = left + w->right;
507            new_bottom = top + w->bottom;
508            if(new_right > right) new_right = right;
509            if(new_bottom > bottom) new_bottom = bottom;
510            if(new_left >= right  ||
511               new_top >= bottom)
512            {  // Do nothing if it's invisible...
513            }
514            else
515            {
516               draw_frame(w->kids, w->length,
517                          new_left, new_top, new_right, new_bottom,
518                          w->wid, w->hgt,
519                          w->speed, timer);
520            }
521         }
522         break;
523         case WID_NUM: // FIXME: doesn't work in frames...
524            if((w->x > 0) && (w->y >= 0) && (w->y <= 9))
525            {
526               if(reset)
527               {
528                  lcd.init_num();
529                  reset = 0;
530               }
531               lcd.num(w->x + left, w->y);
532            }
533            break;
534         case WID_NONE:
535         default:
536            break;
537      }
538   } while(LL_Next(list) == 0);
539
540   
541   return 0;
542}
543
Note: See TracBrowser for help on using the repository browser.