X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fdraw%2Fao_line.c;fp=src%2Fdraw%2Fao_line.c;h=b427892b01bc17ebd9faaa12c26fd8c9f941d4e2;hb=c5734e9e38bc583aff305e3c534cfb8b9088bc71;hp=0000000000000000000000000000000000000000;hpb=83cfc271e37f568cb1d821cf6a96750f3ca3854c;p=fw%2Faltos diff --git a/src/draw/ao_line.c b/src/draw/ao_line.c new file mode 100644 index 00000000..b427892b --- /dev/null +++ b/src/draw/ao_line.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2016 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include "ao.h" +#include "ao_draw.h" +#include "ao_draw_int.h" + +#define ao_mask(x,w) (ao_right(AO_ALLONES,(x) & AO_MASK) & \ + ao_left(AO_ALLONES,(FB_UNIT - ((x)+(w))) & AO_MASK)) + + +/* out of clip region codes */ +#define OUT_LEFT 0x08 +#define OUT_RIGHT 0x04 +#define OUT_ABOVE 0x02 +#define OUT_BELOW 0x01 + +/* major axis for bresenham's line */ +#define X_AXIS 0 +#define Y_AXIS 1 + +static void +ao_bres(const struct ao_bitmap *dst_bitmap, + int16_t signdx, + int16_t signdy, + int16_t axis, + int16_t x1, + int16_t y1, + int16_t e, + int16_t e1, + int16_t e3, + int16_t len, + uint32_t and, + uint32_t xor) +{ + int16_t stride = dst_bitmap->stride; + uint32_t *dst = dst_bitmap->base; + uint32_t mask0, mask; + + mask0 = 1; + if (signdx < 0) + mask0 = ao_right(1, AO_UNIT - 1); + + if (signdy < 0) + stride = -stride; + + dst = dst + y1 * stride + (x1 >> AO_SHIFT); + mask = ao_right(1, x1 & AO_MASK); + + while (len--) { + /* clip each point */ + + if (0 <= x1 && x1 < dst_bitmap->width && + 0 <= y1 && y1 < dst_bitmap->height) + *dst = ao_do_mask_rrop(*dst, and, xor, mask); + + if (axis == X_AXIS) { + if (signdx < 0) + mask = ao_left(mask, 1); + else + mask = ao_right(mask, 1); + if (!mask) { + dst += signdx; + mask = mask0; + } + x1 += signdx; + e += e1; + if (e >= 0) { + dst += stride; + e += e3; + y1 += signdy; + } + } else { + dst += stride; + e += e1; + y1 += signdy; + if (e >= 0) { + if (signdx < 0) + mask = ao_left(mask, 1); + else + mask = ao_right(mask, 1); + if (!mask) { + dst += signdx; + mask = mask0; + } + e += e3; + x1 += signdx; + } + } + } +} + + +#define bound(val,max) do { \ + if (val < 0) { \ + val = 0; \ + } \ + if (val > max) { \ + val = max; \ + } \ + } while (0) + +void +ao_line(const struct ao_bitmap *dst, + int16_t x1, + int16_t y1, + int16_t x2, + int16_t y2, + uint32_t fill, + uint8_t rop) +{ + int16_t adx, ady; + int16_t e, e1, e2, e3; + int16_t signdx = 1, signdy = 1; + int16_t axis; + int16_t len; + + if ((adx = x2 - x1) < 0) { + adx = -adx; + signdx = -1; + } + if ((ady = y2 - y1) < 0) { + ady = -ady; + signdy = -1; + } + + if (adx > ady) { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + len = adx; + } else { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + len = ady; + } + + e3 = e2 - e1; + e = e - e1; + + ao_bres(dst, + signdx, + signdy, + axis, + x1, + y1, + e, e1, e3, len, + ao_and(rop, fill), + ao_xor(rop, fill)); +}