/* * 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)); }