ref: 4a0b3479f227e484b1a65b6443ba59a7bdb49962
dir: /cardgen.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
/* configuration parameters */
/* card dimensions */
int cardwid = 200;
int cardhgt = 300;
/* radius for card corners (for template card) */
int cardrad = 7;
/* symbol dimensions */
int symwid = 30;
int symhgt = 30;
/* symbol locations */
Point symlocs[2] = {
{ 10, 10 },
{ 200-30-10, 300-30-10 },
};
/* label locations */
Point lbllocs[2] = {
{ 10+30+10, 10+15 },
{ 200-30-10-10, 300-30-10+15 },
};
/* label alignment */
/* 0 left, 1 right */
int lblalign[2] = {
0,
1,
};
/* labels for card values */
/* nils will be skipped */
char *labels[15] = {
nil,
nil,
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"J (11)",
"Q (12)",
"K (13)",
"A (14)",
};
/* code */
static void
usage(void)
{
fprint(2, "usage: %s [-dt] [-f subfont]\n", argv0);
exits("usage");
}
Memimage *memred;
Memimage *memgreen;
Memsubfont *memfont;
int fontheight;
int debug = 0;
static void
drawspades(Memimage *mi)
{
/*
/\
* *
|
*/
Point c, p, q;
int d, r;
Point tip[3];
Point bot[5];
r = Dx(mi->r)/5;
c.x = Dx(mi->r)/2 - 1;
c.y = Dy(mi->r)/2 - 1;
/* points */
d = Dx(mi->r)/4.5;
p.x = c.x - d;
p.y = c.y+1;
q.x = c.x;
q.y = Dy(mi->r)/4;
memimageline(mi, p, q, Enddisc, Enddisc, r, memblack, ZP, SoverD);
p.x = c.x + d;
memimageline(mi, p, q, Enddisc, Enddisc, r, memblack, ZP, SoverD);
tip[0] = Pt(c.x+d/2, (p.y - q.y)/2);
tip[1] = Pt(c.x, (p.y - q.y)/10-1);
tip[2] = Pt(c.x-d/2, (p.y - q.y)/2);
bot[0] = Pt(c.x, c.y);
d = Dx(mi->r)/10.;
r = Dx(mi->r)/6.;
bot[1] = Pt(c.x-d, Dy(mi->r)/15.*13.);
bot[2] = Pt(c.x-r, Dy(mi->r)/15.*14.5);
bot[3] = Pt(c.x+r, Dy(mi->r)/15.*14.5);
bot[4] = Pt(c.x+d, Dy(mi->r)/15.*13.);
memfillpoly(mi, tip, nelem(tip), 0, memblack, ZP, SoverD);
memfillpoly(mi, bot, nelem(bot), 0, memblack, ZP, SoverD);
}
static void
drawclubs(Memimage *mi)
{
/*
*
* *
|
*/
Point p;
int r;
int cx;
float d;
r = Dx(mi->r) / 4.5;
d = 4.;
/* center point */
p.x = cx = Dx(mi->r) / 2 -1;
p.y = Dy(mi->r) / 5 + 1;
memimageline(mi, p, p, Enddisc, Enddisc, r, memblack, ZP, SoverD);
/* left point */
p.y = Dy(mi->r) / 2 + 1;
p.x = cx - Dx(mi->r) / d;
memimageline(mi, p, p, Enddisc, Enddisc, r, memblack, ZP, SoverD);
/* right point */
p.x = cx + Dx(mi->r) / d;
memimageline(mi, p, p, Enddisc, Enddisc, r, memblack, ZP, SoverD);
/* line */
p.x = Dx(mi->r) / 2 -1;
p.y = Dy(mi->r) / 5 + 1;
memimageline(mi, p, Pt(p.x, Dy(mi->r)/15.*14.),
Endsquare, Endsquare, Dx(mi->r)/20, memblack, ZP, SoverD);
}
static void
drawhearts(Memimage *mi)
{
/*
* *
\/
*/
Point p, q, c;
int r, d;
float f = 0.7;
c.x = Dx(mi->r)/2 - 1;
c.y = Dy(mi->r)/2;
r = Dx(mi->r)/4.5;
d = Dx(mi->r)/4.5;
p.x = c.x - d;
p.y = c.y - d;
q.x = c.x + r*f;
q.y = c.y + r*f;
memimageline(mi, p, q, Enddisc, Endsquare, r, memred, ZP, SoverD);
p.x = c.x + d;
q.x = c.x - r*f;
memimageline(mi, p, q, Enddisc, Endsquare, r, memred, ZP, SoverD);
}
static void
drawdiamonds(Memimage *mi)
{
/* circle, starting at (1.0, 0.0), counterclockwise. */
Point p[12];
Point c;
int i;
float x, y, f;
float outer, inner;
/* outer distance: diamond corners.
inner distance: inner curve. */
outer = Dx(mi->r)/2.;
inner = Dx(mi->r)/3.4;
c.x = Dx(mi->r)/2. -1;
c.y = Dy(mi->r)/2. -1;
for (i = 0; i < nelem(p); i++) {
f = ( ((float)i) / nelem(p) ) * PI*2.;
x = cos(f);
y = sin(f);
f = i%3 == 0 ? outer : inner;
p[i].x = c.x + x * f;
p[i].y = c.y + y * f;
}
memfillpoly(mi, p, nelem(p), 0, memred, ZP, SoverD);
}
static void
drawborder(Memimage *mi)
{
memimageline(mi,
Pt(mi->r.min.x, mi->r.min.y),
Pt(mi->r.max.x, mi->r.min.y),
Endsquare, Endsquare, 0, memblack, ZP, S);
memimageline(mi,
Pt(mi->r.max.x-1, mi->r.min.y),
Pt(mi->r.max.x-1, mi->r.max.y),
Endsquare, Endsquare, 0, memblack, ZP, S);
memimageline(mi,
Pt(mi->r.max.x, mi->r.max.y-1),
Pt(mi->r.min.x, mi->r.max.y-1),
Endsquare, Endsquare, 0, memblack, ZP, S);
memimageline(mi,
Pt(mi->r.min.x, mi->r.max.y),
Pt(mi->r.min.x, mi->r.min.y),
Endsquare, Endsquare, 0, memblack, ZP, S);
}
int gentemplates = 0;
static void
dogentemplates(void)
{
Memimage *mi;
int fcard;
int fsym;
int fdiamonds;
int fhearts;
int fclubs;
int fspades;
Rectangle r;
Point p;
fcard = create("tcard", OWRITE, 0664);
if (fcard < 0)
sysfatal("%r");
fsym = create("tsym", OWRITE, 0664);
if (fsym < 0)
sysfatal("%r");
fdiamonds = create("tsym0", OWRITE, 0664);
if (fdiamonds < 0)
sysfatal("%r");
fhearts = create("tsym1", OWRITE, 0664);
if (fhearts < 0)
sysfatal("%r");
fclubs = create("tsym2", OWRITE, 0664);
if (fclubs < 0)
sysfatal("%r");
fspades = create("tsym3", OWRITE, 0664);
if (fspades < 0)
sysfatal("%r");
#define FINISH(A) drawborder(mi);writememimage(A, mi);freememimage(mi);close(A);
mi = allocmemimage(Rect(-1, -1, cardwid+1, cardhgt+1), RGBA32);
if (!mi)
sysfatal("%r");
memfillcolor(mi, DTransparent);
p = Pt(cardrad*2, cardrad*2);
memimageline(mi, p, p, Enddisc, Enddisc, cardrad*2, memwhite, ZP, SoverD);
p = Pt(cardwid-cardrad*2, cardrad*2);
memimageline(mi, p, p, Enddisc, Enddisc, cardrad*2, memwhite, ZP, SoverD);
p = Pt(cardwid-cardrad*2, cardhgt-cardrad*2);
memimageline(mi, p, p, Enddisc, Enddisc, cardrad*2, memwhite, ZP, SoverD);
p = Pt(cardrad*2, cardhgt-cardrad*2);
memimageline(mi, p, p, Enddisc, Enddisc, cardrad*2, memwhite, ZP, SoverD);
r.min = Pt(cardrad*2, 0);
r.max = Pt(cardwid-cardrad*2, cardhgt);
memdraw(mi, r, memwhite, ZP, nil, ZP, S);
r.min = Pt(0, cardrad*2);
r.max = Pt(cardwid, cardhgt-cardrad*2);
memdraw(mi, r, memwhite, ZP, nil, ZP, S);
FINISH(fcard)
mi = allocmemimage(Rect(-1, -1, symwid+1, symhgt+1), RGBA32);
if (!mi)
sysfatal("%r");
memfillcolor(mi, DTransparent);
FINISH(fsym);
mi = allocmemimage(Rect(-1, -1, symwid+1, symhgt+1), RGBA32);
if (!mi)
sysfatal("%r");
memfillcolor(mi, DTransparent);
drawdiamonds(mi);
FINISH(fdiamonds);
mi = allocmemimage(Rect(-1, -1, symwid+1, symhgt+1), RGBA32);
if (!mi)
sysfatal("%r");
memfillcolor(mi, DTransparent);
drawhearts(mi);
FINISH(fhearts);
mi = allocmemimage(Rect(-1, -1, symwid+1, symhgt+1), RGBA32);
if (!mi)
sysfatal("%r");
memfillcolor(mi, DTransparent);
drawclubs(mi);
FINISH(fclubs);
mi = allocmemimage(Rect(-1, -1, symwid+1, symhgt+1), RGBA32);
if (!mi)
sysfatal("%r");
memfillcolor(mi, DTransparent);
drawspades(mi);
FINISH(fspades);
#undef FINISH
}
static Memimage*
load(char *name)
{
Memimage *mi;
int fd;
fd = open(name, OREAD);
if (fd < 0)
sysfatal("%r");
mi = readmemimage(fd);
if (!mi)
sysfatal("creadmemimage %s: %r", name);
close(fd);
return mi;
}
Memimage *card;
Memimage *syms[4];
static void
gencard(int num, Memimage *sym, int fadd, Memimage *face)
{
Memimage *mi;
int i, fd;
char *file;
char *label;
Point text;
Point p;
Rectangle r;
label = labels[num];
if (!label)
return;
text = memsubfontwidth(memfont, label);
mi = allocmemimage(Rect(0, 0, cardwid, cardhgt), RGBA32);
if (!mi)
sysfatal("%r");
memfillcolor(mi, DTransparent);
memdraw(mi, mi->r, card, ZP, nil, ZP, S);
r = insetrect(sym->r, 1);
for (i = 0; i < nelem(symlocs); i++) {
memdraw(mi, rectaddpt(r, symlocs[i]), sym, ZP, nil, ZP, SatopD);
}
for (i = 0; i < nelem(lbllocs); i++) {
p = lbllocs[i];
if (lblalign[i])
p.x -= text.x;
if (debug)
memimageline(mi, p, p, Enddisc, Enddisc, 0, memgreen, ZP, SoverD);
p.y -= fontheight/2.;
memimagestring(mi, p, memblack, ZP, memfont, label);
}
if (face) {
p.x = (Dx(mi->r) - Dx(face->r))/2.;
p.y = (Dy(mi->r) - Dy(face->r))/2.;
memdraw(mi, rectaddpt(face->r, p), face, ZP, nil, ZP, SatopD);
}
file = smprint("out/%d", num+fadd);
if (!file)
sysfatal("%r");
fd = create(file, OWRITE, 0644);
if (fd < 0)
sysfatal("%r");
writememimage(fd, mi);
freememimage(mi);
close(fd);
}
static Memimage*
loadface(int value, int color)
{
char file[512];
int fd;
Memimage *mi;
snprint(file, sizeof file, "face/%d.%d", color, value);
fd = open(file, OREAD);
if (fd < 0)
return nil;
mi = readmemimage(fd);
close(fd);
return mi;
}
void
main(int argc, char **argv)
{
int i, j;
char *fontfile = getenv("cardfont");
Memimage *face;
ARGBEGIN{
case 't':
gentemplates++;
break;
case 'f':
fontfile = EARGF(usage());
break;
case 'd':
debug++;
break;
case 'h':
usage();
}ARGEND;
if (memimageinit() < 0)
sysfatal("memimageinit: %r");
memred = allocmemimage(Rect(0, 0, 1, 1), RGB24);
memfillcolor(memred, 0xFF0000FF);
memred->flags |= Frepl;
memred->clipr = memblack->clipr;
memgreen = allocmemimage(Rect(0, 0, 1, 1), RGB24);
memfillcolor(memgreen, 0x00CC00FF);
memgreen->flags |= Frepl;
memgreen->clipr = memblack->clipr;
if (fontfile) {
memfont = openmemsubfont(fontfile, 0);
if (!memfont)
fprint(2, "error: %r. Falling back to default font!\n");
}
if (!memfont)
memfont = getmemdefont();
fontheight = memsubfontwidth(memfont, "M").y;
if (gentemplates) {
dogentemplates();
exits(nil);
}
card = load("card");
syms[0] = load("sym0");
syms[1] = load("sym1");
syms[2] = load("sym2");
syms[3] = load("sym3");
for (j = 0; j < 4; j++) {
for (i = 0; i < nelem(labels); i++) {
face = loadface(i, j);
gencard(i, syms[j], j*nelem(labels), face);
freememimage(face);
}
}
exits(nil);
}