212
210
/* The runtime settings (some initialized from system prefs, but changable.)
214
212
struct render_state {
216
enum date_state { DTime, DDateIn, DDate, DDateOut, DDateOut2, DDash, DDash2 }
219
unsigned int last_time;
213
unsigned int last_secs;
221
214
int char_width, char_height, colon_width;
223
struct frame *base_frames [12];
224
struct frame *orig_frames [6];
225
struct frame *current_frames [6];
226
struct frame *target_frames [6];
227
struct frame *clear_frame;
229
signed char current_digits [6];
230
signed char target_digits [6];
231
BOOL digits_clean_p [6]; /* "clean" means "not stuck between digits" */
215
struct frame *base_frames [12]; /* all digits */
216
struct frame *orig_frames [8]; /* what was there */
217
struct frame *current_frames [8]; /* current intermediate animation */
218
struct frame *target_frames [8]; /* where we are going */
219
int target_digits [8]; /* where we are going */
220
struct frame *empty_frame;
221
struct frame *empty_colon;
235
225
static struct frame *
236
make_blank_frame (int width, int height)
226
make_empty_frame (int width, int height)
238
int size = sizeof (struct frame) + (sizeof (struct scanline) * (height - 1));
228
int size = sizeof (struct frame) + (sizeof (struct scanline) * height);
239
229
struct frame *frame;
409
392
state->char_height = raw[0].height;
410
393
state->colon_width = raw[10].width;
395
state->empty_frame = make_empty_frame (raw[0].width, raw[0].height);
396
state->empty_colon = make_empty_frame (raw[10].width, raw[10].height);
412
398
for (i = 0; i < countof(state->base_frames); i++)
413
399
state->base_frames [i] =
414
400
number_to_frame (raw[i].bits, raw[i].width, raw[i].height);
415
401
#endif /* BUILTIN_FONTS */
417
for (i = 0; i < countof(state->orig_frames); i++)
418
state->orig_frames [i] =
419
make_blank_frame (state->char_width, state->char_height);
421
for (i = 0; i < countof(state->current_frames); i++)
422
state->current_frames [i] =
423
make_blank_frame (state->char_width, state->char_height);
425
for (i = 0; i < countof(state->target_frames); i++)
426
state->target_frames [i] =
427
make_blank_frame (state->char_width, state->char_height);
429
state->clear_frame = make_blank_frame (state->char_width,
403
memset (state->orig_frames, 0, sizeof(state->orig_frames));
404
memset (state->current_frames, 0, sizeof(state->current_frames));
405
memset (state->target_frames, 0, sizeof(state->target_frames));
407
for (i = 0; i < countof(state->current_frames); i++) {
408
int colonic_p = (i == 2 || i == 5);
409
int cw = raw[colonic_p ? 10 : 0].width;
410
int ch = raw[0].height;
411
state->orig_frames[i] = make_empty_frame (cw, ch);
412
state->current_frames[i] = make_empty_frame (cw, ch);
413
state->target_frames[i] = make_empty_frame (cw, ch);
432
416
for (i = 0; i < countof(state->target_digits); i++)
433
state->target_digits[i] = state->current_digits[i] = -1;
435
memset (state->digits_clean_p, 0, sizeof(state->digits_clean_p));
417
state->target_digits[i] = -1;
437
419
memset (c->bitmap, 0, c->height * (c->width >> 3));
475
487
: c->test_hack - '0');
476
488
c->test_hack = 0;
478
else if (state->display_date == DTime ||
479
state->display_date == DDash ||
480
state->display_date == DDash2)
490
else if (!c->display_date_p)
482
BOOL twelve_hour_time_p = c->twelve_hour_p;
484
if (state->display_date == DDash)
485
state->display_date = DDash2;
486
else if (state->display_date == DDash2)
487
state->display_date = DTime;
492
switch (c->time_mode)
491
long delta = ((unsigned long) c->countdown) - time;
492
if (delta < 0) delta = -delta;
493
tm->tm_sec = delta % 60;
494
tm->tm_min = (delta / 60) % 60;
495
tm->tm_hour = (delta / (60 * 60)) % 100;
496
twelve_hour_time_p = 0;
495
state->target_digits[0] = (s / 10);
496
state->target_digits[1] = (s % 10);
499
state->target_digits[0] = (h / 10);
500
state->target_digits[1] = (h % 10);
501
state->target_digits[2] = 10; /* colon */
502
state->target_digits[3] = (m / 10);
503
state->target_digits[4] = (m % 10);
504
if (twelve_p && state->target_digits[0] == 0)
505
state->target_digits[0] = -1;
508
state->target_digits[0] = (h / 10);
509
state->target_digits[1] = (h % 10);
510
state->target_digits[2] = 10; /* colon */
511
state->target_digits[3] = (m / 10);
512
state->target_digits[4] = (m % 10);
513
state->target_digits[5] = 10; /* colon */
514
state->target_digits[6] = (s / 10);
515
state->target_digits[7] = (s % 10);
516
if (twelve_p && state->target_digits[0] == 0)
517
state->target_digits[0] = -1;
498
if (twelve_hour_time_p && tm->tm_hour > 12) tm->tm_hour -= 12;
499
if (twelve_hour_time_p && tm->tm_hour == 0) tm->tm_hour = 12;
500
state->target_digits [0] = (tm->tm_hour - (tm->tm_hour % 10)) / 10;
501
state->target_digits [1] = tm->tm_hour % 10;
502
state->target_digits [2] = (tm->tm_min - (tm->tm_min % 10)) / 10;
503
state->target_digits [3] = tm->tm_min % 10;
504
state->target_digits [4] = (tm->tm_sec - (tm->tm_sec % 10)) / 10;
505
state->target_digits [5] = tm->tm_sec % 10;
507
if (twelve_hour_time_p && state->target_digits [0] == 0)
508
state->target_digits [0] = -1;
512
int m0,m1,d0,d1,y0,y1;
513
tm->tm_mon++; /* 0 based */
514
m0 = (tm->tm_mon - (tm->tm_mon % 10)) / 10;
515
m1 = tm->tm_mon % 10;
516
d0 = (tm->tm_mday - (tm->tm_mday % 10)) / 10;
517
d1 = tm->tm_mday % 10;
518
y0 = tm->tm_year % 100;
519
y0 = (y0 - (y0 % 10)) / 10;
520
y1 = tm->tm_year % 10;
522
if (state->display_date == DDateIn)
523
state->display_date = DDate;
524
if (state->display_date == DDateOut)
525
state->display_date = DDateOut2;
526
else if (state->display_date == DDateOut2)
527
state->display_date = DDash;
528
else if (state->display_date == DDash)
529
state->display_date = DDash2;
531
switch (c->date_mode)
525
switch (c->date_mode)
534
switch (c->time_mode)
538
state->target_digits [0] = m0; state->target_digits [1] = m1;
539
state->target_digits [2] = d0; state->target_digits [3] = d1;
540
state->target_digits [4] = y0; state->target_digits [5] = y1;
543
state->target_digits [4] = d0; state->target_digits [5] = d1;
528
switch (c->time_mode) {
530
state->target_digits[0] = (D / 10);
531
state->target_digits[1] = (D % 10);
534
state->target_digits[0] = (M / 10);
535
state->target_digits[1] = (M % 10);
536
state->target_digits[2] = 11; /* dash */
537
state->target_digits[3] = (D / 10);
538
state->target_digits[4] = (D % 10);
541
state->target_digits[0] = (M / 10);
542
state->target_digits[1] = (M % 10);
543
state->target_digits[2] = 11; /* dash */
544
state->target_digits[3] = (D / 10);
545
state->target_digits[4] = (D % 10);
546
state->target_digits[5] = 11; /* dash */
547
state->target_digits[6] = (Y / 10);
548
state->target_digits[7] = (Y % 10);
550
switch (c->time_mode)
554
state->target_digits [0] = d0; state->target_digits [1] = d1;
555
state->target_digits [2] = m0; state->target_digits [3] = m1;
556
state->target_digits [4] = y0; state->target_digits [5] = y1;
559
state->target_digits [4] = d0; state->target_digits [5] = d1;
555
switch (c->time_mode) {
557
state->target_digits[0] = (D / 10);
558
state->target_digits[1] = (D % 10);
561
state->target_digits[0] = (D / 10);
562
state->target_digits[1] = (D % 10);
563
state->target_digits[2] = 11; /* dash */
564
state->target_digits[3] = (M / 10);
565
state->target_digits[4] = (M % 10);
568
state->target_digits[0] = (D / 10);
569
state->target_digits[1] = (D % 10);
570
state->target_digits[2] = 11; /* dash */
571
state->target_digits[3] = (M / 10);
572
state->target_digits[4] = (M % 10);
573
state->target_digits[5] = 11; /* dash */
574
state->target_digits[6] = (Y / 10);
575
state->target_digits[7] = (Y % 10);
566
switch (c->time_mode)
570
state->target_digits [0] = y0; state->target_digits [1] = y1;
571
state->target_digits [2] = m0; state->target_digits [3] = m1;
572
state->target_digits [4] = d0; state->target_digits [5] = d1;
575
state->target_digits [0] = m0; state->target_digits [1] = m1;
576
state->target_digits [2] = d0; state->target_digits [3] = d1;
582
switch (c->time_mode) {
584
state->target_digits[0] = (D / 10);
585
state->target_digits[1] = (D % 10);
588
state->target_digits[0] = (M / 10);
589
state->target_digits[1] = (M % 10);
590
state->target_digits[2] = 11; /* dash */
591
state->target_digits[3] = (D / 10);
592
state->target_digits[4] = (D % 10);
595
state->target_digits[0] = (Y / 10);
596
state->target_digits[1] = (Y % 10);
597
state->target_digits[2] = 11; /* dash */
598
state->target_digits[3] = (M / 10);
599
state->target_digits[4] = (M % 10);
600
state->target_digits[5] = 11; /* dash */
601
state->target_digits[6] = (D / 10);
602
state->target_digits[7] = (D % 10);
682
708
struct render_state *state = c->render_state;
685
/* Copy the (old) current_frames into the (new) orig_frames,
686
since that's what's on the screen now. */
711
/* Move the (old) current_frames into the (new) orig_frames,
712
since that's what's on the screen now.
713
Frames are freed as they expire out of orig_frames.
687
715
for (i = 0; i < countof (state->current_frames); i++)
688
copy_frame (c, state->current_frames[i], state->orig_frames[i]);
690
/* likewise with the (old) current_digits */
691
memcpy (state->current_digits, state->target_digits,
692
sizeof (state->target_digits));
717
if (state->orig_frames[i])
718
free (state->orig_frames[i]);
719
state->orig_frames[i] = state->current_frames[i];
720
state->current_frames[i] = state->target_frames[i];
721
state->target_frames[i] = 0;
694
724
/* generate new target_digits */
695
725
fill_target_digits (c, time);
697
727
/* Fill the (new) target_frames from the (new) target_digits. */
698
728
for (i = 0; i < countof (state->target_frames); i++)
700
int j = state->target_digits[i];
701
struct frame *to = state->target_frames[i];
702
struct frame *from = (j < 0
704
: state->base_frames [j]);
705
copy_frame (c, from, to);
707
/* This digit is "clean" if what is currently on screen is exactly
708
equal to the rest-state digit (not in some half-animated inbetween
709
state, as it might be if the wall clock moved from 4.8 seconds
710
directly to 5.2 seconds without stopping closer to 5.0.) */
711
state->digits_clean_p[i] = frame_equal (c, to, state->current_frames[i]);
730
int colonic_p = (i == 2 || i == 5);
731
state->target_frames[i] =
733
(state->target_digits[i] == -1
734
? (colonic_p ? state->empty_colon : state->empty_frame)
735
: state->base_frames[state->target_digits[i]]));
714
738
/* Render the current frame. */
794
814
draw_clock (dali_config *c, BOOL colonic_p)
796
816
struct render_state *state = c->render_state;
798
int width = c->width;
799
int height = c->height;
802
switch (c->time_mode)
804
case SS: nn = 2, cc = 0; break;
805
case HHMM: nn = 4, cc = 1; break;
806
case HHMMSS: nn = 6, cc = 2; break;
807
default: abort(); break;
810
x = (width - ((state->char_width * nn) +
811
(state->colon_width * cc))) / 2;
812
y = (height - state->char_height) / 2;
815
We can skip rendering this frame if:
816
- the old and new digit are the same (no motion desired); and
817
- what is on the screen is a rest-state of that digit (not an
818
intermediate frame of the last animation that didn't fully
821
if (state->target_digits[n] != state->current_digits[n] || \
822
!state->digits_clean_p[n]) \
823
draw_frame (c, state->current_frames [n], x, y, 0); \
824
x += state->char_width
828
draw_frame (c, state->base_frames \
829
[state->display_date == DTime ? 10 : 11], \
831
x += state->colon_width
833
switch (c->time_mode)
819
int displayed_digits;
821
switch (c->time_mode)
823
case SS: displayed_digits = 2; break;
824
case HHMM: displayed_digits = 6; break;
825
case HHMMSS: displayed_digits = 8; break;
826
default: abort(); break;
829
for (i = 0; i < displayed_digits; i++)
831
int colonic_p = (i == 2 || i == 5);
832
x += draw_frame (c, state->current_frames[i], x, y, colonic_p);