435 lines
8.5 KiB
C
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;
|
|
}
|