mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-23 11:51:27 +00:00
* Source/art/path.m:, * Source/art/image.m (DPSimage:::::::::::): fixed type formatting specifiers. * Source/art/ftfont.m: removed include to ftfont-old.m. (drawString:at::to::::::::color::::transform:deltas:::widthChar:drawinfo:):, (drawGlyphs::at::to::::::color::::transform:drawinfo:):, (drawGlyphs::at::to::::::alpha::color::::transform:drawinfo:):, (bezierpath_funcs):, fixed type formatting specifiers; moved interface declaration of FTFontInfo to ftfont.h; removed GCCism. * Source/art/ftfont.h: moved interface declaration of FTFontInfo here. * Source/art/composite.m: fixed type formatting specifiers. * Source/art/FTFontEnumerator.m (load_font_configuration): fixed type formatting specifiers.
1517 lines
34 KiB
Objective-C
1517 lines
34 KiB
Objective-C
/*
|
|
Copyright (C) 2002 Free Software Foundation, Inc.
|
|
|
|
Author: Alexander Malmberg <alexander@malmberg.org>
|
|
|
|
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 Lesser 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <math.h>
|
|
|
|
#include <AppKit/NSAffineTransform.h>
|
|
|
|
#include "ARTGState.h"
|
|
|
|
#ifndef RDS
|
|
#include "x11/XWindowBuffer.h"
|
|
#endif
|
|
#include "blit.h"
|
|
|
|
|
|
@implementation ARTGState (composite)
|
|
|
|
|
|
/* Figure out what blit function we should use. If one or both of the
|
|
windows are known to be totally opaque, we can optimize in many ways
|
|
(see big table at the end of blit.m). Will set dst_need_alpha and blit_func
|
|
if necessary. Returns new operation, or -1 it it's a noop. */
|
|
- (int) _composite_func: (BOOL)src_opaque : (BOOL)src_transparent
|
|
: (BOOL)dst_opaque : (BOOL *)dst_needs_alpha
|
|
: (int)op : (void (**)(composite_run_t *c, int num))blit_func_r
|
|
{
|
|
void (*blit_func)(composite_run_t *c, int num);
|
|
|
|
*dst_needs_alpha = NO;
|
|
*blit_func_r = blit_func = NULL;
|
|
|
|
if (src_transparent) /* only happens with compositerect */
|
|
{
|
|
switch (op)
|
|
{
|
|
case NSCompositeCopy:
|
|
case NSCompositeSourceIn:
|
|
case NSCompositeSourceOut:
|
|
case NSCompositeDestinationIn:
|
|
case NSCompositeDestinationAtop:
|
|
case NSCompositePlusDarker:
|
|
return NSCompositeClear;
|
|
|
|
case NSCompositeSourceOver:
|
|
case NSCompositeSourceAtop:
|
|
case NSCompositeDestinationOver:
|
|
case NSCompositeDestinationOut:
|
|
case NSCompositeXOR:
|
|
case NSCompositeHighlight:
|
|
case NSCompositePlusLighter:
|
|
return -1; /* noop */
|
|
}
|
|
}
|
|
else
|
|
if (src_opaque && dst_opaque)
|
|
{ /* both source and destination are totally opaque */
|
|
switch (op)
|
|
{
|
|
case NSCompositeSourceOver:
|
|
case NSCompositeSourceIn:
|
|
case NSCompositeSourceAtop:
|
|
case NSCompositeHighlight:
|
|
return NSCompositeCopy;
|
|
|
|
case NSCompositeSourceOut:
|
|
case NSCompositeDestinationOut:
|
|
case NSCompositeXOR:
|
|
return NSCompositeClear;
|
|
|
|
case NSCompositeDestinationOver:
|
|
case NSCompositeDestinationIn:
|
|
case NSCompositeDestinationAtop:
|
|
return -1; /* noop */
|
|
|
|
case NSCompositePlusLighter:
|
|
blit_func = DI.composite_plusl_oo;
|
|
break;
|
|
case NSCompositePlusDarker:
|
|
blit_func = DI.composite_plusd_oo;
|
|
break;
|
|
}
|
|
}
|
|
else if (src_opaque)
|
|
{ /* source is opaque, destination has alpha */
|
|
switch (op)
|
|
{
|
|
case NSCompositeSourceOver:
|
|
case NSCompositeHighlight:
|
|
return NSCompositeCopy;
|
|
|
|
case NSCompositeSourceIn:
|
|
case NSCompositeSourceAtop:
|
|
blit_func = DI.composite_sin_oa;
|
|
break;
|
|
|
|
case NSCompositeSourceOut:
|
|
case NSCompositeXOR:
|
|
blit_func = DI.composite_sout_oa;
|
|
break;
|
|
|
|
case NSCompositeDestinationOver:
|
|
case NSCompositeDestinationAtop:
|
|
blit_func = DI.composite_dover_oa;
|
|
break;
|
|
|
|
case NSCompositeDestinationIn:
|
|
return -1; /* noop */
|
|
|
|
case NSCompositeDestinationOut:
|
|
return NSCompositeClear;
|
|
|
|
case NSCompositePlusLighter:
|
|
blit_func = DI.composite_plusl_oa;
|
|
break;
|
|
case NSCompositePlusDarker:
|
|
blit_func = DI.composite_plusd_oa;
|
|
break;
|
|
}
|
|
}
|
|
else if (dst_opaque)
|
|
{ /* source has alpha, destination is opaque */
|
|
switch (op)
|
|
{
|
|
case NSCompositeCopy:
|
|
*dst_needs_alpha = YES;
|
|
break;
|
|
|
|
case NSCompositeSourceOver:
|
|
case NSCompositeSourceAtop:
|
|
case NSCompositeHighlight:
|
|
blit_func = DI.composite_sover_ao;
|
|
break;
|
|
|
|
case NSCompositeSourceIn:
|
|
return NSCompositeCopy;
|
|
|
|
case NSCompositeSourceOut:
|
|
return NSCompositeClear;
|
|
|
|
case NSCompositeDestinationOver:
|
|
return -1; /* noop */
|
|
|
|
case NSCompositeDestinationIn:
|
|
case NSCompositeDestinationOut:
|
|
case NSCompositeDestinationAtop:
|
|
case NSCompositeXOR:
|
|
*dst_needs_alpha = YES;
|
|
goto both_have_alpha;
|
|
|
|
case NSCompositePlusLighter:
|
|
blit_func = DI.composite_plusl_ao;
|
|
break;
|
|
case NSCompositePlusDarker:
|
|
blit_func = DI.composite_plusd_ao;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{ /* both source and destination have alpha */
|
|
both_have_alpha:
|
|
switch (op)
|
|
{
|
|
case NSCompositeSourceOver:
|
|
case NSCompositeHighlight:
|
|
blit_func = DI.composite_sover_aa;
|
|
break;
|
|
case NSCompositeSourceIn:
|
|
blit_func = DI.composite_sin_aa;
|
|
break;
|
|
case NSCompositeSourceOut:
|
|
blit_func = DI.composite_sout_aa;
|
|
break;
|
|
case NSCompositeSourceAtop:
|
|
blit_func = DI.composite_satop_aa;
|
|
break;
|
|
case NSCompositeDestinationOver:
|
|
blit_func = DI.composite_dover_aa;
|
|
break;
|
|
case NSCompositeDestinationIn:
|
|
blit_func = DI.composite_din_aa;
|
|
break;
|
|
case NSCompositeDestinationOut:
|
|
blit_func = DI.composite_dout_aa;
|
|
break;
|
|
case NSCompositeDestinationAtop:
|
|
blit_func = DI.composite_datop_aa;
|
|
break;
|
|
case NSCompositeXOR:
|
|
blit_func = DI.composite_xor_aa;
|
|
break;
|
|
case NSCompositePlusLighter:
|
|
blit_func = DI.composite_plusl_aa;
|
|
break;
|
|
case NSCompositePlusDarker:
|
|
blit_func = DI.composite_plusd_aa;
|
|
break;
|
|
}
|
|
}
|
|
*blit_func_r = blit_func;
|
|
return op;
|
|
}
|
|
|
|
|
|
static void copy_oo(composite_run_t *c, int num)
|
|
{
|
|
memcpy(c->dst, c->src, num * DI.bytes_per_pixel);
|
|
}
|
|
|
|
static void copy_oa(composite_run_t *c, int num)
|
|
{
|
|
memcpy(c->dst, c->src, num * DI.bytes_per_pixel);
|
|
if (DI.inline_alpha)
|
|
{
|
|
unsigned char *dsta = c->dst + DI.inline_alpha_ofs;
|
|
|
|
for (; num; num--, dsta += 4)
|
|
*dsta = 0xff;
|
|
}
|
|
else
|
|
memset(c->dsta, 0xff, num);
|
|
}
|
|
|
|
static void copy_aa(composite_run_t *c, int num)
|
|
{
|
|
memcpy(c->dst,c->src,num*DI.bytes_per_pixel);
|
|
if (!DI.inline_alpha)
|
|
memcpy(c->dsta, c->srca, num);
|
|
}
|
|
|
|
|
|
/*
|
|
Handle compositing in transformed coordinate spaces. _rect_setup sets up
|
|
the a rect_trace_t structure, and each call to _rect_advance returns YES
|
|
and the left and right points on the next row, or NO if all rows are done.
|
|
*/
|
|
typedef struct
|
|
{
|
|
int x[4], y[4];
|
|
int cy, ey;
|
|
|
|
int left_delta;
|
|
int lx, lx_frac, ldx, ldx_frac, l_de, le;
|
|
int rx, rx_frac, rdx, rdx_frac, r_de, re;
|
|
|
|
int cx0, cx1;
|
|
} rect_trace_t;
|
|
|
|
static void _rect_setup(rect_trace_t *t, NSRect r, int cx0, int cx1,
|
|
NSAffineTransform *ctm, int up, int *y0, NSPoint offset)
|
|
{
|
|
float fx[4], fy[4];
|
|
NSPoint p;
|
|
|
|
t->cx0 = cx0;
|
|
t->cx1 = cx1;
|
|
|
|
p = r.origin;
|
|
p = [ctm transformPoint: p];
|
|
fx[0] = p.x; fy[0] = p.y;
|
|
p = r.origin; p.x += r.size.width;
|
|
p = [ctm transformPoint: p];
|
|
fx[1] = p.x; fy[1] = p.y;
|
|
p = r.origin; p.x += r.size.width; p.y += r.size.height;
|
|
p = [ctm transformPoint: p];
|
|
fx[2] = p.x; fy[2] = p.y;
|
|
p = r.origin; p.y += r.size.height;
|
|
p = [ctm transformPoint: p];
|
|
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);
|
|
|
|
t->x[0] = floor(fx[0]) - offset.x; t->y[0] = offset.y - floor(fy[0]);
|
|
t->x[1] = floor(fx[1]) - offset.x; t->y[1] = offset.y - floor(fy[1]);
|
|
t->x[2] = floor(fx[2]) - offset.x; t->y[2] = offset.y - floor(fy[2]);
|
|
t->x[3] = floor(fx[3]) - offset.x; t->y[3] = offset.y - floor(fy[3]);
|
|
|
|
/* If we're tracing the 'other way', we just flip the y-coordinates
|
|
and unflip when returning them */
|
|
if (up)
|
|
{
|
|
t->y[0] = -t->y[0];
|
|
t->y[1] = -t->y[1];
|
|
t->y[2] = -t->y[2];
|
|
t->y[3] = -t->y[3];
|
|
}
|
|
|
|
t->cy = t->y[t->le = 0];
|
|
if (t->y[1] < t->cy) t->cy = t->y[t->le = 1];
|
|
if (t->y[2] < t->cy) t->cy = t->y[t->le = 2];
|
|
if (t->y[3] < t->cy) t->cy = t->y[t->le = 3];
|
|
t->re = t->le;
|
|
|
|
t->ey = t->y[0];
|
|
if (t->y[1] > t->ey) t->ey = t->y[1];
|
|
if (t->y[2] > t->ey) t->ey = t->y[2];
|
|
if (t->y[3] > t->ey) t->ey = t->y[3];
|
|
|
|
if (t->x[(t->le + 1) & 3] < t->x[(t->le - 1) & 3])
|
|
t->left_delta = 1;
|
|
else
|
|
t->left_delta = -1;
|
|
|
|
/* silence the compiler */
|
|
t->lx = t->lx_frac = t->ldx = t->ldx_frac = t->l_de = 0;
|
|
t->rx = t->rx_frac = t->rdx = t->rdx_frac = t->r_de = 0;
|
|
|
|
if (up)
|
|
*y0 = -t->cy;
|
|
else
|
|
*y0 = t->cy;
|
|
}
|
|
|
|
static BOOL _rect_advance(rect_trace_t *t, int *x0, int *x1)
|
|
{
|
|
int next;
|
|
|
|
if (t->cy > t->ey)
|
|
return NO;
|
|
|
|
if (t->cy == t->y[t->le])
|
|
{
|
|
next = (t->le + t->left_delta) & 3;
|
|
if (t->y[t->le] == t->y[next])
|
|
{
|
|
t->le = next;
|
|
next = (t->le + t->left_delta) & 3;
|
|
}
|
|
t->l_de = t->y[next] - t->y[t->le];
|
|
if (!t->l_de)
|
|
return NO;
|
|
t->lx = t->x[t->le];
|
|
t->lx_frac = 0;
|
|
t->ldx = (t->x[next] - t->x[t->le]) / t->l_de;
|
|
t->ldx_frac = (t->x[next] - t->x[t->le]) % t->l_de;
|
|
|
|
t->le = next;
|
|
}
|
|
else
|
|
{
|
|
t->lx += t->ldx;
|
|
t->lx_frac += t->ldx_frac;
|
|
if (t->lx_frac < 0)
|
|
t->lx--, t->lx_frac += t->l_de;
|
|
if (t->lx_frac > t->l_de)
|
|
t->lx++, t->lx_frac -= t->l_de;
|
|
}
|
|
|
|
if (t->cy == t->y[t->re])
|
|
{
|
|
next = (t->re - t->left_delta) & 3;
|
|
if (t->y[t->re] == t->y[next])
|
|
{
|
|
t->re = next;
|
|
next = (t->re - t->left_delta) & 3;
|
|
}
|
|
t->r_de = t->y[next] - t->y[t->re];
|
|
if (!t->r_de)
|
|
return NO;
|
|
t->rx = t->x[t->re];
|
|
t->rx_frac = t->r_de - 1; /* TODO? */
|
|
t->rdx = (t->x[next] - t->x[t->re]) / t->r_de;
|
|
t->rdx_frac = (t->x[next] - t->x[t->re]) % t->r_de;
|
|
|
|
t->re = next;
|
|
}
|
|
else
|
|
{
|
|
t->rx += t->rdx;
|
|
t->rx_frac += t->rdx_frac;
|
|
if (t->rx_frac < 0)
|
|
t->rx--, t->rx_frac += t->r_de;
|
|
if (t->rx_frac > t->r_de)
|
|
t->rx++, t->rx_frac -= t->r_de;
|
|
}
|
|
|
|
if (t->rx > t->lx && t->rx >= t->cx0 && t->lx < t->cx1)
|
|
{
|
|
*x0 = t->lx - t->cx0;
|
|
if (*x0 < 0)
|
|
*x0 = 0;
|
|
*x1 = t->rx - t->cx0;
|
|
if (*x1 > t->cx1 - t->cx0)
|
|
*x1 = t->cx1 - t->cx0;
|
|
}
|
|
else
|
|
{
|
|
*x0 = *x1 = 0;
|
|
}
|
|
|
|
t->cy++;
|
|
|
|
return YES;
|
|
}
|
|
|
|
|
|
- (void) compositeGState: (GSGState *)source
|
|
fromRect: (NSRect)aRect
|
|
toPoint: (NSPoint)aPoint
|
|
op: (NSCompositingOperation)composite_op
|
|
{
|
|
ARTGState *ags = (ARTGState *)source;
|
|
unsigned char *dst, *dst_alpha, *src, *src_alpha;
|
|
|
|
int op;
|
|
void (*blit_func)(composite_run_t *c, int num) = NULL;
|
|
|
|
NSPoint sp, dp;
|
|
|
|
int cx0,cy0,cx1,cy1;
|
|
int sx0,sy0;
|
|
|
|
int sbpl, dbpl;
|
|
int asbpl, adbpl;
|
|
|
|
rect_trace_t state;
|
|
|
|
/* 0 = top->down, 1 = bottom->up */
|
|
/*
|
|
TODO: this does not handle the horizontal case
|
|
either 0=top->down, left->right, 2=top->down, right->left
|
|
or keep 0 and add 2=top->down, make temporary copy of source
|
|
could allocate a temporary array on the stack large enough to hold
|
|
one row and do the operations on it
|
|
*/
|
|
/* currently 2=top->down, be careful with overlapping rows */
|
|
/* order=1 is handled generically by flipping sbpl and dbpl and
|
|
adjusting the pointers. order=2 is handled specially */
|
|
int order;
|
|
|
|
int delta;
|
|
|
|
|
|
if (!wi || !wi->data || !ags->wi || !ags->wi->data) return;
|
|
if (all_clipped) return;
|
|
|
|
{
|
|
BOOL dst_needs_alpha;
|
|
op = [self _composite_func: !ags->wi->has_alpha : NO
|
|
: !wi->has_alpha : &dst_needs_alpha
|
|
: composite_op : &blit_func];
|
|
if (op == -1)
|
|
return;
|
|
|
|
if (dst_needs_alpha)
|
|
{
|
|
[wi needsAlpha];
|
|
if (!wi->has_alpha)
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/* these ignore the source window, so we send them off to
|
|
compositerect: op: */
|
|
if (op == NSCompositeClear || op == GSCompositeHighlight)
|
|
{
|
|
[self compositerect: NSMakeRect(aPoint.x, aPoint.y,
|
|
aRect.size.width, aRect.size.height)
|
|
op: op];
|
|
return;
|
|
}
|
|
|
|
|
|
/* Set up all the pointers and clip things */
|
|
|
|
dbpl = wi->bytes_per_line;
|
|
sbpl = ags->wi->bytes_per_line;
|
|
|
|
cx0 = clip_x0;
|
|
cy0 = clip_y0;
|
|
cx1 = clip_x1;
|
|
cy1 = clip_y1;
|
|
|
|
sp = [ags->ctm transformPoint: aRect.origin];
|
|
sp.x = floor(sp.x - ags->offset.x);
|
|
sp.y = floor(ags->offset.y - sp.y);
|
|
dp = [ctm transformPoint: aPoint];
|
|
dp.x = floor(dp.x - offset.x);
|
|
dp.y = floor(offset.y - dp.y);
|
|
|
|
if (dp.x - cx0 > sp.x)
|
|
cx0 = dp.x - sp.x;
|
|
if (dp.y - cy0 > sp.y)
|
|
cy0 = dp.y - sp.y;
|
|
|
|
if (cx1 - dp.x > ags->wi->sx - sp.x)
|
|
cx1 = dp.x + ags->wi->sx - sp.x;
|
|
if (cy1 - dp.y > ags->wi->sy - sp.y)
|
|
cy1 = dp.y + ags->wi->sy - sp.y;
|
|
|
|
sx0 = sp.x - dp.x + cx0;
|
|
sy0 = sp.y - dp.y + cy0;
|
|
|
|
dst = wi->data + cx0 * DI.bytes_per_pixel + cy0 * dbpl;
|
|
src = ags->wi->data + sx0 * DI.bytes_per_pixel + sy0 * sbpl;
|
|
|
|
if (ags->wi->has_alpha && op == NSCompositeCopy)
|
|
{
|
|
[wi needsAlpha];
|
|
if (!wi->has_alpha)
|
|
return;
|
|
}
|
|
|
|
if (ags->wi->has_alpha)
|
|
{
|
|
if (DI.inline_alpha)
|
|
src_alpha = src;
|
|
else
|
|
src_alpha = ags->wi->alpha + sx0 + sy0 * ags->wi->sx;
|
|
asbpl = ags->wi->sx;
|
|
}
|
|
else
|
|
{
|
|
src_alpha = NULL;
|
|
asbpl = 0;
|
|
}
|
|
|
|
if (wi->has_alpha)
|
|
{
|
|
if (DI.inline_alpha)
|
|
dst_alpha = dst;
|
|
else
|
|
dst_alpha = wi->alpha + cx0 + cy0 * wi->sx;
|
|
adbpl = wi->sx;
|
|
}
|
|
else
|
|
{
|
|
dst_alpha = NULL;
|
|
adbpl = 0;
|
|
}
|
|
|
|
cy1 -= cy0;
|
|
cx1 -= cx0;
|
|
|
|
if (cx0<0 || cy0<0 || cx0+cx1>wi->sx || cy0+cy1>wi->sy ||
|
|
sx0<0 || sy0<0 || sx0+cx1>ags->wi->sx || sy0+cy1>ags->wi->sy)
|
|
{
|
|
NSLog(@"Warning: invalid coordinates in composite: (%g %g)+(%g %g) -> (%g %g) got (%i %i) (%i %i) +(%i %i)",
|
|
aRect.origin.x,aRect.origin.x,aRect.size.width,aRect.size.height,aPoint.x,aPoint.y,
|
|
cx0,cy0,sx0,sy0,cx1,cy1);
|
|
return;
|
|
}
|
|
|
|
if (cx1<=0 || cy1<=0)
|
|
return;
|
|
|
|
/* To handle overlapping areas properly, we sometimes need to do
|
|
things bottom-up instead of top-down. If so, we flip the
|
|
coordinates here. */
|
|
order = 0;
|
|
if (ags->wi == self->wi && sy0 <= cy0)
|
|
{
|
|
order = 1;
|
|
dst += dbpl * (cy1 - 1);
|
|
src += sbpl * (cy1 - 1);
|
|
dst_alpha += adbpl * (cy1 - 1);
|
|
src_alpha += asbpl * (cy1 - 1);
|
|
dbpl = -dbpl;
|
|
sbpl = -sbpl;
|
|
adbpl = -adbpl;
|
|
asbpl = -asbpl;
|
|
if (sy0 == cy0)
|
|
{
|
|
if ((sx0 >= cx0 && sx0 <= cx0 + cx1) || (cx0 >= sx0 && cx0 <= sx0 + cx1))
|
|
{
|
|
order = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (op == NSCompositeCopy)
|
|
{
|
|
if (ags->wi->has_alpha)
|
|
blit_func = copy_aa;
|
|
else if (wi->has_alpha)
|
|
blit_func = copy_oa;
|
|
else
|
|
blit_func = copy_oo;
|
|
}
|
|
|
|
if (!blit_func)
|
|
{
|
|
NSLog(@"unimplemented: compositeGState: %p fromRect: (%g %g)+(%g %g) toPoint: (%g %g) op: %i",
|
|
source,
|
|
aRect.origin.x, aRect.origin.y,
|
|
aRect.size.width, aRect.size.height,
|
|
aPoint.x, aPoint.y,
|
|
op);
|
|
return;
|
|
}
|
|
|
|
{
|
|
int ry;
|
|
int x0, x1;
|
|
_rect_setup(&state, aRect, sx0, sx0 + cx1, ags->ctm, order, &ry, ags->offset);
|
|
if (order)
|
|
{
|
|
if (ry < sy0)
|
|
return;
|
|
delta = sy0 + cy1 - ry;
|
|
}
|
|
else
|
|
{
|
|
if (ry >= sy0 + cy1)
|
|
return;
|
|
delta = ry - sy0;
|
|
}
|
|
|
|
if (delta > 0)
|
|
{
|
|
src += sbpl * delta;
|
|
src_alpha += asbpl * delta;
|
|
dst += dbpl * delta;
|
|
dst_alpha += adbpl * delta;
|
|
}
|
|
else if (delta < 0)
|
|
{
|
|
delta = -delta;
|
|
while (delta)
|
|
{
|
|
if (!_rect_advance(&state,&x0,&x1))
|
|
{
|
|
break;
|
|
}
|
|
delta--;
|
|
}
|
|
if (delta)
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* this breaks the alpha pointer in some, but that's ok since in
|
|
all those cases, the alpha pointer isn't used (inline alpha or
|
|
no alpha) */
|
|
if (order == 2)
|
|
{
|
|
unsigned char tmpbuf[cx1 * DI.bytes_per_pixel];
|
|
unsigned char tmpbufa[cx1];
|
|
int y;
|
|
composite_run_t c;
|
|
int x0, x1;
|
|
|
|
c.dst = dst;
|
|
c.dsta = dst_alpha;
|
|
c.src = tmpbuf;
|
|
c.srca = tmpbufa;
|
|
for (y = cy1 - delta - 1; y >= 0; y--)
|
|
{
|
|
if (!_rect_advance(&state,&x0,&x1))
|
|
break;
|
|
x1 -= x0;
|
|
|
|
c.dst += x0 * DI.bytes_per_pixel;
|
|
c.dsta += x0;
|
|
/* TODO: update c.dst and c.dsta properly when x1==0 */
|
|
|
|
if (x1)
|
|
{
|
|
memcpy(tmpbuf, src + x0 * DI.bytes_per_pixel, x1 * DI.bytes_per_pixel);
|
|
if (ags->wi->has_alpha && !DI.inline_alpha)
|
|
memcpy(tmpbufa, src_alpha + x0, x1);
|
|
|
|
if (!clip_span)
|
|
{
|
|
blit_func(&c, x1);
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
}
|
|
else
|
|
{
|
|
unsigned int *span, *end;
|
|
BOOL state = NO;
|
|
|
|
span = &clip_span[clip_index[y + cy0 - clip_y0]];
|
|
end = &clip_span[clip_index[y + cy0 - clip_y0 + 1]];
|
|
|
|
x0 = x0 + cx0 - clip_x0;
|
|
x1 += x0;
|
|
while (span != end && *span < x0)
|
|
{
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (span != end)
|
|
{
|
|
while (span != end && *span < x1)
|
|
{
|
|
if (state)
|
|
blit_func(&c, *span - x0);
|
|
c.dst += (*span - x0) * DI.bytes_per_pixel;
|
|
c.dsta += (*span - x0);
|
|
c.src += (*span - x0) * DI.bytes_per_pixel;
|
|
c.srca += (*span - x0);
|
|
x0 = *span;
|
|
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (state)
|
|
blit_func(&c, x1 - x0);
|
|
}
|
|
x0 = x0 - cx0 + clip_x0;
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
c.src = tmpbuf;
|
|
c.srca = tmpbufa;
|
|
}
|
|
}
|
|
|
|
src += sbpl;
|
|
src_alpha += asbpl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int y;
|
|
composite_run_t c;
|
|
int x0, x1;
|
|
|
|
c.dst = dst;
|
|
c.dsta = dst_alpha;
|
|
c.src = src;
|
|
c.srca = src_alpha;
|
|
if (order)
|
|
y = cy1 - delta - 1;
|
|
else
|
|
y = delta;
|
|
for (; y < cy1 && y >= 0; order? y-- : y++)
|
|
{
|
|
if (!_rect_advance(&state,&x0,&x1))
|
|
break;
|
|
x1 -= x0;
|
|
if (x1 <= 0)
|
|
{
|
|
c.dst += dbpl;
|
|
c.dsta += adbpl;
|
|
c.src += sbpl;
|
|
c.srca += asbpl;
|
|
continue;
|
|
}
|
|
c.dst += x0 * DI.bytes_per_pixel;
|
|
c.dsta += x0;
|
|
c.src += x0 * DI.bytes_per_pixel;
|
|
c.srca += x0;
|
|
if (!clip_span)
|
|
{
|
|
blit_func(&c, x1);
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
c.src += sbpl - x0 * DI.bytes_per_pixel;
|
|
c.srca += asbpl - x0;
|
|
}
|
|
else
|
|
{
|
|
unsigned int *span, *end;
|
|
BOOL state = NO;
|
|
|
|
span = &clip_span[clip_index[y + cy0 - clip_y0]];
|
|
end = &clip_span[clip_index[y + cy0 - clip_y0 + 1]];
|
|
|
|
x0 = x0 + cx0 - clip_x0;
|
|
x1 += x0;
|
|
while (span != end && *span < x0)
|
|
{
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (span != end)
|
|
{
|
|
while (span != end && *span < x1)
|
|
{
|
|
if (state)
|
|
blit_func(&c, *span - x0);
|
|
c.dst += (*span - x0) * DI.bytes_per_pixel;
|
|
c.dsta += (*span - x0);
|
|
c.src += (*span - x0) * DI.bytes_per_pixel;
|
|
c.srca += (*span - x0);
|
|
x0 = *span;
|
|
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (state)
|
|
blit_func(&c, x1 - x0);
|
|
}
|
|
x0 = x0 - cx0 + clip_x0;
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
c.src += sbpl - x0 * DI.bytes_per_pixel;
|
|
c.srca += asbpl - x0;
|
|
}
|
|
}
|
|
}
|
|
UPDATE_UNBUFFERED
|
|
}
|
|
|
|
|
|
- (void) dissolveGState: (GSGState *)source
|
|
fromRect: (NSRect)aRect
|
|
toPoint: (NSPoint)aPoint
|
|
delta: (CGFloat)fraction
|
|
{
|
|
/* much setup code shared with compositeGState:... */
|
|
ARTGState *ags = (ARTGState *)source;
|
|
unsigned char *dst, *dst_alpha, *src, *src_alpha;
|
|
|
|
void (*blit_func)(composite_run_t *c, int num) = NULL;
|
|
|
|
NSPoint sp, dp;
|
|
|
|
int cx0,cy0,cx1,cy1;
|
|
int sx0,sy0;
|
|
|
|
int sbpl, dbpl;
|
|
int asbpl, adbpl;
|
|
|
|
rect_trace_t state;
|
|
|
|
/* 0 = top->down, 1 = bottom->up */
|
|
/*
|
|
TODO: this does not handle the horizontal case
|
|
either 0=top->down, left->right, 2=top->down, right->left
|
|
or keep 0 and add 2=top->down, make temporary copy of source
|
|
could allocate a temporary array on the stack large enough to hold
|
|
one row and do the operations on it
|
|
*/
|
|
/* currently 2=top->down, be careful with overlapping rows */
|
|
/* order=1 is handled generically by flipping sbpl and dbpl and
|
|
adjusting the pointers. order=2 is handled specially */
|
|
int order;
|
|
|
|
int delta;
|
|
|
|
|
|
if (!wi || !wi->data || !ags->wi || !ags->wi->data) return;
|
|
if (all_clipped) return;
|
|
|
|
/* Set up all the pointers and clip things */
|
|
|
|
dbpl = wi->bytes_per_line;
|
|
sbpl = ags->wi->bytes_per_line;
|
|
|
|
cx0 = clip_x0;
|
|
cy0 = clip_y0;
|
|
cx1 = clip_x1;
|
|
cy1 = clip_y1;
|
|
|
|
sp = [ags->ctm transformPoint: aRect.origin];
|
|
sp.x = floor(sp.x - ags->offset.x);
|
|
sp.y = floor(ags->offset.y - sp.y);
|
|
dp = [ctm transformPoint: aPoint];
|
|
dp.x = floor(dp.x - offset.x);
|
|
dp.y = floor(offset.y - dp.y);
|
|
|
|
if (dp.x - cx0 > sp.x)
|
|
cx0 = dp.x - sp.x;
|
|
if (dp.y - cy0 > sp.y)
|
|
cy0 = dp.y - sp.y;
|
|
|
|
if (cx1 - dp.x > ags->wi->sx - sp.x)
|
|
cx1 = dp.x + ags->wi->sx - sp.x;
|
|
if (cy1 - dp.y > ags->wi->sy - sp.y)
|
|
cy1 = dp.y + ags->wi->sy - sp.y;
|
|
|
|
sx0 = sp.x - dp.x + cx0;
|
|
sy0 = sp.y - dp.y + cy0;
|
|
|
|
dst = wi->data + cx0 * DI.bytes_per_pixel + cy0 * dbpl;
|
|
src = ags->wi->data + sx0 * DI.bytes_per_pixel + sy0 * sbpl;
|
|
|
|
if (ags->wi->has_alpha)
|
|
{
|
|
if (DI.inline_alpha)
|
|
src_alpha = src;
|
|
else
|
|
src_alpha = ags->wi->alpha + sx0 + sy0 * ags->wi->sx;
|
|
asbpl = ags->wi->sx;
|
|
}
|
|
else
|
|
{
|
|
src_alpha = NULL;
|
|
asbpl = 0;
|
|
}
|
|
|
|
if (wi->has_alpha)
|
|
{
|
|
if (DI.inline_alpha)
|
|
dst_alpha = dst;
|
|
else
|
|
dst_alpha = wi->alpha + cx0 + cy0 * wi->sx;
|
|
adbpl = wi->sx;
|
|
}
|
|
else
|
|
{
|
|
dst_alpha = NULL;
|
|
adbpl = 0;
|
|
}
|
|
|
|
cy1 -= cy0;
|
|
cx1 -= cx0;
|
|
|
|
if (cx0<0 || cy0<0 || cx0+cx1>wi->sx || cy0+cy1>wi->sy ||
|
|
sx0<0 || sy0<0 || sx0+cx1>ags->wi->sx || sy0+cy1>ags->wi->sy)
|
|
{
|
|
NSLog(@"Warning: invalid coordinates in dissolve: (%g %g)+(%g %g) -> (%g %g) got (%i %i) (%i %i) +(%i %i)",
|
|
aRect.origin.x,aRect.origin.x,aRect.size.width,aRect.size.height,aPoint.x,aPoint.y,
|
|
cx0,cy0,sx0,sy0,cx1,cy1);
|
|
return;
|
|
}
|
|
|
|
if (cx1<=0 || cy1<=0)
|
|
return;
|
|
|
|
/* To handle overlapping areas properly, we sometimes need to do
|
|
things bottom-up instead of top-down. If so, we flip the
|
|
coordinates here. */
|
|
order = 0;
|
|
if (ags->wi == self->wi && sy0 <= cy0)
|
|
{
|
|
order = 1;
|
|
dst += dbpl * (cy1 - 1);
|
|
src += sbpl * (cy1 - 1);
|
|
dst_alpha += adbpl * (cy1 - 1);
|
|
src_alpha += asbpl * (cy1 - 1);
|
|
dbpl = -dbpl;
|
|
sbpl = -sbpl;
|
|
adbpl = -adbpl;
|
|
asbpl = -asbpl;
|
|
if (sy0 == cy0)
|
|
{
|
|
if ((sx0 >= cx0 && sx0 <= cx0 + cx1) || (cx0 >= sx0 && cx0 <= sx0 + cx1))
|
|
{
|
|
order = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ags->wi->has_alpha && wi->has_alpha)
|
|
blit_func = DI.dissolve_aa;
|
|
else if (wi->has_alpha)
|
|
blit_func = DI.dissolve_oa;
|
|
else if (ags->wi->has_alpha)
|
|
blit_func = DI.dissolve_ao;
|
|
else
|
|
blit_func = DI.dissolve_oo;
|
|
|
|
if (!blit_func)
|
|
{
|
|
NSLog(@"unimplemented: dissolveGState: %p fromRect: (%g %g)+(%g %g) toPoint: (%g %g) delta: %g",
|
|
source,
|
|
aRect.origin.x, aRect.origin.y,
|
|
aRect.size.width, aRect.size.height,
|
|
aPoint.x, aPoint.y,
|
|
fraction);
|
|
return;
|
|
}
|
|
|
|
{
|
|
int ry;
|
|
int x0, x1;
|
|
_rect_setup(&state, aRect, sx0, sx0 + cx1, ags->ctm, order, &ry, ags->offset);
|
|
if (order)
|
|
{
|
|
if (ry < sy0)
|
|
return;
|
|
delta = sy0 + cy1 - ry;
|
|
}
|
|
else
|
|
{
|
|
if (ry >= sy0 + cy1)
|
|
return;
|
|
delta = ry - sy0;
|
|
}
|
|
|
|
if (delta > 0)
|
|
{
|
|
src += sbpl * delta;
|
|
src_alpha += asbpl * delta;
|
|
dst += dbpl * delta;
|
|
dst_alpha += adbpl * delta;
|
|
}
|
|
else if (delta < 0)
|
|
{
|
|
delta = -delta;
|
|
while (delta)
|
|
{
|
|
if (!_rect_advance(&state,&x0,&x1))
|
|
{
|
|
break;
|
|
}
|
|
delta--;
|
|
}
|
|
if (delta)
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* this breaks the alpha pointer in some cases, but that's ok since in
|
|
all those cases, the alpha pointer isn't used (inline alpha or
|
|
no alpha) */
|
|
if (order == 2)
|
|
{
|
|
unsigned char tmpbuf[cx1 * DI.bytes_per_pixel];
|
|
unsigned char tmpbufa[cx1];
|
|
int y;
|
|
composite_run_t c;
|
|
int x0, x1;
|
|
|
|
c.dst = dst;
|
|
c.dsta = dst_alpha;
|
|
c.src = tmpbuf;
|
|
c.srca = tmpbufa;
|
|
c.fraction = fraction * 255;
|
|
for (y = cy1 - delta - 1; y >= 0; y--)
|
|
{
|
|
if (!_rect_advance(&state,&x0,&x1))
|
|
break;
|
|
x1 -= x0;
|
|
|
|
c.dst += x0 * DI.bytes_per_pixel;
|
|
c.dsta += x0;
|
|
|
|
if (x1)
|
|
{
|
|
memcpy(tmpbuf, src + x0 * DI.bytes_per_pixel, x1 * DI.bytes_per_pixel);
|
|
if (ags->wi->has_alpha && !DI.inline_alpha)
|
|
memcpy(tmpbufa, src_alpha + x0, x1);
|
|
|
|
if (!clip_span)
|
|
{
|
|
blit_func(&c, x1);
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
}
|
|
else
|
|
{
|
|
unsigned int *span, *end;
|
|
BOOL state = NO;
|
|
|
|
span = &clip_span[clip_index[y + cy0 - clip_y0]];
|
|
end = &clip_span[clip_index[y + cy0 - clip_y0 + 1]];
|
|
|
|
x0 = x0 + cx0 - clip_x0;
|
|
x1 += x0;
|
|
while (span != end && *span < x0)
|
|
{
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (span != end)
|
|
{
|
|
while (span != end && *span < x1)
|
|
{
|
|
if (state)
|
|
blit_func(&c, *span - x0);
|
|
c.dst += (*span - x0) * DI.bytes_per_pixel;
|
|
c.dsta += (*span - x0);
|
|
c.src += (*span - x0) * DI.bytes_per_pixel;
|
|
c.srca += (*span - x0);
|
|
x0 = *span;
|
|
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (state)
|
|
blit_func(&c, x1 - x0);
|
|
}
|
|
x0 = x0 - cx0 + clip_x0;
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
c.src = tmpbuf;
|
|
c.srca = tmpbufa;
|
|
}
|
|
}
|
|
|
|
src += sbpl;
|
|
src_alpha += asbpl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int y;
|
|
composite_run_t c;
|
|
int x0, x1;
|
|
|
|
c.dst = dst;
|
|
c.dsta = dst_alpha;
|
|
c.src = src;
|
|
c.srca = src_alpha;
|
|
c.fraction = fraction * 255;
|
|
if (order)
|
|
y = cy1 - delta - 1;
|
|
else
|
|
y = delta;
|
|
for (; y < cy1 && y >= 0; order? y-- : y++)
|
|
{
|
|
if (!_rect_advance(&state,&x0,&x1))
|
|
break;
|
|
x1 -= x0;
|
|
if (x1 <= 0)
|
|
{
|
|
c.dst += dbpl;
|
|
c.dsta += adbpl;
|
|
c.src += sbpl;
|
|
c.srca += asbpl;
|
|
continue;
|
|
}
|
|
c.dst += x0 * DI.bytes_per_pixel;
|
|
c.dsta += x0;
|
|
c.src += x0 * DI.bytes_per_pixel;
|
|
c.srca += x0;
|
|
if (!clip_span)
|
|
{
|
|
blit_func(&c, x1);
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
c.src += sbpl - x0 * DI.bytes_per_pixel;
|
|
c.srca += asbpl - x0;
|
|
}
|
|
else
|
|
{
|
|
unsigned int *span, *end;
|
|
BOOL state = NO;
|
|
|
|
span = &clip_span[clip_index[y + cy0 - clip_y0]];
|
|
end = &clip_span[clip_index[y + cy0 - clip_y0 + 1]];
|
|
|
|
x0 = x0 + cx0 - clip_x0;
|
|
x1 += x0;
|
|
while (span != end && *span < x0)
|
|
{
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (span != end)
|
|
{
|
|
while (span != end && *span < x1)
|
|
{
|
|
if (state)
|
|
blit_func(&c, *span - x0);
|
|
c.dst += (*span - x0) * DI.bytes_per_pixel;
|
|
c.dsta += (*span - x0);
|
|
c.src += (*span - x0) * DI.bytes_per_pixel;
|
|
c.srca += (*span - x0);
|
|
x0 = *span;
|
|
|
|
state = !state;
|
|
span++;
|
|
if (span == end)
|
|
break;
|
|
}
|
|
if (state)
|
|
blit_func(&c, x1 - x0);
|
|
}
|
|
x0 = x0 - cx0 + clip_x0;
|
|
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
|
c.dsta += adbpl - x0;
|
|
c.src += sbpl - x0 * DI.bytes_per_pixel;
|
|
c.srca += asbpl - x0;
|
|
}
|
|
}
|
|
}
|
|
UPDATE_UNBUFFERED
|
|
}
|
|
|
|
- (void) compositeGState: (GSGState *)source
|
|
fromRect: (NSRect)aRect
|
|
toPoint: (NSPoint)aPoint
|
|
op: (NSCompositingOperation)op
|
|
fraction: (CGFloat)delta
|
|
{
|
|
if (op == NSCompositeSourceOver)
|
|
{
|
|
[self dissolveGState: source
|
|
fromRect: aRect
|
|
toPoint: aPoint
|
|
delta: delta];
|
|
}
|
|
else
|
|
{
|
|
[self compositeGState: source
|
|
fromRect: aRect
|
|
toPoint: aPoint
|
|
op: op];
|
|
}
|
|
}
|
|
|
|
- (void) compositerect: (NSRect)aRect
|
|
op: (NSCompositingOperation)op
|
|
{
|
|
/* much setup code shared with compositeGState:... */
|
|
unsigned char *dst, *dst_alpha;
|
|
int dbpl, adbpl;
|
|
|
|
int cx0, cy0, cx1, cy1;
|
|
|
|
void (*blit_func)(composite_run_t *c, int num);
|
|
|
|
rect_trace_t state;
|
|
|
|
int delta;
|
|
|
|
|
|
if (!wi || !wi->data) return;
|
|
if (all_clipped) return;
|
|
|
|
|
|
{
|
|
BOOL dest_needs_alpha;
|
|
|
|
/* TODO: which color? using fill_color for now */
|
|
op = [self _composite_func: fill_color[3] == 255 : fill_color[3] == 0
|
|
: !wi->has_alpha : &dest_needs_alpha
|
|
: op : &blit_func];
|
|
|
|
if (op == -1)
|
|
return;
|
|
|
|
if (dest_needs_alpha || op == NSCompositeClear)
|
|
{
|
|
[wi needsAlpha];
|
|
if (!wi->has_alpha)
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
dbpl = wi->bytes_per_line;
|
|
adbpl = wi->sx;
|
|
|
|
cx0 = clip_x0; cy0 = clip_y0;
|
|
cx1 = clip_x1; cy1 = clip_y1;
|
|
|
|
dst = wi->data + cx0 * DI.bytes_per_pixel + cy0 * dbpl;
|
|
dst_alpha = wi->alpha + cx0 + cy0 * wi->sx;
|
|
|
|
cx1 -= cx0;
|
|
cy1 -= cy0;
|
|
|
|
{
|
|
int ry;
|
|
int x0, x1;
|
|
_rect_setup(&state, aRect, cx0, cx0 + cx1, ctm, 0, &ry, offset);
|
|
if (ry >= cy0 + cy1)
|
|
return;
|
|
delta = ry - cy0;
|
|
|
|
if (delta > 0)
|
|
{
|
|
dst += dbpl * delta;
|
|
dst_alpha += adbpl * delta;
|
|
}
|
|
else if (delta < 0)
|
|
{
|
|
delta = -delta;
|
|
while (delta)
|
|
{
|
|
if (!_rect_advance(&state,&x0,&x1))
|
|
break;
|
|
delta--;
|
|
}
|
|
if (delta)
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
#define DO_STUFF(HANDLE_SPAN) \
|
|
{ \
|
|
int y; \
|
|
int x0, x1; \
|
|
int n; \
|
|
\
|
|
if (clip_span) \
|
|
{ \
|
|
for (y = delta; y < cy1; y++) \
|
|
{ \
|
|
unsigned int *span, *end; \
|
|
BOOL clip_state = NO; \
|
|
\
|
|
if (!_rect_advance(&state,&x0,&x1)) \
|
|
break; \
|
|
\
|
|
x1 -= x0; \
|
|
if (!x1) \
|
|
{ \
|
|
dst += dbpl; \
|
|
dst_alpha += adbpl; \
|
|
continue; \
|
|
} \
|
|
\
|
|
dst += x0 * DI.bytes_per_pixel; \
|
|
dst_alpha += x0; \
|
|
\
|
|
span = &clip_span[clip_index[y + cy0 - clip_y0]]; \
|
|
end = &clip_span[clip_index[y + cy0 - clip_y0 + 1]]; \
|
|
\
|
|
x0 = x0 + cx0 - clip_x0; \
|
|
x1 += x0; \
|
|
while (span != end && *span < x0) \
|
|
{ \
|
|
clip_state = !clip_state; \
|
|
span++; \
|
|
if (span == end) \
|
|
break; \
|
|
} \
|
|
if (span != end) \
|
|
{ \
|
|
while (span != end && *span < x1) \
|
|
{ \
|
|
if (clip_state) \
|
|
{ \
|
|
n = (*span - x0); \
|
|
HANDLE_SPAN \
|
|
} \
|
|
dst += (*span - x0) * DI.bytes_per_pixel; \
|
|
dst_alpha += (*span - x0); \
|
|
x0 = *span; \
|
|
\
|
|
clip_state = !clip_state; \
|
|
span++; \
|
|
if (span == end) \
|
|
break; \
|
|
} \
|
|
if (clip_state) \
|
|
{ \
|
|
n = x1 - x0; \
|
|
HANDLE_SPAN \
|
|
} \
|
|
} \
|
|
x0 = x0 - cx0 + clip_x0; \
|
|
\
|
|
dst += dbpl - x0 * DI.bytes_per_pixel; \
|
|
dst_alpha += adbpl - x0; \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
for (y = delta; y < cy1; y++) \
|
|
{ \
|
|
if (!_rect_advance(&state,&x0,&x1)) \
|
|
break; \
|
|
\
|
|
x1 -= x0; \
|
|
if (!x1) \
|
|
{ \
|
|
dst += dbpl; \
|
|
dst_alpha += adbpl; \
|
|
continue; \
|
|
} \
|
|
\
|
|
dst += x0 * DI.bytes_per_pixel; \
|
|
dst_alpha += x0; \
|
|
\
|
|
n = x1; \
|
|
HANDLE_SPAN \
|
|
\
|
|
dst += dbpl - x0 * DI.bytes_per_pixel; \
|
|
dst_alpha += adbpl - x0; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
if (op == NSCompositeClear)
|
|
{
|
|
DO_STUFF(
|
|
memset(dst, 0, n * DI.bytes_per_pixel);
|
|
if (!DI.inline_alpha)
|
|
memset(dst_alpha, 0, n);
|
|
)
|
|
}
|
|
else if (op == GSCompositeHighlight)
|
|
{
|
|
DO_STUFF(
|
|
{
|
|
unsigned char *d = dst;
|
|
n *= DI.bytes_per_pixel;
|
|
for (; n; n--, d++)
|
|
(*d) ^= 0xff;
|
|
}
|
|
)
|
|
}
|
|
else if (op == NSCompositeCopy)
|
|
{
|
|
render_run_t ri;
|
|
ri.dst = dst;
|
|
/* We don't want to blend, so we premultiply and fill the
|
|
alpha channel manually. */
|
|
ri.a = fill_color[3];
|
|
ri.r = (fill_color[0] * ri.a + 0xff) >> 8;
|
|
ri.g = (fill_color[1] * ri.a + 0xff) >> 8;
|
|
ri.b = (fill_color[2] * ri.a + 0xff) >> 8;
|
|
if (ri.a != 255 && !wi->has_alpha)
|
|
return;
|
|
|
|
DO_STUFF(
|
|
ri.dst = dst;
|
|
DI.render_run_opaque(&ri, n);
|
|
if (ri.a != 255)
|
|
{
|
|
if (DI.inline_alpha)
|
|
{
|
|
/* TODO: needs to change to support inline
|
|
alpha for non-32-bit modes */
|
|
unsigned char *p;
|
|
for (p = dst; n; n--, p += 4)
|
|
p[DI.inline_alpha_ofs] = ri.a;
|
|
}
|
|
else
|
|
{
|
|
memset(dst_alpha, ri.a, n);
|
|
}
|
|
}
|
|
)
|
|
}
|
|
else if (blit_func)
|
|
{
|
|
/* this is slightly ugly, but efficient */
|
|
unsigned char buf[DI.bytes_per_pixel * cx1];
|
|
unsigned char abuf[fill_color[3] == 255? 1 : cx1];
|
|
composite_run_t c;
|
|
|
|
c.src = buf;
|
|
if (fill_color[3] != 255)
|
|
c.srca = abuf;
|
|
else
|
|
c.srca = NULL;
|
|
|
|
{
|
|
render_run_t ri;
|
|
ri.dst = buf;
|
|
ri.dsta = NULL;
|
|
/* Note that we premultiply _here_ and set the alpha
|
|
channel manually (for speed; no reason to do slow
|
|
blending when we just want a straight blit of all
|
|
channels). */
|
|
ri.a = fill_color[3];
|
|
ri.r = (fill_color[0] * ri.a + 0xff) >> 8;
|
|
ri.g = (fill_color[1] * ri.a + 0xff) >> 8;
|
|
ri.b = (fill_color[2] * ri.a + 0xff) >> 8;
|
|
DI.render_run_opaque(&ri, cx1);
|
|
if (fill_color[3] != 255)
|
|
{
|
|
if (DI.inline_alpha)
|
|
{
|
|
int i;
|
|
unsigned char *s;
|
|
/* TODO: needs to change to support inline
|
|
alpha for non-32-bit modes */
|
|
for (i = 0, s = buf + DI.inline_alpha_ofs; i < cx1; i++, s += 4)
|
|
*s = ri.a;
|
|
}
|
|
else
|
|
memset(abuf, ri.a, cx1);
|
|
}
|
|
}
|
|
|
|
DO_STUFF(
|
|
c.dst = dst;
|
|
c.dsta = dst_alpha;
|
|
blit_func(&c, n);
|
|
)
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"unimplemented compositerect: (%g %g)+(%g %g) op: %lu",
|
|
aRect.origin.x, aRect.origin.y,
|
|
aRect.size.width, aRect.size.height,
|
|
op);
|
|
}
|
|
UPDATE_UNBUFFERED
|
|
}
|
|
|
|
@end
|
|
|