popup: refine the input panel
This commit is contained in:
@@ -1,6 +1,41 @@
|
||||
#include "test.h"
|
||||
#include <limits.h>
|
||||
|
||||
enum {
|
||||
Rgbmask = 0xffffff,
|
||||
};
|
||||
|
||||
static u32int
|
||||
pixel(u32int *img, Popup *p, int x, int y)
|
||||
{
|
||||
return img[y*p->w + x] & Rgbmask;
|
||||
}
|
||||
|
||||
static int
|
||||
rectcolor(u32int *img, Popup *p, int x0, int y0, int x1, int y1,
|
||||
u32int color)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
color &= Rgbmask;
|
||||
for(y = y0; y < y1; y++)
|
||||
for(x = x0; x < x1; x++)
|
||||
if(pixel(img, p, x, y) != color)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
checkpadding(struct ct *t, u32int *img, Popup *p)
|
||||
{
|
||||
CT_CHECK(t, rectcolor(img, p, 0, 0, p->w, PopupPad, Colbg));
|
||||
CT_CHECK(t, rectcolor(img, p, 0, p->h - PopupPad,
|
||||
p->w, p->h, Colbg));
|
||||
CT_CHECK(t, rectcolor(img, p, 0, 0, PopupPad, p->h, Colbg));
|
||||
CT_CHECK(t, rectcolor(img, p, p->w - PopupPad, 0,
|
||||
p->w, p->h, Colbg));
|
||||
}
|
||||
|
||||
void
|
||||
popup_layout(struct ct *t)
|
||||
{
|
||||
@@ -22,7 +57,11 @@ popup_layout(struct ct *t)
|
||||
};
|
||||
char buf[32];
|
||||
Caret caret;
|
||||
int i, n, x, y;
|
||||
Drawcmd dc;
|
||||
Popup p;
|
||||
Str longrow;
|
||||
u32int c, *img;
|
||||
int i, ink, markink, n, numink, selbg, textink, x, y;
|
||||
|
||||
for(i = 0; i < nelem(markers); i++){
|
||||
n = pagemarker(buf, sizeof buf, markers[i].first,
|
||||
@@ -30,7 +69,8 @@ popup_layout(struct ct *t)
|
||||
CT_EQ_INT(t, strlen(markers[i].want), n);
|
||||
CT_CHECK(t, strcmp(markers[i].want, buf) == 0);
|
||||
}
|
||||
CT_EQ_INT(t, (1 + Maxdisp + 1) * Fontsz, Imgh);
|
||||
CT_EQ_INT(t, 2*PopupPad + (1 + Maxdisp + 1)*Fontsz + PopupSep,
|
||||
Imgh);
|
||||
|
||||
memset(&caret, 0, sizeof caret);
|
||||
popupposition(&caret, 40, 50, 800, 600, 100, 60, &x, &y);
|
||||
@@ -81,4 +121,157 @@ popup_layout(struct ct *t)
|
||||
INT_MAX, INT_MAX, &x, &y);
|
||||
CT_EQ_INT(t, 0, x);
|
||||
CT_EQ_INT(t, 0, y);
|
||||
|
||||
if(!CT_CHECK(t, textinit()))
|
||||
return;
|
||||
|
||||
/* Empty sections reserve nothing. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.sel = -1;
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, 0, p.w);
|
||||
CT_EQ_INT(t, 0, p.h);
|
||||
CT_EQ_INT(t, -1, p.prey);
|
||||
CT_EQ_INT(t, -1, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
|
||||
/* Preedit only. */
|
||||
dc.pre = mkstr("preedit");
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, PopupPad, p.prey);
|
||||
CT_EQ_INT(t, -1, p.sepy);
|
||||
CT_EQ_INT(t, -1, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
CT_EQ_INT(t, 2*PopupPad + Fontsz, p.h);
|
||||
|
||||
/* Candidates only. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.sel = -1;
|
||||
dc.nkouho = 2;
|
||||
dc.kouho[0] = mkstr("short");
|
||||
dc.kouho[1] = mkstr("candidate");
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, -1, p.prey);
|
||||
CT_EQ_INT(t, -1, p.sepy);
|
||||
CT_EQ_INT(t, PopupPad, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
CT_EQ_INT(t, 2*PopupPad + 2*Fontsz, p.h);
|
||||
CT_EQ_INT(t, PopupPad, p.numx);
|
||||
CT_EQ_INT(t, p.numx + PopupNumw, p.textx);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.textx + p.textw);
|
||||
|
||||
/* Preedit and candidates meet at one separator, with no empty rows. */
|
||||
dc.pre = mkstr("preedit");
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, PopupPad, p.prey);
|
||||
CT_EQ_INT(t, p.prey + Fontsz, p.sepy);
|
||||
CT_EQ_INT(t, p.sepy + PopupSep, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
CT_EQ_INT(t, p.rowsy + 2*Fontsz + PopupPad, p.h);
|
||||
CT_EQ_INT(t, 2*PopupPad + 3*Fontsz + PopupSep, p.h);
|
||||
|
||||
/* The largest panel includes all sections and fits its backing image. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.pre = mkstr("preedit");
|
||||
dc.nkouho = Maxdisp;
|
||||
dc.sel = 4;
|
||||
dc.first = 0;
|
||||
dc.total = Maxdisp + 1;
|
||||
sclear(&longrow);
|
||||
for(i = 0; i < Maxrunes; i++)
|
||||
sputr(&longrow, 'W');
|
||||
for(i = 0; i < Maxdisp; i++)
|
||||
dc.kouho[i] = mkstr(i == dc.sel ? "M" : "candidate");
|
||||
dc.kouho[0] = longrow;
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, Maxdisp, p.n);
|
||||
CT_EQ_INT(t, PopupPad, p.prey);
|
||||
CT_EQ_INT(t, p.prey + Fontsz, p.sepy);
|
||||
CT_EQ_INT(t, p.sepy + PopupSep, p.rowsy);
|
||||
CT_EQ_INT(t, p.rowsy + Maxdisp*Fontsz, p.marky);
|
||||
CT_EQ_INT(t, p.marky + Fontsz + PopupPad, p.h);
|
||||
CT_EQ_INT(t, Imgh, p.h);
|
||||
CT_CHECK(t, p.w > 2*PopupPad + PopupNumw);
|
||||
CT_CHECK(t, p.w <= Imgw);
|
||||
CT_CHECK(t, p.h <= Imgh);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.markx + p.markw);
|
||||
CT_EQ_INT(t, PopupPad, p.selx);
|
||||
CT_EQ_INT(t, p.w - 2*PopupPad, p.selw);
|
||||
CT_EQ_INT(t, p.rowsy + dc.sel*Fontsz, p.sely);
|
||||
CT_EQ_INT(t, PopupPad, p.numx);
|
||||
CT_EQ_INT(t, p.numx + PopupNumw, p.textx);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.textx + p.textw);
|
||||
|
||||
img = emalloc(Imgw*Imgh*sizeof img[0]);
|
||||
popupdraw(img, &dc, &p);
|
||||
checkpadding(t, img, &p);
|
||||
for(x = 0; x < p.w; x++)
|
||||
CT_EQ_UINT(t,
|
||||
x >= PopupPad && x < p.w - PopupPad ? Colsep : Colbg,
|
||||
pixel(img, &p, x, p.sepy));
|
||||
|
||||
/* Selection paint and both foreground columns stay inside the row. */
|
||||
selbg = numink = textink = 0;
|
||||
for(y = p.sely; y < p.sely + Fontsz; y++){
|
||||
for(x = 0; x < p.w; x++){
|
||||
c = pixel(img, &p, x, y);
|
||||
if(x < p.selx || x >= p.selx + p.selw){
|
||||
CT_EQ_UINT(t, Colbg, c);
|
||||
continue;
|
||||
}
|
||||
if(c == (Colsel & Rgbmask)){
|
||||
selbg++;
|
||||
continue;
|
||||
}
|
||||
CT_CHECK(t,
|
||||
(x >= p.numx && x < p.numx + PopupNumw) ||
|
||||
(x >= p.textx && x < p.textx + p.textw));
|
||||
if(x < p.numx + PopupNumw)
|
||||
numink++;
|
||||
else
|
||||
textink++;
|
||||
}
|
||||
}
|
||||
CT_CHECK(t, Colsel != Colselfg);
|
||||
CT_CHECK(t, selbg > p.selw*Fontsz/2);
|
||||
CT_CHECK(t, numink > 0);
|
||||
CT_CHECK(t, textink > 0);
|
||||
|
||||
/* The marker occupies only its compact, right-aligned footer box. */
|
||||
markink = 0;
|
||||
for(y = p.marky; y < p.marky + Fontsz; y++){
|
||||
for(x = 0; x < p.w; x++){
|
||||
if(pixel(img, &p, x, y) == (Colbg & Rgbmask))
|
||||
continue;
|
||||
markink++;
|
||||
CT_CHECK(t, x >= p.markx && x < p.markx + p.markw);
|
||||
}
|
||||
}
|
||||
CT_CHECK(t, markink > 0);
|
||||
|
||||
/* A fitted long row is bounded by the fixed candidate content area. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.sel = -1;
|
||||
dc.nkouho = 1;
|
||||
dc.kouho[0] = longrow;
|
||||
n = textwidth(&longrow);
|
||||
popuplayout(&dc, 6*Fontsz, &p);
|
||||
CT_CHECK(t, n > p.textw);
|
||||
CT_EQ_INT(t, PopupPad, p.rowsy);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.textx + p.textw);
|
||||
popupdraw(img, &dc, &p);
|
||||
ink = 0;
|
||||
for(y = p.rowsy; y < p.rowsy + Fontsz; y++){
|
||||
for(x = 0; x < p.w; x++){
|
||||
c = pixel(img, &p, x, y);
|
||||
if(x < PopupPad || x >= p.w - PopupPad)
|
||||
CT_EQ_UINT(t, Colbg, c);
|
||||
if(x >= p.textx && x < p.textx + p.textw &&
|
||||
c != (Colbg & Rgbmask))
|
||||
ink++;
|
||||
}
|
||||
}
|
||||
CT_CHECK(t, ink > 0);
|
||||
CT_EQ_INT(t, n, textwidth(&longrow));
|
||||
free(img);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user