brender-1997/pixelmap/genclip.c
2022-05-03 14:31:40 -07:00

435 lines
8.5 KiB
C

/*
* Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: genclip.c 2.5 1996/03/07 20:36:08 sam Exp $
* $Locker: $
*
* Useful line and rectangle clipping routines
*/
#include "pm.h"
#include "brassert.h"
BR_RCS_ID("$Id: genclip.c 2.5 1996/03/07 20:36:08 sam Exp $")
/*
* Clip a point to a pixelmap, producing coordinates relative to base of pixelmap
*/
br_clip_result BR_RESIDENT_ENTRY PixelmapPointClip(br_point *out, br_point *in, br_pixelmap *pm)
{
out->x = in->x + pm->origin_x;
out->y = in->y + pm->origin_y;
if(out->x < 0 || out->y < 0)
return BR_CLIP_REJECT;
if(out->x >= pm->width || out->y >= pm->height)
return BR_CLIP_REJECT;
return BR_CLIP_ACCEPT;
}
/*
* Clip a line to a pixelmap, producing coordinates relative to base of pixelmap
*/
br_clip_result BR_RESIDENT_ENTRY PixelmapLineClip(br_point *s_out, br_point *e_out, br_point *s_in, br_point *e_in, br_pixelmap *pm)
{
int temp;
br_int_32 w,h;
br_int_32 x1,x2,y1,y2;
x1 = s_in->x + pm->origin_x;
y1 = s_in->y + pm->origin_y;
x2 = e_in->x + pm->origin_x;
y2 = e_in->y + pm->origin_y;
#define USCALE(var,arg,num,den) ((var) = ((unsigned)(arg) * (unsigned)(num)) / (unsigned)(den))
#define EXCHG(a,b) do { \
int __temp__ = (a); \
(a) = (b); \
(b) = __temp__; \
} while(0)
w = pm->width-1;
h = pm->height-1;
if (x1 > x2) {
EXCHG(x1, x2);
EXCHG(y1, y2);
}
if ((x2 < 0) || (x1 > w)) {
return BR_CLIP_REJECT;
}
if (y1 < y2) {
if ((y2 < 0) || (y1 > h)) {
return BR_CLIP_REJECT;
}
if (y1 < 0) {
USCALE(temp, (x2 - x1), (0 - y1), (y2 - y1));
if ((x1 += temp) > w) {
return BR_CLIP_REJECT;
}
y1 = 0;
}
if (y2 > h) {
USCALE(temp, (x2 - x1), (y2 - h), (y2 - y1));
if ((x2 -= temp) < 0) {
return BR_CLIP_REJECT;
}
y2 = h;
}
if (x1 < 0) {
USCALE(temp, (y2 - y1), (0 - x1), (x2 - x1));
y1 += temp;
x1 = 0;
}
if (x2 > w) {
USCALE(temp, (y2 - y1), (x2 - w), (x2 - x1));
y2 -= temp;
x2 = w;
}
} else {
if ((y1 < 0) || (y2 > h)) {
return BR_CLIP_REJECT;
}
if (y1 > h) {
USCALE(temp, (x2 - x1), (y1 - h), (y1 - y2));
if ((x1 += temp) > w) {
return BR_CLIP_REJECT;
}
y1 = h;
}
if (y2 < 0) {
USCALE(temp, (x2 - x1), (0 - y2), (y1 - y2));
if ((x2 -= temp) < 0) {
return BR_CLIP_REJECT;
}
y2 = 0;
}
if (x1 < 0) {
USCALE(temp, (y1 - y2), (0 - x1), (x2 - x1));
y1 -= temp;
x1 = 0;
}
if (x2 > w) {
USCALE(temp, (y1 - y2), (x2 - w), (x2 - x1));
y2 += temp;
x2 = w;
}
}
s_out->x = x1;
s_out->y = y1;
e_out->x = x2;
e_out->y = y2;
return BR_CLIP_PARTIAL;
}
/*
* Clip a rectangle to a pixelmap, producing coordinates relative to base of pixelmap
*/
br_clip_result BR_RESIDENT_ENTRY PixelmapRectangleClip(br_rectangle *out, br_rectangle *in, br_pixelmap *pm)
{
out->x = in->x + pm->origin_x;
out->y = in->y + pm->origin_y;
out->w = in->w;
out->h = in->h;
/*
* Trivial reject
*/
if(out->x >= pm->width || out->y >= pm->height)
return BR_CLIP_REJECT;
if((out->x+out->w) <= 0 || (out->y+out->h) <= 0)
return BR_CLIP_REJECT;
/*
* Clip rectangle to destination
*/
if(out->x < 0) {
out->w += out->x; out->x = 0;
}
if(out->y < 0) {
out->h += out->y; out->y = 0;
}
if((out->x+out->w) > pm->width)
out->w = pm->width - out->x;
if((out->y+out->h) > pm->height)
out->h = pm->height - out->y;
/*
* Don't draw empty rectangles
*/
if(out->w == 0 || out->h == 0)
return BR_CLIP_REJECT;
return BR_CLIP_PARTIAL;
}
/*
* Clip a rectangle to two pixelmaps, producing coordinates relative to base of pixelmap
*/
br_clip_result BR_RESIDENT_ENTRY PixelmapRectangleClipTwo(
br_rectangle *r_out, br_point *p_out,
br_rectangle *r_in, br_point *p_in,
br_pixelmap *pm_dst, br_pixelmap *pm_src)
{
r_out->x = r_in->x + pm_src->origin_x;
r_out->y = r_in->y + pm_src->origin_y;
r_out->w = r_in->w;
r_out->h = r_in->h;
p_out->x = p_in->x + pm_dst->origin_x;
p_out->y = p_in->y + pm_dst->origin_y;
/*
* Trivial reject
*/
if(p_out->x >= pm_dst->width || p_out->y >= pm_dst->height)
return BR_CLIP_REJECT;
if(r_out->x >= pm_src->width || r_out->y >= pm_src->height)
return BR_CLIP_REJECT;
if((p_out->x+r_out->w) <= 0 || (p_out->y+r_out->h) <= 0)
return BR_CLIP_REJECT;
if((r_out->x+r_out->w) <= 0 || (r_out->y+r_out->h) <= 0)
return BR_CLIP_REJECT;
/*
* Clip rectangle to destination
*/
if(p_out->x < 0) {
r_out->w += p_out->x;
r_out->x -= p_out->x;
p_out->x = 0;
}
if(p_out->y < 0) {
r_out->h += p_out->y;
r_out->y -= p_out->y;
p_out->y = 0;
}
if((p_out->x+r_out->w) > pm_dst->width)
r_out->w = pm_dst->width - p_out->x;
if((p_out->y+r_out->h) > pm_dst->height)
r_out->h = pm_dst->height - p_out->y;
/*
* Clip rectangle to source
*/
if(r_out->x < 0) {
r_out->w += r_out->x;
p_out->x -= r_out->x;
r_out->x = 0;
}
if(r_out->y < 0) {
r_out->h += r_out->y;
p_out->y -= r_out->y;
r_out->y = 0;
}
if((r_out->x+r_out->w) > pm_src->width)
r_out->w = pm_src->width - r_out->x;
if((r_out->y+r_out->h) > pm_src->height)
r_out->h = pm_src->height - r_out->y;
/*
* Don't draw empty rectangles
*/
if(r_out->w == 0 || r_out->h == 0)
return BR_CLIP_REJECT;
return BR_CLIP_PARTIAL;
}
/*
* Clip two rectangles rectangle to two pixelmaps, producing coordinates relative to base of pixelmaps
*/
br_clip_result BR_RESIDENT_ENTRY PixelmapRectanglesClipTwo(
br_rectangle *s_out, br_rectangle *d_out,
br_rectangle *s_in, br_rectangle *d_in,
br_pixelmap *pm_dst, br_pixelmap *pm_src)
{
br_int_32 adjust;
s_out->x = s_in->x + pm_src->origin_x;
s_out->y = s_in->y + pm_src->origin_y;
s_out->w = s_in->w;
s_out->h = s_in->h;
d_out->x = d_in->x + pm_dst->origin_x;
d_out->y = d_in->y + pm_dst->origin_y;
d_out->w = d_in->w;
d_out->h = d_in->h;
/*
* Trivial reject
*/
if (d_out->x >= pm_dst->width || d_out->y >= pm_dst->height)
return BR_CLIP_REJECT;
if (s_out->x >= pm_src->width || s_out->y >= pm_src->height)
return BR_CLIP_REJECT;
if ((d_out->x + d_out->w) <= 0 || (d_out->y + d_out->h) <= 0)
return BR_CLIP_REJECT;
if ((s_out->x + s_out->w) <= 0 || (s_out->y + s_out->h) <= 0)
return BR_CLIP_REJECT;
/*
* Clip rectangles to destination
*/
if (d_out->x < 0) {
adjust = d_out->x * s_in->w / d_in->w;
d_out->w += d_out->x;
d_out->x = 0;
s_out->x -= adjust;
s_out->w += adjust;
}
if (d_out->y < 0) {
adjust = d_out->y * s_in->h / d_in->h;
d_out->h += d_out->y;
d_out->y = 0;
s_out->y -= adjust;
s_out->h += adjust;
}
if ((d_out->x + d_out->w) > pm_dst->width) {
d_out->w = pm_dst->width - d_out->x;
s_out->w = d_out->w * s_in->w / d_in->w;
}
if ((d_out->y + d_out->h) > pm_dst->height) {
d_out->h = pm_dst->height - d_out->y;
s_out->h = d_out->h * s_in->h / d_in->h;
}
/*
* Clip rectangles to source
*/
if (s_out->x < 0) {
adjust = s_out->x * d_in->w / s_in->w;
s_out->w += s_out->x;
s_out->x = 0;
d_out->x -= adjust;
d_out->w += adjust;
}
if (s_out->y < 0) {
adjust = s_out->y * d_in->h / s_in->h;
s_out->h += s_out->y;
s_out->y = 0;
d_out->y -= adjust;
d_out->h += adjust;
}
if ((s_out->x + s_out->w) > pm_src->width) {
s_out->w = pm_src->width - s_out->x;
d_out->w = s_out->w * d_in->w / s_in->w;
}
if ((s_out->y + s_out->h) > pm_src->height) {
s_out->h = pm_src->height - s_out->y;
d_out->h = s_out->h * d_in->h / s_in->h;
}
/*
* Don't draw empty rectangles
*/
if(s_out->w <= 0 || s_out->h <= 0 || d_out->w <= 0 || d_out->h <= 0)
return BR_CLIP_REJECT;
return BR_CLIP_PARTIAL;
}
/*
* Clip CopyBits arguments to a pixelmap
*/
br_clip_result BR_RESIDENT_ENTRY PixelmapCopyBitsClip(
br_rectangle *r_out, br_point *p_out,
br_rectangle *r_in, br_point *p_in,
br_pixelmap *pm)
{
r_out->x = r_in->x;
r_out->y = r_in->y;
r_out->w = r_in->w;
r_out->h = r_in->h;
p_out->x = p_in->x + pm->origin_x;
p_out->y = p_in->y + pm->origin_y;
/*
* Trivial reject
*/
if(p_out->x >= pm->width || p_out->y >= pm->height)
return BR_CLIP_REJECT;
if((p_out->x+r_out->w) <= 0 || (p_out->y+r_out->h) <= 0)
return BR_CLIP_REJECT;
/*
* Clip rectangle to destination
*/
if(p_out->x < 0) {
r_out->w += p_out->x;
r_out->x -= p_out->x;
p_out->x = 0;
}
if(p_out->y < 0) {
r_out->h += p_out->y;
r_out->y -= p_out->y;
p_out->y = 0;
}
if((p_out->x+r_out->w) > pm->width)
r_out->w = pm->width - p_out->x;
if((p_out->y+r_out->h) > pm->height)
r_out->h = pm->height - p_out->y;
/*
* Don't draw empty rectangles
*/
if(r_out->w == 0 || r_out->h == 0)
return BR_CLIP_REJECT;
return BR_CLIP_PARTIAL;
}