2002-08-26 14:03:04 +00:00
|
|
|
/*
|
2002-08-27 10:11:20 +00:00
|
|
|
Copyright (C) 2002 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Author: Alexander Malmberg <alexander@malmberg.org>
|
2002-08-26 14:03:04 +00:00
|
|
|
|
|
|
|
This file is part of GNUstep.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Image drawing. DPSimage and helpers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include <AppKit/NSAffineTransform.h>
|
|
|
|
#include <AppKit/NSGraphics.h>
|
|
|
|
|
|
|
|
#include "ARTGState.h"
|
|
|
|
|
2002-09-10 19:37:47 +00:00
|
|
|
#include "x11/XWindowBuffer.h"
|
2002-08-26 14:03:04 +00:00
|
|
|
#include "blit.h"
|
|
|
|
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
static unsigned int _get_8_bits(const unsigned char *ptr, int bit_ofs,
|
|
|
|
int num_bits)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
TODO: if we get values with more than 8 bits, we should round properly and
|
|
|
|
not just discard the extra bits
|
|
|
|
*/
|
|
|
|
int i;
|
|
|
|
unsigned int v;
|
2002-08-26 14:36:43 +00:00
|
|
|
ptr += bit_ofs / 8;
|
|
|
|
bit_ofs %= 8;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
v = 0;
|
|
|
|
for (i = 0; i < 8 && i < num_bits; i++)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
v <<= 1;
|
|
|
|
if ((*ptr) & (128 >> bit_ofs))
|
|
|
|
v |= 1;
|
2002-08-26 14:03:04 +00:00
|
|
|
bit_ofs++;
|
2002-08-26 14:36:43 +00:00
|
|
|
if (bit_ofs == 8)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
|
|
|
ptr++;
|
2002-08-26 14:36:43 +00:00
|
|
|
bit_ofs = 0;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
}
|
2002-08-26 14:36:43 +00:00
|
|
|
/* extend what we've got to 8 bits */
|
2002-08-26 14:03:04 +00:00
|
|
|
switch (num_bits)
|
|
|
|
{
|
|
|
|
case 1:
|
2002-08-26 14:36:43 +00:00
|
|
|
v *= 255;
|
2002-08-26 14:03:04 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2002-08-26 14:36:43 +00:00
|
|
|
v *= 85;
|
2002-08-26 14:03:04 +00:00
|
|
|
break;
|
|
|
|
case 3:
|
2002-08-26 14:36:43 +00:00
|
|
|
v = (v << 5) | (v << 2) | (v >> 1);
|
2002-08-26 14:03:04 +00:00
|
|
|
break;
|
|
|
|
case 4:
|
2002-08-26 14:36:43 +00:00
|
|
|
v = (v << 4) | v;
|
2002-08-26 14:03:04 +00:00
|
|
|
break;
|
|
|
|
case 5:
|
2002-08-26 14:36:43 +00:00
|
|
|
v = (v << 3) | (v >> 2);
|
2002-08-26 14:03:04 +00:00
|
|
|
break;
|
|
|
|
case 6:
|
2002-08-26 14:36:43 +00:00
|
|
|
v = (v << 2) | (v >> 4);
|
2002-08-26 14:03:04 +00:00
|
|
|
break;
|
|
|
|
case 7:
|
2002-08-26 14:36:43 +00:00
|
|
|
v = (v << 1) | (v >> 6);
|
2002-08-26 14:03:04 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
int width, height;
|
|
|
|
int bits_per_sample, samples_per_pixel, bits_per_pixel, bytes_per_row;
|
|
|
|
BOOL is_planar, has_alpha;
|
2002-08-26 14:03:04 +00:00
|
|
|
const unsigned char **data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
0 unknown, use colorspacename
|
|
|
|
1 rgb
|
|
|
|
2 cmyk
|
|
|
|
3 gray
|
|
|
|
*/
|
|
|
|
int colorspace;
|
|
|
|
NSString *colorspacename;
|
|
|
|
} image_info_t;
|
|
|
|
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
static void _image_get_color_rgb_8(image_info_t *ii, render_run_t *ri,
|
|
|
|
int x, int y)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
|
|
|
int ofs;
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (x < 0) x = 0;
|
|
|
|
if (y < 0) y = 0;
|
|
|
|
if (x >= ii->width) x = ii->width - 1;
|
2002-09-12 00:29:54 +00:00
|
|
|
if (y >= ii->height) y = ii->height - 1;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
ofs = ii->bytes_per_row * y + x * ii->bits_per_pixel / 8;
|
2002-08-26 14:03:04 +00:00
|
|
|
if (ii->is_planar)
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->r = ii->data[0][ofs];
|
|
|
|
ri->g = ii->data[1][ofs];
|
|
|
|
ri->b = ii->data[2][ofs];
|
2002-08-26 14:03:04 +00:00
|
|
|
if (ii->has_alpha)
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->a = ii->data[3][ofs];
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->a = 255;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->r = ii->data[0][ofs];
|
|
|
|
ri->g = ii->data[0][ofs + 1];
|
|
|
|
ri->b = ii->data[0][ofs + 2];
|
2002-08-26 14:03:04 +00:00
|
|
|
if (ii->has_alpha)
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->a = ii->data[0][ofs + 3];
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->a = 255;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
static void _image_get_color_rgb_cmyk_gray(image_info_t *ii, render_run_t *ri,
|
|
|
|
int x, int y)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
int ofs, bit_ofs;
|
2002-08-26 14:03:04 +00:00
|
|
|
int values[5];
|
2002-08-26 14:36:43 +00:00
|
|
|
int i, j;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (x < 0) x = 0;
|
|
|
|
if (y < 0) y = 0;
|
|
|
|
if (x >= ii->width) x = ii->width - 1;
|
2002-09-12 00:29:54 +00:00
|
|
|
if (y >= ii->height) y = ii->height - 1;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
ofs = y * ii->bytes_per_row;
|
|
|
|
bit_ofs = x * ii->bits_per_pixel;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
for (i = j = 0; i < ii->samples_per_pixel; i++)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
values[i] = _get_8_bits(ii->data[j] + ofs, bit_ofs, ii->bits_per_sample);
|
2002-08-26 14:03:04 +00:00
|
|
|
if (ii->is_planar)
|
|
|
|
j++;
|
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
bit_ofs += ii->bits_per_sample;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
if (ii->has_alpha)
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->a = values[i - 1];
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->a = 255;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (ii->colorspace == 1)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->r = values[0];
|
|
|
|
ri->g = values[1];
|
|
|
|
ri->b = values[2];
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
2002-08-26 14:36:43 +00:00
|
|
|
else if (ii->colorspace == 2)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
j = 255 - values[0] - values[3];
|
|
|
|
ri->r = j < 0?0:j;
|
|
|
|
j = 255 - values[1] - values[3];
|
|
|
|
ri->g = j < 0?0:j;
|
|
|
|
j = 255 - values[2] - values[3];
|
|
|
|
ri->b = j < 0?0:j;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
2002-08-26 14:36:43 +00:00
|
|
|
else if (ii->colorspace == 3)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
ri->r = ri->g = ri->b = values[0];
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@implementation ARTGState (image)
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
-(void) _image_do_rgb_transform: (image_info_t *)ii
|
|
|
|
: (NSAffineTransform *)matrix
|
|
|
|
: (void (*)(image_info_t *ii, render_run_t *ri, int x, int y))ifunc
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
TODO:
|
|
|
|
seems to have problems with rotations. 0, 90, 180, 270 work fine, but others
|
|
|
|
seem to cause edges to be off by a pixel
|
|
|
|
*/
|
2002-08-26 14:36:43 +00:00
|
|
|
int x[4], y[4];
|
|
|
|
int tx[4], ty[4];
|
|
|
|
float fx[4], fy[4];
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
int cy, ey;
|
|
|
|
int left_delta, next;
|
|
|
|
int lx, lx_frac, ldx, ldx_frac, l_de, le;
|
|
|
|
int rx, rx_frac, rdx, rdx_frac, r_de, re;
|
|
|
|
int ltx, lty, ltx_frac, lty_frac, ldtx, ldty, ldtx_frac, ldty_frac;
|
|
|
|
int rtx, rty, rtx_frac, rty_frac, rdtx, rdty, rdtx_frac, rdty_frac;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
|
|
|
NSPoint p;
|
|
|
|
|
2002-08-31 13:53:42 +00:00
|
|
|
void (*render_run)(render_run_t *ri, int num);
|
|
|
|
|
|
|
|
|
|
|
|
if (wi->has_alpha)
|
|
|
|
render_run = RENDER_RUN_ALPHA_A;
|
|
|
|
else
|
|
|
|
render_run = RENDER_RUN_ALPHA;
|
|
|
|
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
p = [matrix transformPoint: NSMakePoint(0, 0)];
|
|
|
|
fx[0] = p.x; fy[0] = p.y;
|
|
|
|
p = [matrix transformPoint: NSMakePoint(ii->width, 0)];
|
|
|
|
fx[1] = p.x; fy[1] = p.y;
|
|
|
|
p = [matrix transformPoint: NSMakePoint(ii->width, ii->height)];
|
|
|
|
fx[2] = p.x; fy[2] = p.y;
|
|
|
|
p = [matrix transformPoint: NSMakePoint(0, ii->height)];
|
|
|
|
fx[3] = p.x; fy[3] = p.y;
|
|
|
|
|
|
|
|
if (fabs(fx[0] - floor(fx[0] + .5)) < 0.001) fx[0] = floor(fx[0] + .5);
|
|
|
|
if (fabs(fx[1] - floor(fx[1] + .5)) < 0.001) fx[1] = floor(fx[1] + .5);
|
|
|
|
if (fabs(fx[2] - floor(fx[2] + .5)) < 0.001) fx[2] = floor(fx[2] + .5);
|
|
|
|
if (fabs(fx[3] - floor(fx[3] + .5)) < 0.001) fx[3] = floor(fx[3] + .5);
|
|
|
|
if (fabs(fy[0] - floor(fy[0] + .5)) < 0.001) fy[0] = floor(fy[0] + .5);
|
|
|
|
if (fabs(fy[1] - floor(fy[1] + .5)) < 0.001) fy[1] = floor(fy[1] + .5);
|
|
|
|
if (fabs(fy[2] - floor(fy[2] + .5)) < 0.001) fy[2] = floor(fy[2] + .5);
|
|
|
|
if (fabs(fy[3] - floor(fy[3] + .5)) < 0.001) fy[3] = floor(fy[3] + .5);
|
|
|
|
|
|
|
|
x[0] = floor(fx[0]); y[0] = wi->sy - floor(fy[0]);
|
|
|
|
x[1] = floor(fx[1]); y[1] = wi->sy - floor(fy[1]);
|
|
|
|
x[2] = floor(fx[2]); y[2] = wi->sy - floor(fy[2]);
|
|
|
|
x[3] = floor(fx[3]); y[3] = wi->sy - floor(fy[3]);
|
|
|
|
|
|
|
|
tx[0] = 0; ty[0] = ii->height;
|
|
|
|
tx[1] = ii->width; ty[1] = ii->height;
|
|
|
|
tx[2] = ii->width; ty[2] = 0;
|
|
|
|
tx[3] = 0; ty[3] = 0;
|
|
|
|
|
|
|
|
cy = y[le = 0];
|
|
|
|
if (y[1] < cy) cy = y[le = 1];
|
|
|
|
if (y[2] < cy) cy = y[le = 2];
|
|
|
|
if (y[3] < cy) cy = y[le = 3];
|
|
|
|
re = le;
|
|
|
|
|
|
|
|
ey = y[0];
|
|
|
|
if (y[1] > ey) ey = y[1];
|
|
|
|
if (y[2] > ey) ey = y[2];
|
|
|
|
if (y[3] > ey) ey = y[3];
|
|
|
|
|
|
|
|
if (x[(le + 1) & 3] < x[(le - 1) & 3])
|
|
|
|
left_delta = 1;
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
left_delta = -1;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
|
|
|
/* silence the compiler */
|
2002-08-26 14:36:43 +00:00
|
|
|
lx = lx_frac = ldx = ldx_frac = l_de = 0;
|
|
|
|
rx = rx_frac = rdx = rdx_frac = r_de = 0;
|
|
|
|
ltx = lty = ltx_frac = lty_frac = ldtx = ldty = ldtx_frac = ldty_frac = 0;
|
|
|
|
rtx = rty = rtx_frac = rty_frac = rdtx = rdty = rdtx_frac = rdty_frac = 0;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
while (cy <= ey && cy < clip_y1)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
if (cy == y[le])
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
next = (le + left_delta) & 3;
|
|
|
|
while (y[le] == y[next])
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
le = next;
|
|
|
|
next = (le + left_delta) & 3;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
2002-08-26 14:36:43 +00:00
|
|
|
l_de = y[next] - y[le];
|
|
|
|
lx = x[le];
|
|
|
|
lx_frac = 0;
|
|
|
|
ldx = (x[next] - x[le]) / l_de;
|
|
|
|
ldx_frac = (x[next] - x[le]) % l_de;
|
|
|
|
|
|
|
|
ltx = tx[le];
|
|
|
|
lty = ty[le];
|
|
|
|
ltx_frac = 0;
|
|
|
|
lty_frac = 0;
|
|
|
|
ldtx = (tx[next] - tx[le]) / l_de;
|
|
|
|
ldty = (ty[next] - ty[le]) / l_de;
|
|
|
|
ldtx_frac = (tx[next] - tx[le]) % l_de;
|
|
|
|
ldty_frac = (ty[next] - ty[le]) % l_de;
|
|
|
|
|
|
|
|
le = next;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
lx += ldx;
|
|
|
|
lx_frac += ldx_frac;
|
|
|
|
if (lx_frac < 0)
|
|
|
|
lx--, lx_frac += l_de;
|
|
|
|
if (lx_frac > l_de)
|
|
|
|
lx++, lx_frac -= l_de;
|
|
|
|
|
|
|
|
ltx += ldtx;
|
|
|
|
ltx_frac += ldtx_frac;
|
|
|
|
if (ltx_frac < 0)
|
|
|
|
ltx--, ltx_frac += l_de;
|
|
|
|
if (ltx_frac > l_de)
|
|
|
|
ltx++, ltx_frac -= l_de;
|
|
|
|
|
|
|
|
lty += ldty;
|
|
|
|
lty_frac += ldty_frac;
|
|
|
|
if (lty_frac < 0)
|
|
|
|
lty--, lty_frac += l_de;
|
|
|
|
if (lty_frac > l_de)
|
|
|
|
lty++, lty_frac -= l_de;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (cy == y[re])
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
next = (re - left_delta) & 3;
|
|
|
|
while (y[re] == y[next])
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
re = next;
|
|
|
|
next = (re - left_delta) & 3;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
2002-08-26 14:36:43 +00:00
|
|
|
r_de = y[next] - y[re];
|
|
|
|
rx = x[re];
|
|
|
|
rx_frac = r_de - 1; /* TODO? */
|
|
|
|
rdx = (x[next] - x[re]) / r_de;
|
|
|
|
rdx_frac = (x[next] - x[re]) % r_de;
|
|
|
|
|
|
|
|
rtx = tx[re];
|
|
|
|
rty = ty[re];
|
|
|
|
rtx_frac = 0;
|
|
|
|
rty_frac = 0;
|
|
|
|
rdtx = (tx[next] - tx[re]) / r_de;
|
|
|
|
rdty = (ty[next] - ty[re]) / r_de;
|
|
|
|
rdtx_frac = (tx[next] - tx[re]) % r_de;
|
|
|
|
rdty_frac = (ty[next] - ty[re]) % r_de;
|
|
|
|
|
|
|
|
re = next;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
rx += rdx;
|
|
|
|
rx_frac += rdx_frac;
|
|
|
|
if (rx_frac < 0)
|
|
|
|
rx--, rx_frac += r_de;
|
|
|
|
if (rx_frac > r_de)
|
|
|
|
rx++, rx_frac -= r_de;
|
|
|
|
|
|
|
|
rtx += rdtx;
|
|
|
|
rtx_frac += rdtx_frac;
|
|
|
|
if (rtx_frac < 0)
|
|
|
|
rtx--, rtx_frac += r_de;
|
|
|
|
if (rtx_frac > r_de)
|
|
|
|
rtx++, rtx_frac -= r_de;
|
|
|
|
|
|
|
|
rty += rdty;
|
|
|
|
rty_frac += rdty_frac;
|
|
|
|
if (rty_frac < 0)
|
|
|
|
rty--, rty_frac += r_de;
|
|
|
|
if (rty_frac > r_de)
|
|
|
|
rty++, rty_frac -= r_de;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (cy >= clip_y0 && rx > lx)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
|
|
|
render_run_t ri;
|
2002-08-26 14:36:43 +00:00
|
|
|
int x0, x1, de;
|
|
|
|
int tx, ty, tx_frac, ty_frac, dtx, dty, dtx_frac, dty_frac;
|
2002-08-26 14:03:04 +00:00
|
|
|
int delta;
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
x0 = lx;
|
|
|
|
x1 = rx;
|
|
|
|
de = x1 - x0;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
tx = ltx;
|
|
|
|
ty = lty;
|
|
|
|
tx_frac = ltx_frac * de * r_de;
|
|
|
|
ty_frac = lty_frac * de * r_de;
|
|
|
|
de *= r_de * l_de;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
delta = (rtx * r_de + rtx_frac) * l_de
|
2002-08-31 13:53:42 +00:00
|
|
|
- (ltx * l_de + ltx_frac) * r_de;
|
2002-08-26 14:36:43 +00:00
|
|
|
dtx = delta / de;
|
|
|
|
dtx_frac = delta % de;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
delta = (rty * r_de + rty_frac) * l_de
|
2002-08-31 13:53:42 +00:00
|
|
|
- (lty * l_de + lty_frac) * r_de;
|
2002-08-26 14:36:43 +00:00
|
|
|
dty = delta / de;
|
|
|
|
dty_frac = delta % de;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
|
|
|
/*
|
2002-08-26 14:36:43 +00:00
|
|
|
x0 x1 / x2 -> y0 y1 / y2 z
|
|
|
|
((y0 * y2 + y1) * x2 - (x0 * x2 + x1) * y2) / (x2 * y2 * z)
|
2002-08-26 14:03:04 +00:00
|
|
|
*/
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (x0 < clip_x0)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
tx += dtx * (clip_x0 - x0);
|
|
|
|
ty += dty * (clip_x0 - x0);
|
|
|
|
tx_frac += dtx_frac * (clip_x0 - x0);
|
|
|
|
while (tx_frac < 0)
|
|
|
|
tx--, tx_frac += de;
|
|
|
|
while (tx_frac >= de)
|
|
|
|
tx++, tx_frac -= de;
|
|
|
|
ty_frac += dty_frac * (clip_x0 - x0);
|
|
|
|
while (ty_frac < 0)
|
|
|
|
ty--, ty_frac += de;
|
|
|
|
while (ty_frac >= de)
|
|
|
|
ty++, ty_frac -= de;
|
|
|
|
x0 = clip_x0;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
2002-08-31 13:53:42 +00:00
|
|
|
if (x1 >= clip_x1) x1 = clip_x1 - 1; /* TODO? */
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
ri.dst = wi->data + x0 * DI.bytes_per_pixel
|
2002-08-31 13:53:42 +00:00
|
|
|
+ cy * wi->bytes_per_line;
|
2002-08-26 14:36:43 +00:00
|
|
|
ri.dsta = wi->alpha + x0 + cy * wi->sx;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-31 13:53:42 +00:00
|
|
|
if (!clip_span)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
for (; x0 < x1; x0++, ri.dst += DI.bytes_per_pixel, ri.dsta++)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
ifunc(ii, &ri, tx, ty);
|
2002-08-31 13:53:42 +00:00
|
|
|
render_run(&ri, 1);
|
2002-08-26 14:36:43 +00:00
|
|
|
|
|
|
|
tx += dtx;
|
|
|
|
ty += dty;
|
|
|
|
tx_frac += dtx_frac;
|
|
|
|
if (tx_frac < 0)
|
|
|
|
tx--, tx_frac += de;
|
|
|
|
if (tx_frac >= de)
|
|
|
|
tx++, tx_frac -= de;
|
|
|
|
ty_frac += dty_frac;
|
|
|
|
if (ty_frac < 0)
|
|
|
|
ty--, ty_frac += de;
|
|
|
|
if (ty_frac >= de)
|
|
|
|
ty++, ty_frac -= de;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-08-31 13:53:42 +00:00
|
|
|
unsigned int *span, *end;
|
|
|
|
BOOL state = NO;
|
2002-08-26 14:36:43 +00:00
|
|
|
|
2002-08-31 13:53:42 +00:00
|
|
|
span = &clip_span[clip_index[cy - clip_y0]];
|
|
|
|
end = &clip_span[clip_index[cy - clip_y0 + 1]];
|
|
|
|
|
|
|
|
x0 -= clip_x0;
|
|
|
|
x1 -= clip_x0;
|
|
|
|
while (span != end && *span < x0)
|
|
|
|
{
|
|
|
|
state = !state;
|
|
|
|
span++;
|
|
|
|
if (span == end)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (span != end)
|
|
|
|
{
|
|
|
|
for (; x0 < x1; x0++, ri.dst += DI.bytes_per_pixel, ri.dsta++)
|
|
|
|
{
|
|
|
|
if (x0 == *span)
|
|
|
|
{
|
|
|
|
span++;
|
|
|
|
state = !state;
|
|
|
|
if (span == end)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state)
|
|
|
|
{
|
|
|
|
ifunc(ii, &ri, tx, ty);
|
|
|
|
render_run(&ri, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
tx += dtx;
|
|
|
|
ty += dty;
|
|
|
|
tx_frac += dtx_frac;
|
|
|
|
if (tx_frac < 0)
|
|
|
|
tx--, tx_frac += de;
|
|
|
|
if (tx_frac >= de)
|
|
|
|
tx++, tx_frac -= de;
|
|
|
|
ty_frac += dty_frac;
|
|
|
|
if (ty_frac < 0)
|
|
|
|
ty--, ty_frac += de;
|
|
|
|
if (ty_frac >= de)
|
|
|
|
ty++, ty_frac -= de;
|
|
|
|
}
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cy++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
- (void)DPSimage: (NSAffineTransform * ) matrix
|
2002-08-26 14:03:04 +00:00
|
|
|
: (int) pixelsWide : (int) pixelsHigh
|
|
|
|
: (int) bitsPerSample : (int) samplesPerPixel
|
|
|
|
: (int) bitsPerPixel : (int) bytesPerRow : (BOOL) isPlanar
|
|
|
|
: (BOOL) hasAlpha : (NSString *) colorSpaceName
|
|
|
|
: (const unsigned char *const [5]) data
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
BOOL identity_transform, is_rgb;
|
2002-08-26 14:03:04 +00:00
|
|
|
image_info_t ii;
|
|
|
|
|
|
|
|
if (!wi || !wi->data) return;
|
|
|
|
if (all_clipped) return;
|
|
|
|
|
|
|
|
[matrix prependTransform: ctm];
|
2002-08-26 14:36:43 +00:00
|
|
|
if (fabs(matrix->matrix.m11 - 1.0) < 0.001 &&
|
|
|
|
fabs(matrix->matrix.m12) < 0.001 &&
|
|
|
|
fabs(matrix->matrix.m22 - 1.0) < 0.001 &&
|
|
|
|
fabs(matrix->matrix.m21) < 0.001)
|
|
|
|
identity_transform = YES;
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
identity_transform = NO;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (colorSpaceName == NSDeviceRGBColorSpace ||
|
|
|
|
colorSpaceName == NSCalibratedRGBColorSpace)
|
|
|
|
is_rgb = YES;
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
is_rgb = NO;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
|
|
|
/* optimize common case */
|
|
|
|
if (identity_transform && is_rgb &&
|
2002-08-31 13:53:42 +00:00
|
|
|
!clip_span &&
|
2002-08-26 14:36:43 +00:00
|
|
|
bitsPerSample == 8 && !isPlanar &&
|
|
|
|
bytesPerRow == samplesPerPixel * pixelsWide &&
|
|
|
|
((samplesPerPixel == 3 && bitsPerPixel == 24 && !hasAlpha) ||
|
|
|
|
(samplesPerPixel == 4 && bitsPerPixel == 32 && hasAlpha)))
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
int x, y, ox, oy;
|
|
|
|
const unsigned char *src = data[0];
|
2002-08-26 14:03:04 +00:00
|
|
|
unsigned char *alpha_dest;
|
|
|
|
render_run_t ri;
|
|
|
|
|
|
|
|
if (wi->has_alpha)
|
|
|
|
{
|
|
|
|
if (DI.inline_alpha)
|
2002-08-26 14:36:43 +00:00
|
|
|
alpha_dest = wi->data + DI.inline_alpha_ofs;
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
alpha_dest = wi->alpha;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
alpha_dest = NULL;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
ox = [matrix transformPoint: NSMakePoint(0, 0)].x;
|
|
|
|
oy = wi->sy - [matrix transformPoint: NSMakePoint(0, 0)].y - pixelsHigh;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
for (y = 0; y < pixelsHigh; y++)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
for (x = 0; x < pixelsWide; x++)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
if (x + ox < clip_x0 || x + ox >= clip_x1 ||
|
2002-08-31 13:53:42 +00:00
|
|
|
y + oy < clip_y0 || y + oy >= clip_y1)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
|
|
|
if (hasAlpha)
|
2002-08-26 14:36:43 +00:00
|
|
|
src += 4;
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
src += 3;
|
2002-08-26 14:03:04 +00:00
|
|
|
continue;
|
|
|
|
}
|
2002-08-26 14:36:43 +00:00
|
|
|
ri.dst = wi->data + (x + ox) * DI.bytes_per_pixel
|
2002-08-31 13:53:42 +00:00
|
|
|
+ (y + oy) * wi->bytes_per_line;
|
2002-08-26 14:36:43 +00:00
|
|
|
ri.dsta = wi->alpha + (x + ox) + (y + oy) * wi->sx;
|
|
|
|
ri.r = src[0];
|
|
|
|
ri.g = src[1];
|
|
|
|
ri.b = src[2];
|
2002-08-26 14:03:04 +00:00
|
|
|
if (hasAlpha)
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
ri.a = src[3];
|
2002-08-26 14:03:04 +00:00
|
|
|
/* TODO: find out if input is premultiplied or not */
|
2002-09-17 22:37:28 +00:00
|
|
|
if (ri.a && ri.a != 255)
|
|
|
|
{
|
|
|
|
ri.r = (255 * ri.r) / ri.a;
|
|
|
|
ri.g = (255 * ri.g) / ri.a;
|
|
|
|
ri.b = (255 * ri.b) / ri.a;
|
|
|
|
}
|
2002-08-26 14:03:04 +00:00
|
|
|
if (alpha_dest)
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
if (src[3] == 255)
|
|
|
|
RENDER_RUN_OPAQUE_A(&ri, 1);
|
2002-08-26 14:03:04 +00:00
|
|
|
else if (src[3])
|
2002-08-26 14:36:43 +00:00
|
|
|
RENDER_RUN_ALPHA_A(&ri, 1);
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
if (src[3] == 255)
|
|
|
|
RENDER_RUN_OPAQUE(&ri, 1);
|
2002-08-26 14:03:04 +00:00
|
|
|
else if (src[3])
|
2002-08-26 14:36:43 +00:00
|
|
|
RENDER_RUN_ALPHA(&ri, 1);
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
2002-08-26 14:36:43 +00:00
|
|
|
src += 4;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
ri.a = 255;
|
2002-08-26 14:03:04 +00:00
|
|
|
if (alpha_dest)
|
2002-08-26 14:36:43 +00:00
|
|
|
RENDER_RUN_OPAQUE_A(&ri, 1);
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
RENDER_RUN_OPAQUE(&ri, 1);
|
|
|
|
src += 3;
|
2002-08-26 14:03:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-09-16 14:38:25 +00:00
|
|
|
UPDATE_UNBUFFERED
|
2002-08-26 14:03:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
ii.bits_per_sample = bitsPerSample;
|
|
|
|
ii.bits_per_pixel = bitsPerPixel;
|
|
|
|
ii.is_planar = isPlanar;
|
|
|
|
ii.has_alpha = hasAlpha;
|
|
|
|
ii.width = pixelsWide;
|
|
|
|
ii.height = pixelsHigh;
|
|
|
|
ii.samples_per_pixel = samplesPerPixel;
|
|
|
|
ii.bytes_per_row = bytesPerRow;
|
|
|
|
ii.data = (const unsigned char **)data;
|
|
|
|
|
|
|
|
if (bitsPerSample == 8 && is_rgb &&
|
|
|
|
((samplesPerPixel == 3 && !hasAlpha) ||
|
|
|
|
(samplesPerPixel == 4 && hasAlpha)))
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
|
|
|
[self _image_do_rgb_transform: &ii : matrix : _image_get_color_rgb_8];
|
2002-09-16 14:38:25 +00:00
|
|
|
UPDATE_UNBUFFERED
|
2002-08-26 14:03:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_rgb)
|
2002-08-26 14:36:43 +00:00
|
|
|
ii.colorspace = 1;
|
|
|
|
else if (colorSpaceName == NSDeviceCMYKColorSpace)
|
|
|
|
ii.colorspace = 2;
|
|
|
|
else if (colorSpaceName == NSDeviceWhiteColorSpace ||
|
|
|
|
colorSpaceName == NSDeviceBlackColorSpace ||
|
|
|
|
colorSpaceName == NSCalibratedWhiteColorSpace ||
|
|
|
|
colorSpaceName == NSCalibratedBlackColorSpace)
|
|
|
|
ii.colorspace = 3;
|
2002-08-26 14:03:04 +00:00
|
|
|
else
|
2002-08-26 14:36:43 +00:00
|
|
|
ii.colorspace = 0;
|
2002-08-26 14:03:04 +00:00
|
|
|
|
2002-08-26 14:36:43 +00:00
|
|
|
if (ii.colorspace != 0)
|
2002-08-26 14:03:04 +00:00
|
|
|
{
|
2002-08-26 14:36:43 +00:00
|
|
|
[self _image_do_rgb_transform: &ii : matrix :
|
2002-08-31 13:53:42 +00:00
|
|
|
_image_get_color_rgb_cmyk_gray];
|
2002-09-16 14:38:25 +00:00
|
|
|
UPDATE_UNBUFFERED
|
2002-08-26 14:03:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSLog(@"unimplemented DPSimage %ix%i |%@| bips=%i spp=%i bipp=%i bypr=%i planar=%i alpha=%i\n",
|
2002-08-26 14:36:43 +00:00
|
|
|
pixelsWide, pixelsHigh, matrix,
|
|
|
|
bitsPerSample, samplesPerPixel, bitsPerPixel, bytesPerRow, isPlanar,
|
2002-08-26 14:03:04 +00:00
|
|
|
hasAlpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|