ao_font.h: $(FONT_SRCS)
grep -h '^const struct ao_font' $(FONT_SRCS) | sed -e 's/^/extern /' -e 's/ =.*$$/;/' > $@
-ao_logo.h: make-logo Makefile
- nickle make-logo ao_logo 48 0 10 > $@
+ao_logo.h: make-logo
+ nickle make-logo ao_logo > $@
SRCS=\
draw-test.c \
LIBS=-lXrender -lX11 -lm
-CFLAGS=-O0 -g
+CFLAGS=-O2 -g $(WARN_FLAGS)
HEADERS=\
ao_draw.h \
#define bound(val,max,other) do { \
if (val < 0) { \
- other -= val; \
+ other += (typeof(other)) (-val); \
val = 0; \
} \
if (val > max) { \
- other -= (val - max); \
+ other -= (typeof(other)) (val - max); \
val = max; \
} \
} while (0)
float x, y;
};
+struct ao_transform {
+ float x_scale, x_off;
+ float y_scale, y_off;
+};
+
+static inline float ao_t_x(float x, float y, const struct ao_transform *t)
+{
+ (void) y;
+ return x * t->x_scale + t->x_off;
+}
+
+static inline int16_t ao_t_xi(float x, float y, const struct ao_transform *t)
+{
+ return (int16_t) (ao_t_x(x, y, t) + 0.5f);
+}
+
+static inline float ao_t_y(float x, float y, const struct ao_transform *t)
+{
+ (void) x;
+ return y * t->y_scale + t->y_off;
+}
+
+static inline int16_t ao_t_yi(float x, float y, const struct ao_transform *t)
+{
+ return (int16_t) (ao_t_y(x, y, t) + 0.5f);
+}
+
+static inline float ao_t_x_c(const struct ao_coord *c,
+ const struct ao_transform *t)
+{
+ return ao_t_x(c->x, c->y, t);
+}
+
+static inline float ao_t_y_c(const struct ao_coord *c,
+ const struct ao_transform *t)
+{
+ return ao_t_y(c->x, c->y, t);
+}
+
+static inline int16_t
+ao_stride(int16_t width)
+{
+ return (int16_t) ((width + 31) >> 5);
+}
+
+static inline int16_t
+ao_stride_bytes(int16_t width)
+{
+ return (int16_t) ((width + 7) >> 3);
+}
+
struct ao_pattern {
uint8_t pattern[8];
};
const uint8_t *bytes;
const uint16_t *pos;
const struct ao_glyph_metrics *metrics;
- int max_width;
- int max_height;
- int ascent;
+ int16_t max_width;
+ int16_t max_height;
+ int16_t ascent;
};
void
uint8_t rop);
void
-ao_poly(const struct ao_bitmap *dst,
- const struct ao_coord *coords,
- uint16_t ncoords,
- uint32_t fill,
- uint8_t rop);
+ao_poly(const struct ao_bitmap *dst,
+ const struct ao_coord *coords,
+ uint16_t ncoords,
+ const struct ao_transform *transform,
+ uint32_t fill,
+ uint8_t rop);
void
ao_text(const struct ao_bitmap *dst,
uint8_t rop);
void
-ao_logo(const struct ao_bitmap *dst,
- const struct ao_font *font,
- uint32_t fill,
- uint8_t rop);
+ao_logo(const struct ao_bitmap *dst,
+ const struct ao_transform *transform,
+ const struct ao_font *font,
+ uint32_t fill,
+ uint8_t rop);
-extern const struct ao_font FrutigerLT_Roman_50_font;
+extern const struct ao_transform ao_identity;
#define AO_SHIFT 5
#define AO_UNIT (1 << AO_SHIFT)
r = ao_right_mask((x)+n); \
l = ao_left_mask(x); \
if (l) { \
- n -= AO_UNIT - ((x) & AO_MASK); \
+ n -= (int16_t) (AO_UNIT - ((x) & AO_MASK)); \
if (n < 0) { \
n = 0; \
l &= r; \
/* -b <= a, so we need to make a bigger */
static int16_t
div_ceil(int32_t a, int16_t b) {
- return (a + b + b - 1) / b - 1;
+ return (int16_t) ((a + b + b - 1) / b - 1);
}
static int16_t
div_floor_plus_one(int32_t a, int16_t b) {
- return (a + b) / b;
+ return (int16_t) ((a + b) / b);
}
static int8_t
adjust_minor = adj_min;
}
- c->e += adjust_major * c->e1 + adjust_minor * c->e3;
+ c->e = (int16_t) (c->e + adjust_major * c->e1 + adjust_minor * c->e3);
- c->major += c->sign_major * adjust_major;
- c->minor += c->sign_minor * adjust_minor;
+ c->major = (int16_t) (c->major + c->sign_major * adjust_major);
+ c->minor = (int16_t) (c->minor + c->sign_minor * adjust_minor);
return true;
}
if (adx > ady) {
axis = X_AXIS;
e1 = ady << 1;
- e2 = e1 - (adx << 1);
+ e2 = e1 - (int16_t) (adx << 1);
e = e1 - adx;
clip_1.major = x1;
} else {
axis = Y_AXIS;
e1 = adx << 1;
- e2 = e1 - (ady << 1);
+ e2 = e1 - (int16_t) (ady << 1);
e = e1 - ady;
clip_1.major = y1;
if (!ao_clip_line(&clip_2, &cbox))
return;
- len = clip_1.sign_major * (clip_2.major - clip_1.major) + clip_2.first;
+ len = (int16_t) (clip_1.sign_major * (clip_2.major - clip_1.major) + clip_2.first);
if (len <= 0)
return;
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
void
-ao_logo(const struct ao_bitmap *dst,
- const struct ao_font *font,
- uint32_t fill,
- uint8_t rop)
+ao_logo(const struct ao_bitmap *dst,
+ const struct ao_transform *transform,
+ const struct ao_font *font,
+ uint32_t fill,
+ uint8_t rop)
{
- ao_poly(dst, ao_logo_top, ARRAYSIZE(ao_logo_top), 0x00000000, AO_COPY);
- ao_poly(dst, ao_logo_bottom, ARRAYSIZE(ao_logo_bottom), 0x00000000, AO_COPY);
- ao_text(dst, font, 38, 31, "Altus", 0x00000000, AO_COPY);
- ao_text(dst, font, 38, 57, "Metrum", 0x00000000, AO_COPY);
+ if (!transform)
+ transform = &ao_identity;
+ int16_t name_x = ao_t_xi(ao_logo_width, 0.0f, transform);
+ int16_t name_y1 = ao_t_yi(ao_logo_width, 0.5f, transform);
+ int16_t name_y2 = ao_t_yi(ao_logo_width, 0.98f, transform);
+ ao_poly(dst, ao_logo_top, ARRAYSIZE(ao_logo_top), transform, fill, rop);
+ ao_poly(dst, ao_logo_bottom, ARRAYSIZE(ao_logo_bottom), transform, fill, rop);
+ ao_text(dst, font, name_x, name_y1, "Altus", fill, rop);
+ ao_text(dst, font, name_x, name_y2, "Metrum", fill, rop);
}
uint32_t r;
if (rot)
- v = ao_left(v, 8-rot) | ao_right(v, rot);
+ v = (uint8_t) ao_left(v, 8-rot) | (uint8_t) ao_right(v, rot);
r = v;
return (r << 24) | (r << 16) | (r << 8) | (r);
}
ao_clip(y2, 0, dst->height);
if (x < x2 && y < y2) {
- int xrot = (x - pat_x) & 7;
- int yrot = (y - pat_y) & 7;
- int i;
+ uint8_t xrot = (x - pat_x) & 7;
+ uint8_t yrot = (y - pat_y) & 7;
+ uint8_t i;
int16_t dst_x, dst_y;
for (i = 0; i < 8; i++)
pat[(i + yrot) & 7] = ao_pattern_expand(pattern->pattern[i], xrot);
for (dst_y = y; dst_y < y2; dst_y += 8) {
- int h = min(y2 - dst_y, 8);
+ int16_t h = (int16_t) min(y2 - dst_y, 8);
for (dst_x = x; dst_x < x2; dst_x += 8) {
- int w = min(x2 - dst_x, 8);
+ int16_t w = (int16_t) min(x2 - dst_x, 8);
ao_blt(pat, 1, 0,
dst->base + dst_y * dst->stride,
#include <math.h>
#include <float.h>
+const struct ao_transform ao_identity = {
+ .x_scale = 1.0f, .x_off = 0.0f,
+ .y_scale = 1.0f, .y_off = 0.0f
+};
+
+static float
+_x(const struct ao_coord *coords,
+ const struct ao_transform *transform,
+ uint16_t coord)
+{
+ return ao_t_x_c(&coords[coord], transform);
+}
+
+static float
+_y(const struct ao_coord *coords,
+ const struct ao_transform *transform,
+ uint16_t coord)
+{
+ return ao_t_y_c(&coords[coord], transform);
+}
+
+static uint16_t
+_next(uint16_t ncoords, uint16_t edge)
+{
+ return edge == ncoords - 1 ? 0 : edge + 1;
+}
+
/*
* Return if the given edge is 'live' at the specified y coordinate.
* That means the edge spans the y value. Horizontal lines are never
static bool
ao_edge_live(const struct ao_coord *coords,
uint16_t ncoords,
+ const struct ao_transform *transform,
uint16_t edge,
float y)
{
- int next_edge = (edge == ncoords - 1) ? 0 : edge + 1;
- float y1 = coords[edge].y;
- float y2 = coords[next_edge].y;
+ float y1 = _y(coords, transform, edge);
+ float y2 = _y(coords, transform, _next(ncoords, edge));
if (y1 > y2)
return y2 <= y && y < y1;
* Compute the X coordinate for a given edge at a specified y value
*/
static int16_t
-ao_edge_x(const struct ao_coord *coords,
- uint16_t ncoords,
- uint16_t edge,
- float y)
+ao_edge_x(const struct ao_coord *coords,
+ uint16_t ncoords,
+ const struct ao_transform *transform,
+ uint16_t edge,
+ float y)
{
- int next_edge = (edge == ncoords - 1) ? 0 : edge + 1;
- float x1 = coords[edge].x;
- float x2 = coords[next_edge].x;
- float y1 = coords[edge].y;
- float y2 = coords[next_edge].y;
+ uint16_t next_edge = _next(ncoords, edge);
+ float x1 = _x(coords, transform, edge);
+ float x2 = _x(coords, transform, next_edge);
+ float y1 = _y(coords, transform, edge);
+ float y2 = _y(coords, transform, next_edge);
float dx = x2 - x1;
float dy = y2 - y1;
float off_y = y - y1;
- return x1 + (off_y * dx) / dy;
+ return (int16_t) (x1 + (off_y * dx) / dy + 0.5f);
}
struct next_x {
* if there are no more edges.
*/
static bool
-ao_next_x(const struct ao_coord *coords,
- uint16_t ncoords,
- struct next_x *this_x,
- float y)
+ao_next_x(const struct ao_coord *coords,
+ uint16_t ncoords,
+ const struct ao_transform *transform,
+ struct next_x *this_x,
+ float y)
{
uint16_t edge;
float next_x = FLT_MAX;
bool ret = false;
for (edge = 0; edge < ncoords; edge++) {
- if (ao_edge_live(coords, ncoords, edge, y)) {
- float nx = ao_edge_x(coords, ncoords, edge, y);
+ if (ao_edge_live(coords, ncoords, transform, edge, y)) {
+ float nx = ao_edge_x(coords, ncoords, transform, edge, y);
if (this_x->x < nx || (this_x->x == nx && this_x->edge < edge)) {
if (nx < next_x) {
next_x = nx;
uint32_t fill,
uint8_t rop)
{
- int16_t ix1 = floorf(x1 + 0.5f);
- int16_t ix2 = floorf(x2 + 0.5f);
+ int16_t ix1 = (int16_t) floorf(x1 + 0.5f);
+ int16_t ix2 = (int16_t) floorf(x2 + 0.5f);
int16_t iy = (int16_t) y;
ao_rect(dst, ix1, iy, ix2 - ix1, 1, fill, rop);
}
* indication of whether the edge goes upwards or downwards
*/
static int
-ao_wind(const struct ao_coord *coords,
- uint16_t ncoords,
- uint16_t edge)
+ao_wind(const struct ao_coord *coords,
+ uint16_t ncoords,
+ const struct ao_transform *transform,
+ uint16_t edge)
{
- uint16_t next_edge = (edge == ncoords - 1) ? 0 : edge + 1;
- return coords[edge].y > coords[next_edge].y ? 1 : -1;
+ uint16_t next_edge = _next(ncoords, edge);
+ return _y(coords, transform, edge) > _y(coords, transform, next_edge) ? 1 : -1;
}
/*
*/
void
ao_poly(const struct ao_bitmap *dst,
- const struct ao_coord *coords,
- uint16_t ncoords,
- uint32_t fill,
+ const struct ao_coord *coords,
+ uint16_t ncoords,
+ const struct ao_transform *transform,
+ uint32_t fill,
uint8_t rop)
{
float y_min, y_max;
struct next_x next_x;
int wind;
+ if (!transform)
+ transform = &ao_identity;
+
/*
* Find the y limits of the polygon
*/
- y_min = y_max = coords[0].y;
+ y_min = y_max = _y(coords, transform, 0);
for (edge = 1; edge < ncoords; edge++) {
- y = coords[edge].y;
+ y = _y(coords, transform, edge);
if (y < y_min)
y_min = y;
else if (y > y_max)
next_x.x = INT16_MIN;
next_x.edge = 0;
wind = 0;
- while (ao_next_x(coords, ncoords, &next_x, y)) {
+ while (ao_next_x(coords, ncoords, transform, &next_x, y)) {
/*
* Fill the previous span if winding is
ao_span(dst, x, next_x.x, y, fill, rop);
/* Adjust winding for the current span */
- wind += ao_wind(coords, ncoords, next_x.edge);
+ wind += ao_wind(coords, ncoords, transform, next_x.edge);
/* Step to next span start x value */
x = next_x.x;
uint32_t fill,
uint8_t rop)
{
- int glyph_stride = (font->max_width + 31) / 32;
+ int16_t glyph_stride = ao_stride(font->max_width);
uint32_t src[glyph_stride * font->max_height];
char c;
int h;
- int8_t x_off, y_off, advance;
- int byte_width;
+ int16_t x_off = 0, y_off = 0, advance = 0;
+ int16_t byte_width = 0;
struct ao_bitmap src_bitmap = {
.base = src,
if (!font->metrics) {
src_bitmap.width = font->max_width;
- src_bitmap.height = font->max_width;
+ src_bitmap.height = font->max_height;
src_bitmap.stride = glyph_stride;
x_off = 0;
y_off = font->ascent;
advance = font->max_width;
+ byte_width = ao_stride_bytes(font->max_width);
}
while ((c = *string++)) {
const uint8_t *bytes = &font->bytes[font->pos[(uint8_t) c]];
const struct ao_glyph_metrics *m = &font->metrics[(uint8_t) c];
src_bitmap.width = m->width;
src_bitmap.height = m->height;
- src_bitmap.stride = (m->width + 31) / 32;
+ src_bitmap.stride = ao_stride(m->width);
x_off = m->x_off;
y_off = m->y_off;
advance = m->advance;
- byte_width = ((src_bitmap.width + 7) / 8);
+ byte_width = ao_stride_bytes(m->width);
}
for (h = 0; h < src_bitmap.height; h++)
- memcpy(&src[h * src_bitmap.stride], &bytes[h * byte_width], byte_width);
+ memcpy(&src[h * src_bitmap.stride], &bytes[h * byte_width], (size_t) byte_width);
ao_copy(dst,
x + x_off, y - y_off, src_bitmap.width, src_bitmap.height,
#define BIG_FONT FrutigerLT_Roman_64_font
#define SMALL_FONT FrutigerLT_Roman_12_font
-#define LOGO_FONT FrutigerLT_Roman_24_font
+#define LOGO_FONT BenguiatGothicStd_Bold_26_font
#define VALUE_Y BIG_FONT.ascent
-#define LABEL_Y BIG_FONT.ascent + SMALL_FONT.ascent + 2
+#define LABEL_Y (int16_t) (BIG_FONT.ascent + SMALL_FONT.ascent + 2)
#define BOX_X 2
#define PAD_X 90
#define BOX_LABEL_X 30
static int box_number = 1;
static int pad_number = 1;
-static bool do_polys = false;
+static int do_polys = 0;
static const struct ao_coord trek[] = {
{ .x = 90, .y = 0 },
#define NCOORD_DONUT (sizeof(donut)/sizeof(donut[0]))
+static const struct ao_coord bowtie[] = {
+ { .x = 0, .y = 0 },
+ { .x = 32, .y = 32 },
+ { .x = 0, .y = 32 },
+ { .x = 32, .y = 0 },
+};
+
+#define NCOORD_BOWTIE (sizeof(bowtie)/sizeof(bowtie[0]))
+
+static const struct ao_transform logo_transform = {
+ .x_scale = 48, .x_off = 0,
+ .y_scale = 48, .y_off = 10,
+};
+
void HandleExpose(Display *dpy, Window win, GC gc)
{
+ char str[64];
+
ao_rect(&fb, 0, 0, WIDTH, HEIGHT, 0xffffffff, AO_COPY);
- if (do_polys) {
- ao_logo(&fb, &LOGO_FONT, 0x00000000, AO_COPY);
-// ao_poly(&fb, trek, NCOORD_TREK, 0x00000000, AO_COPY);
-// ao_poly(&fb, donut, NCOORD_DONUT, 0x00000000, AO_COPY);
- } else {
- char str[64];
+ switch (do_polys) {
+ case 1:
+ ao_logo(&fb, &logo_transform, &LOGO_FONT, 0x00000000, AO_COPY);
+ break;
+ case 2:
+ ao_poly(&fb, trek, NCOORD_TREK, NULL, 0x00000000, AO_COPY);
+ ao_poly(&fb, donut, NCOORD_DONUT, NULL, 0x00000000, AO_COPY);
+ break;
+ case 3:
+ ao_poly(&fb, bowtie, NCOORD_BOWTIE, NULL, 0x00000000, AO_COPY);
+ break;
+ default:
+ case 0:
sprintf(str, "%02d", box_number);
ao_text(&fb, &BIG_FONT, BOX_X, VALUE_Y, str, 0x00000000, AO_COPY);
ao_text(&fb, &SMALL_FONT, PAD_LABEL_X, LABEL_Y, "pad", 0x00000000, AO_COPY);
ao_line(&fb, SEP_X, 0, SEP_X, HEIGHT, 0x00000000, AO_COPY);
+ break;
}
XImage *image = XCreateImage(dpy, visual, 1, XYBitmap, 0, (char *) bits, WIDTH, HEIGHT, 32, STRIDE*4);
box_number = 99;
break;
case 's':
- do_polys = !do_polys;
+ do_polys++;
+ if (do_polys == 4)
+ do_polys = 0;
break;
case 'c':
break;
void
HandleKeyRelease(Display *dpy, Window win, GC gc, XEvent *ev)
{
+ (void) dpy;
+ (void) win;
+ (void) gc;
+ (void) ev;
}
y = polygon[i].y;
break;
}
- printf("\t{ .x = %8g, .y = %8g },\n",
- (x - x_off) * scale + x_pos,
- (y - y_off) * scale + y_pos);
+ printf("\t{ .x = %8.6ff, .y = %8.6ff },\n",
+ imprecise((x - x_off) * scale + x_pos),
+ imprecise((y - y_off) * scale + y_pos));
}
}
printf("const struct ao_coord %s_bottom[] = {\n", name);
print_poly(bottom, height, bounds, x_pos, y_pos);
printf("};\n");
+ printf("\n");
+ real width = height * (bounds.max_x - bounds.min_x) / (bounds.max_y - bounds.min_y);
+ printf("static const float %s_height = %8.6ff;\n", name, height);
+ printf("static const float %s_width = %8.6ff;\n", name, width);
}
-print_logo(argv[1], string_to_real(argv[2]), string_to_real(argv[3]), string_to_real(argv[4]));
+print_logo(argv[1], 1.0, 0, 0);