diff --git a/src/widget/label.c b/src/widget/label.c index 64cfcbd..0a6ee0d 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -122,7 +122,197 @@ static void draw_h(MwWidget handle, unsigned char* raw, int x, int y, int stride } } -static void draw(MwWidget handle) { +static void draw_seven_segment(MwWidget handle) { + MwRect r; + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwLLColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow); + int align; + const char* str = MwGetText(handle, MwNtext); + MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + MwLabel lab = handle->internal; + int l_one = MwGetInteger(handle, MwNlength) - (MwGetInteger(handle, MwNlength) % 2); + int s_one = (l_one * 3 / 4) - ((l_one * 3 / 4) % 2) + 1; + MwLLPixmap px; + unsigned char* raw; + int w = 0, h = s_one * 3 + l_one * 2, i; + int x = 0; + + if(str == NULL) str = ""; + + r.x = 0; + r.y = 0; + r.width = MwGetInteger(handle, MwNwidth); + r.height = MwGetInteger(handle, MwNheight); + + MwDrawRect(handle, &r, base); + if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); + + align = MwGetInteger(handle, MwNalignment); + + /* so - this mode cannot do unicode. + * but you wouldn't show unicode on 7 segment anyways + */ + + /* L + * S <---> + * + * S + * ^ + * | + * L | + * | + * v + */ + + for(i = 0; (hmgeti(lab->segment, i) != -1) || str[i] != 0; i++) { + if(i > 0 && ((hmgeti(lab->segment, i) != -1) || str[i] != '.')) w += Spacing; + if(hmgeti(lab->segment, i) != -1 || ('0' <= str[i] && str[i] <= '9') || ('A' <= str[i] && str[i] <= 'F') || ('a' <= str[i] && str[i] <= 'f')) { + w += l_one + s_one * 2; + } else if(str[i] == ':' || str[i] == ' ') { + w += s_one; + } + } + + w++; + h++; + + raw = malloc(w * h * 4); + memset(raw, 0, w * h * 4); + + for(i = 0; (hmgeti(lab->segment, i) != -1) || str[i] != 0; i++) { + if((hmgeti(lab->segment, i) != -1) || ('0' <= str[i] && str[i] <= '9') || ('A' <= str[i] && str[i] <= 'F') || ('a' <= str[i] && str[i] <= 'f')) { + int la = 0, lb = 0, lc = 0, ld = 0, le = 0, lf = 0, lg = 0; + int j; + + /* https://en.wikipedia.org/wiki/File:7_Segment_Display_with_Labeled_Segments.svg */ + + if(hmgeti(lab->segment, i) != -1) { + unsigned char c = hmget(lab->segment, i); + + if(c & (1 << 0)) la = 1; + if(c & (1 << 1)) lb = 1; + if(c & (1 << 2)) lc = 1; + if(c & (1 << 3)) ld = 1; + if(c & (1 << 4)) le = 1; + if(c & (1 << 5)) lf = 1; + if(c & (1 << 6)) lg = 1; + } else { + if(str[i] == '0') { + la = lb = lc = ld = le = lf = 1; + } else if(str[i] == '1') { + lb = lc = 1; + } else if(str[i] == '2') { + la = lb = ld = le = lg = 1; + } else if(str[i] == '3') { + la = lb = lc = ld = lg = 1; + } else if(str[i] == '4') { + lb = lc = lf = lg = 1; + } else if(str[i] == '5') { + la = lc = ld = lf = lg = 1; + } else if(str[i] == '6') { + la = lc = ld = le = lf = lg = 1; + } else if(str[i] == '7') { + la = lb = lc = 1; + } else if(str[i] == '8') { + la = lb = lc = ld = le = lf = lg = 1; + } else if(str[i] == '9') { + la = lb = lc = ld = lf = lg = 1; + } else if(str[i] == 'A' || str[i] == 'a') { + la = lb = lc = le = lf = lg = 1; + } else if(str[i] == 'B' || str[i] == 'b') { + lc = ld = le = lf = lg = 1; + } else if(str[i] == 'C' || str[i] == 'c') { + ld = le = lg = 1; + } else if(str[i] == 'D' || str[i] == 'd') { + lb = lc = ld = le = lg = 1; + } else if(str[i] == 'E' || str[i] == 'e') { + la = ld = le = lf = lg = 1; + } else if(str[i] == 'F' || str[i] == 'f') { + la = le = lf = lg = 1; + } + } + + for(j = 1; j >= 0; j--) { + MwLLColor cl = j == 1 ? shadow : text; + + if(la) draw_h(handle, raw, x + s_one + j, j, w, cl); + if(lb) draw_v(handle, raw, x + s_one + l_one + j, s_one + j, w, cl); + if(lc) draw_v(handle, raw, x + s_one + l_one + j, s_one * 2 + l_one + j, w, cl); + if(ld) draw_h(handle, raw, x + s_one + j, s_one * 2 + l_one * 2 + j, w, cl); + if(le) draw_v(handle, raw, x + j, s_one * 2 + l_one + j, w, cl); + if(lf) draw_v(handle, raw, x + j, s_one + j, w, cl); + if(lg) draw_h(handle, raw, x + s_one + j, s_one + l_one + j, w, cl); + } + + x += l_one + s_one * 2; + } else if(str[i] == ':') { + int cy, cx; + int j; + for(j = 1; j >= 0; j--) { + MwLLColor cl = j == 1 ? shadow : text; + for(cy = 1; cy < h - 1; cy++) { + int h = s_one / 2; + int c = (l_one - h) / 2 + s_one; + + int c1 = (c <= cy && cy <= (c + h)) ? 1 : 0; + int c2 = ((s_one + l_one + c) <= cy && cy <= (s_one + l_one + c + h)) ? 1 : 0; + + if(c1 || c2) { + for(cx = x; cx < x + s_one; cx++) { + unsigned char* px = &raw[((cy + j) * w + (cx + j)) * 4]; + px[0] = cl->common.red; + px[1] = cl->common.green; + px[2] = cl->common.blue; + px[3] = 255; + } + } + } + } + x += s_one; + } else if(str[i] == ' ') { + x += s_one; + } else if(str[i] == '.') { + int cy, cx; + int j; + for(j = 1; j >= 0; j--) { + MwLLColor cl = j == 1 ? shadow : text; + for(cy = h - (s_one - 1) / 2 - 1; cy < h; cy++) { + for(cx = x - Spacing - (s_one - 1) / 2 - 1; cx < (x - Spacing); cx++) { + unsigned char* px = &raw[((cy + j) * w + (cx + j)) * 4]; + px[0] = cl->common.red; + px[1] = cl->common.green; + px[2] = cl->common.blue; + px[3] = 255; + } + } + } + continue; + } + + x += Spacing; + } + + px = MwLoadRaw(handle, raw, w, h); + + r.y = (r.height - h) / 2; + r.height = h; + if(align == MwALIGNMENT_CENTER) { + r.x = (r.width - w) / 2; + } else if(align == MwALIGNMENT_BEGINNING) { + r.x = 0; + } else if(align == MwALIGNMENT_END) { + r.x = r.width - w; + } + r.width = w; + MwLLDrawPixmap(handle->lowlevel, &r, px); + + free(raw); + + MwLLDestroyPixmap(px); +} + +static void draw_normal(MwWidget handle) { MwRect r; MwPoint p; MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); @@ -146,194 +336,27 @@ static void draw(MwWidget handle) { if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx); align = MwGetInteger(handle, MwNalignment); - if(MwGetInteger(handle, MwNsevenSegment)) { - MwLLPixmap px; - unsigned char* raw; - int w = 0, h = s_one * 3 + l_one * 2, i; - int x = 0; - /* so - this mode cannot do unicode. - * but you wouldn't show unicode on 7 segment anyways - */ + r.width -= MwGetInteger(handle, MwNleftPadding); - /* L - * S <---> - * - * S - * ^ - * | - * L | - * | - * v - */ - - for(i = 0; (hmgeti(lab->segment, i) != -1) || str[i] != 0; i++) { - if(i > 0 && ((hmgeti(lab->segment, i) != -1) || str[i] != '.')) w += Spacing; - if(hmgeti(lab->segment, i) != -1 || ('0' <= str[i] && str[i] <= '9') || ('A' <= str[i] && str[i] <= 'F') || ('a' <= str[i] && str[i] <= 'f')) { - w += l_one + s_one * 2; - } else if(str[i] == ':' || str[i] == ' ') { - w += s_one; - } - } - - w++; - h++; - - raw = malloc(w * h * 4); - memset(raw, 0, w * h * 4); - - for(i = 0; (hmgeti(lab->segment, i) != -1) || str[i] != 0; i++) { - if((hmgeti(lab->segment, i) != -1) || ('0' <= str[i] && str[i] <= '9') || ('A' <= str[i] && str[i] <= 'F') || ('a' <= str[i] && str[i] <= 'f')) { - int la = 0, lb = 0, lc = 0, ld = 0, le = 0, lf = 0, lg = 0; - int j; - - /* https://en.wikipedia.org/wiki/File:7_Segment_Display_with_Labeled_Segments.svg */ - - if(hmgeti(lab->segment, i) != -1) { - unsigned char c = hmget(lab->segment, i); - - if(c & (1 << 0)) la = 1; - if(c & (1 << 1)) lb = 1; - if(c & (1 << 2)) lc = 1; - if(c & (1 << 3)) ld = 1; - if(c & (1 << 4)) le = 1; - if(c & (1 << 5)) lf = 1; - if(c & (1 << 6)) lg = 1; - } else { - if(str[i] == '0') { - la = lb = lc = ld = le = lf = 1; - } else if(str[i] == '1') { - lb = lc = 1; - } else if(str[i] == '2') { - la = lb = ld = le = lg = 1; - } else if(str[i] == '3') { - la = lb = lc = ld = lg = 1; - } else if(str[i] == '4') { - lb = lc = lf = lg = 1; - } else if(str[i] == '5') { - la = lc = ld = lf = lg = 1; - } else if(str[i] == '6') { - la = lc = ld = le = lf = lg = 1; - } else if(str[i] == '7') { - la = lb = lc = 1; - } else if(str[i] == '8') { - la = lb = lc = ld = le = lf = lg = 1; - } else if(str[i] == '9') { - la = lb = lc = ld = lf = lg = 1; - } else if(str[i] == 'A' || str[i] == 'a') { - la = lb = lc = le = lf = lg = 1; - } else if(str[i] == 'B' || str[i] == 'b') { - lc = ld = le = lf = lg = 1; - } else if(str[i] == 'C' || str[i] == 'c') { - ld = le = lg = 1; - } else if(str[i] == 'D' || str[i] == 'd') { - lb = lc = ld = le = lg = 1; - } else if(str[i] == 'E' || str[i] == 'e') { - la = ld = le = lf = lg = 1; - } else if(str[i] == 'F' || str[i] == 'f') { - la = le = lf = lg = 1; - } - } - - for(j = 1; j >= 0; j--) { - MwLLColor cl = j == 1 ? shadow : text; - - if(la) draw_h(handle, raw, x + s_one + j, j, w, cl); - if(lb) draw_v(handle, raw, x + s_one + l_one + j, s_one + j, w, cl); - if(lc) draw_v(handle, raw, x + s_one + l_one + j, s_one * 2 + l_one + j, w, cl); - if(ld) draw_h(handle, raw, x + s_one + j, s_one * 2 + l_one * 2 + j, w, cl); - if(le) draw_v(handle, raw, x + j, s_one * 2 + l_one + j, w, cl); - if(lf) draw_v(handle, raw, x + j, s_one + j, w, cl); - if(lg) draw_h(handle, raw, x + s_one + j, s_one + l_one + j, w, cl); - } - - x += l_one + s_one * 2; - } else if(str[i] == ':') { - int cy, cx; - int j; - for(j = 1; j >= 0; j--) { - MwLLColor cl = j == 1 ? shadow : text; - for(cy = 1; cy < h - 1; cy++) { - int h = s_one / 2; - int c = (l_one - h) / 2 + s_one; - - int c1 = (c <= cy && cy <= (c + h)) ? 1 : 0; - int c2 = ((s_one + l_one + c) <= cy && cy <= (s_one + l_one + c + h)) ? 1 : 0; - - if(c1 || c2) { - for(cx = x; cx < x + s_one; cx++) { - unsigned char* px = &raw[((cy + j) * w + (cx + j)) * 4]; - px[0] = cl->common.red; - px[1] = cl->common.green; - px[2] = cl->common.blue; - px[3] = 255; - } - } - } - } - x += s_one; - } else if(str[i] == ' ') { - x += s_one; - } else if(str[i] == '.') { - int cy, cx; - int j; - for(j = 1; j >= 0; j--) { - MwLLColor cl = j == 1 ? shadow : text; - for(cy = h - (s_one - 1) / 2 - 1; cy < h; cy++) { - for(cx = x - Spacing - (s_one - 1) / 2 - 1; cx < (x - Spacing); cx++) { - unsigned char* px = &raw[((cy + j) * w + (cx + j)) * 4]; - px[0] = cl->common.red; - px[1] = cl->common.green; - px[2] = cl->common.blue; - px[3] = 255; - } - } - } - continue; - } - - x += Spacing; - } - - px = MwLoadRaw(handle, raw, w, h); - - r.y = (r.height - h) / 2; - r.height = h; - if(align == MwALIGNMENT_CENTER) { - r.x = (r.width - w) / 2; - } else if(align == MwALIGNMENT_BEGINNING) { - r.x = 0; - } else if(align == MwALIGNMENT_END) { - r.x = r.width - w; - } - r.width = w; - MwLLDrawPixmap(handle->lowlevel, &r, px); - - free(raw); - - MwLLDestroyPixmap(px); - } else { - r.width -= MwGetInteger(handle, MwNleftPadding); - - if(align == MwALIGNMENT_CENTER) { - p.x = r.width / 2; - } else if(align == MwALIGNMENT_BEGINNING) { - p.x = MwTextWidth(handle, NULL, str) / 2; - } else if(align == MwALIGNMENT_END) { - p.x = r.width - MwTextWidth(handle, NULL, str) / 2; - } - p.y = r.height / 2; - - p.x += MwGetInteger(handle, MwNleftPadding); - - p.x += 1; - p.y += 1; - MwDrawText(handle, NULL, &p, str, MwALIGNMENT_CENTER, shadow); - - p.x -= 1; - p.y -= 1; - MwDrawText(handle, NULL, &p, str, MwALIGNMENT_CENTER, text); + if(align == MwALIGNMENT_CENTER) { + p.x = r.width / 2; + } else if(align == MwALIGNMENT_BEGINNING) { + p.x = MwTextWidth(handle, NULL, str) / 2; + } else if(align == MwALIGNMENT_END) { + p.x = r.width - MwTextWidth(handle, NULL, str) / 2; } + p.y = r.height / 2; + + p.x += MwGetInteger(handle, MwNleftPadding); + + p.x += 1; + p.y += 1; + MwDrawText(handle, NULL, &p, str, MwALIGNMENT_CENTER, shadow); + + p.x -= 1; + p.y -= 1; + MwDrawText(handle, NULL, &p, str, MwALIGNMENT_CENTER, text); MwLLFreeColor(shadow); MwLLFreeColor(text); @@ -348,6 +371,8 @@ static void mwLabelSetSevenSegmentImpl(MwWidget handle, int index, unsigned char MwLabel lab = handle->internal; hmput(lab->segment, index, data); + + handle->widget_class->draw = draw_seven_segment; } static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { @@ -364,7 +389,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v MwClassRec MwLabelClassRec = { wcreate, /* create */ destroy, /* destroy */ - draw, /* draw */ + draw_normal, /* draw */ NULL, /* click */ NULL, /* parent_resize */ prop_change, /* prop_change */