278 lines
7.0 KiB
C
278 lines
7.0 KiB
C
#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)
|
|
{
|
|
static const struct {
|
|
int first;
|
|
int shown;
|
|
int total;
|
|
char *want;
|
|
} markers[] = {
|
|
{ 0, 0, 0, "" },
|
|
{ 0, 9, 9, "" },
|
|
{ 0, 9, 10, "1-9/10" },
|
|
{ 9, 1, 10, "10-10/10" },
|
|
{ 0, 9, 18, "1-9/18" },
|
|
{ 9, 9, 18, "10-18/18" },
|
|
{ 9, 9, 32, "10-18/32" },
|
|
{ 18, 9, 32, "19-27/32" },
|
|
{ 27, 5, 32, "28-32/32" },
|
|
};
|
|
char buf[32];
|
|
Caret caret;
|
|
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,
|
|
markers[i].shown, markers[i].total);
|
|
CT_EQ_INT(t, strlen(markers[i].want), n);
|
|
CT_CHECK(t, strcmp(markers[i].want, buf) == 0);
|
|
}
|
|
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);
|
|
CT_EQ_INT(t, 50, x);
|
|
CT_EQ_INT(t, 60, y);
|
|
caret.valid = 1;
|
|
caret.x = 70;
|
|
caret.y = 80;
|
|
caret.h = 20;
|
|
popupposition(&caret, 40, 50, 800, 600, 100, 60, &x, &y);
|
|
CT_EQ_INT(t, 70, x);
|
|
CT_EQ_INT(t, 100, y);
|
|
caret.x = 790;
|
|
caret.y = 590;
|
|
popupposition(&caret, 0, 0, 800, 600, 100, 60, &x, &y);
|
|
CT_EQ_INT(t, 700, x);
|
|
CT_EQ_INT(t, 530, y);
|
|
|
|
/* Neither side fits: choose above, then clamp to the screen. */
|
|
caret.x = 20;
|
|
caret.y = 30;
|
|
caret.h = 20;
|
|
popupposition(&caret, 0, 0, 80, 80, 100, 100, &x, &y);
|
|
CT_EQ_INT(t, 0, x);
|
|
CT_EQ_INT(t, 0, y);
|
|
|
|
caret.x = 70;
|
|
caret.y = 80;
|
|
caret.h = 0;
|
|
popupposition(&caret, 0, 0, 800, 600, 100, 60, &x, &y);
|
|
CT_EQ_INT(t, 70, x);
|
|
CT_EQ_INT(t, 80, y);
|
|
caret.h = -20;
|
|
popupposition(&caret, 0, 0, 800, 600, 100, 60, &x, &y);
|
|
CT_EQ_INT(t, 70, x);
|
|
CT_EQ_INT(t, 80, y);
|
|
|
|
caret.x = INT_MIN;
|
|
caret.y = INT_MAX;
|
|
caret.h = INT_MAX;
|
|
popupposition(&caret, 0, 0, 800, 600, 100, 60, &x, &y);
|
|
CT_EQ_INT(t, 0, x);
|
|
CT_EQ_INT(t, 540, y);
|
|
caret.x = INT_MAX;
|
|
caret.y = INT_MIN;
|
|
caret.h = INT_MIN;
|
|
popupposition(&caret, 0, 0, INT_MAX, INT_MAX,
|
|
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);
|
|
}
|