diff options
author | Vincent Sanders <vince@netsurf-browser.org> | 2010-01-20 17:18:28 +0000 |
---|---|---|
committer | Vincent Sanders <vince@netsurf-browser.org> | 2010-01-20 17:18:28 +0000 |
commit | 131b6c4a00575c9e996a9ae60c90a9647fb5ef75 (patch) | |
tree | dba439673b801a22a833270dbd615628bf0614e4 /src/plot/util.c | |
parent | a3097232844a20ea918d63722dbe6a7c71493bab (diff) | |
download | libnsfb-131b6c4a00575c9e996a9ae60c90a9647fb5ef75.tar.gz libnsfb-131b6c4a00575c9e996a9ae60c90a9647fb5ef75.tar.bz2 |
move plot functions to their own sub directory
fix 8 and 16bpp plotters when used with cursor
svn path=/trunk/libnsfb/; revision=9850
Diffstat (limited to 'src/plot/util.c')
-rw-r--r-- | src/plot/util.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/plot/util.c b/src/plot/util.c new file mode 100644 index 0000000..cf2ec9b --- /dev/null +++ b/src/plot/util.c @@ -0,0 +1,199 @@ +#include <stdbool.h> + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_plot_util.h" + +#include "nsfb.h" + +enum { + POINT_LEFTOF_REGION = 1, + POINT_RIGHTOF_REGION = 2, + POINT_ABOVE_REGION = 4, + POINT_BELOW_REGION = 8, +}; + +#define REGION(x,y,cx1,cx2,cy1,cy2) \ + ( ( (y) > (cy2) ? POINT_BELOW_REGION : 0) | \ + ( (y) < (cy1) ? POINT_ABOVE_REGION : 0) | \ + ( (x) > (cx2) ? POINT_RIGHTOF_REGION : 0) | \ + ( (x) < (cx1) ? POINT_LEFTOF_REGION : 0) ) + +#define SWAP(a, b) do { int t; t=(a); (a)=(b); (b)=t; } while(0) + +/* clip a rectangle with another clipping rectangle. + * + * @param clip The rectangle to clip to. + * @param rect The rectangle to clip. + * @return false if the \a rect lies completely outside the \a clip rectangle, + * true if some of the \a rect is still visible. + */ +bool +nsfb_plot_clip(const nsfb_bbox_t * restrict clip, nsfb_bbox_t * restrict rect) +{ + char region1; + char region2; + + if (rect->x1 < rect->x0) SWAP(rect->x0, rect->x1); + + if (rect->y1 < rect->y0) SWAP(rect->y0, rect->y1); + + region1 = REGION(rect->x0, rect->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + region2 = REGION(rect->x1, rect->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + + /* area lies entirely outside the clipping rectangle */ + if ((region1 | region2) && (region1 & region2)) + return false; + + if (rect->x0 < clip->x0) + rect->x0 = clip->x0; + if (rect->x0 > clip->x1) + rect->x0 = clip->x1; + + if (rect->x1 < clip->x0) + rect->x1 = clip->x0; + if (rect->x1 > clip->x1) + rect->x1 = clip->x1; + + if (rect->y0 < clip->y0) + rect->y0 = clip->y0; + if (rect->y0 > clip->y1) + rect->y0 = clip->y1; + + if (rect->y1 < clip->y0) + rect->y1 = clip->y0; + if (rect->y1 > clip->y1) + rect->y1 = clip->y1; + + return true; +} + +bool +nsfb_plot_clip_ctx(nsfb_t *nsfb, nsfb_bbox_t * restrict rect) +{ + return nsfb_plot_clip(&nsfb->clip, rect); +} + +/** Clip a line to a bounding box. + */ +bool nsfb_plot_clip_line(const nsfb_bbox_t *clip, nsfb_bbox_t * restrict line) +{ + char region1; + char region2; + region1 = REGION(line->x0, line->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + region2 = REGION(line->x1, line->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + + while (region1 | region2) { + if (region1 & region2) { + /* line lies entirely outside the clipping rectangle */ + return false; + } + + if (region1) { + /* first point */ + if (region1 & POINT_BELOW_REGION) { + /* divide line at bottom */ + line->x0 = (line->x0 + (line->x1 - line->x0) * + (clip->y1 - 1 - line->y0) / (line->y1 - line->y0)); + line->y0 = clip->y1 - 1; + } else if (region1 & POINT_ABOVE_REGION) { + /* divide line at top */ + line->x0 = (line->x0 + (line->x1 - line->x0) * + (clip->y0 - line->y0) / (line->y1 - line->y0)); + line->y0 = clip->y0; + } else if (region1 & POINT_RIGHTOF_REGION) { + /* divide line at right */ + line->y0 = (line->y0 + (line->y1 - line->y0) * + (clip->x1 - 1 - line->x0) / (line->x1 - line->x0)); + line->x0 = clip->x1 - 1; + } else if (region1 & POINT_LEFTOF_REGION) { + /* divide line at right */ + line->y0 = (line->y0 + (line->y1 - line->y0) * + (clip->x0 - line->x0) / (line->x1 - line->x0)); + line->x0 = clip->x0; + } + + region1 = REGION(line->x0, line->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + } else { + /* second point */ + if (region2 & POINT_BELOW_REGION) { + /* divide line at bottom*/ + line->x1 = (line->x0 + (line->x1 - line->x0) * + (clip->y1 - 1 - line->y0) / (line->y1 - line->y0)); + line->y1 = clip->y1 - 1; + } else if (region2 & POINT_ABOVE_REGION) { + /* divide line at top*/ + line->x1 = (line->x0 + (line->x1 - line->x0) * + (clip->y0 - line->y0) / (line->y1 - line->y0)); + line->y1 = clip->y0; + } else if (region2 & POINT_RIGHTOF_REGION) { + /* divide line at right*/ + line->y1 = (line->y0 + (line->y1 - line->y0) * + (clip->x1 - 1 - line->x0) / (line->x1 - line->x0)); + line->x1 = clip->x1 - 1; + } else if (region2 & POINT_LEFTOF_REGION) { + /* divide line at right*/ + line->y1 = (line->y0 + (line->y1 - line->y0) * + (clip->x0 - line->x0) / (line->x1 - line->x0)); + line->x1 = clip->x0; + } + + region2 = REGION(line->x1, line->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1); + } + } + + return true; +} + +bool nsfb_plot_clip_line_ctx(nsfb_t *nsfb, nsfb_bbox_t * restrict line) +{ + return nsfb_plot_clip_line(&nsfb->clip, line); +} + +/* documented in libnsfb_plot_util.h */ +bool +nsfb_plot_add_rect(const nsfb_bbox_t *box1, const nsfb_bbox_t *box2, nsfb_bbox_t *result) +{ + /* lower x coordinate */ + if (box1->x0 < box2->x0) + result->x0 = box1->x0; + else + result->x0 = box2->x0; + + /* lower y coordinate */ + if (box1->y0 < box2->y0) + result->y0 = box1->y0; + else + result->y0 = box2->y0; + + /* upper x coordinate */ + if (box1->x1 > box2->x1) + result->x1 = box1->x1; + else + result->x1 = box2->x1; + + /* upper y coordinate */ + if (box1->y1 > box2->y1) + result->y1 = box1->y1; + else + result->y1 = box2->y1; + + return true; +} + +bool nsfb_plot_bbox_intersect(const nsfb_bbox_t *box1, const nsfb_bbox_t *box2) +{ + if (box2->x1 < box1->x0) + return false; + + if (box2->y1 < box1->y0) + return false; + + if (box2->x0 > box1->x1) + return false; + + if (box2->y0 > box1->y1) + return false; + + return true; +} |