mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-24 04:11:28 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@22464 72102866-910b-0410-8b05-ffd578937521
1248 lines
26 KiB
Objective-C
1248 lines
26 KiB
Objective-C
/*
|
|
* CairoGState.m
|
|
|
|
* Copyright (C) 2003 Free Software Foundation, Inc.
|
|
* August 31, 2003
|
|
* Written by Banlu Kemiyatorn <object at gmail dot com>
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
|
*/
|
|
|
|
#include <AppKit/NSBezierPath.h>
|
|
#include <AppKit/NSColor.h>
|
|
#include <AppKit/NSGraphics.h>
|
|
#include "cairo/CairoGState.h"
|
|
#include "cairo/CairoFontInfo.h"
|
|
#include "cairo/CairoSurface.h"
|
|
#include "cairo/CairoContext.h"
|
|
#include "NSBezierPathCairo.h"
|
|
#include <math.h>
|
|
|
|
#define FIXME() NSLog(@":::FIXME::: %@ %s", [self description], sel_get_name(_cmd))
|
|
|
|
static cairo_matrix_t local_matrix;
|
|
|
|
/* Be warned that CairoGState didn't derived GSGState */
|
|
@implementation CairoGState
|
|
|
|
+ (void) initialize
|
|
{
|
|
if (self == [CairoGState class])
|
|
{
|
|
}
|
|
}
|
|
|
|
- (void) forwardInvocation: (NSInvocation *)anInvocation
|
|
{
|
|
/* only for trapping any unknown message. */
|
|
NSLog (@":::UNKNOWN::: %@ %@", self, anInvocation);
|
|
exit(1);
|
|
}
|
|
|
|
- (id) copyWithZone: (NSZone *)zone
|
|
{
|
|
CairoGState *copy = (CairoGState *)NSCopyObject(self, 0, zone);
|
|
|
|
if (_ct)
|
|
{
|
|
cairo_path_t *path;
|
|
cairo_status_t status;
|
|
|
|
// FIXME: Need some way to do a copy
|
|
//cairo_copy(copy->_ct, _ct);
|
|
copy->_ct = cairo_create(cairo_get_target(_ct));
|
|
cairo_get_matrix(_ct, &local_matrix);
|
|
cairo_set_matrix(copy->_ct, &local_matrix);
|
|
path = cairo_copy_path(_ct);
|
|
cairo_append_path(copy->_ct, path);
|
|
cairo_path_destroy(path);
|
|
//NSLog(@"copy gstate old %d new %d", _ct, copy->_ct);
|
|
|
|
status = cairo_status(copy->_ct);
|
|
if (status != CAIRO_STATUS_SUCCESS)
|
|
{
|
|
NSLog(@"Cairo status %s in copy", cairo_status_to_string(status));
|
|
}
|
|
}
|
|
|
|
/*
|
|
NSLog(@"copy state %p(%p) to %p(%p)",self,
|
|
cairo_get_target(_ct),
|
|
copy,
|
|
cairo_get_target(copy->_ct)
|
|
);
|
|
*/
|
|
|
|
RETAIN(_font);
|
|
RETAIN(_surface);
|
|
|
|
return copy;
|
|
}
|
|
|
|
- (id) init
|
|
{
|
|
[self DPSinitgraphics];
|
|
return self;
|
|
}
|
|
|
|
- (id) initWithDrawContext: (CairoContext *)drawContext
|
|
{
|
|
//NSLog (@"CairoGState initWithDrawContext:%@", drawContext);
|
|
[self init];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
//NSLog(@"destate %p",self);
|
|
if (_ct)
|
|
{
|
|
cairo_destroy(_ct);
|
|
}
|
|
RELEASE(_font);
|
|
RELEASE(_surface);
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
static void
|
|
_flipCairoSurfaceMatrix(cairo_t *ct, CairoSurface *surface)
|
|
{
|
|
cairo_matrix_init_scale(&local_matrix, 1, -1);
|
|
|
|
if (surface != nil)
|
|
{
|
|
cairo_matrix_translate(&local_matrix, 0, -[surface size].height);
|
|
}
|
|
cairo_set_matrix(ct, &local_matrix);
|
|
}
|
|
|
|
- (void) setOffset: (NSPoint)theOffset
|
|
{
|
|
_offset = theOffset;
|
|
}
|
|
|
|
- (NSPoint) offset
|
|
{
|
|
return _offset;
|
|
}
|
|
|
|
- (void) GSCurrentDevice: (void **)device: (int *)x : (int *)y
|
|
{
|
|
if (x)
|
|
*x = 0;
|
|
if (y)
|
|
*y = 0;
|
|
if (device)
|
|
{
|
|
if (_surface)
|
|
{
|
|
*device = _surface->gsDevice;
|
|
}
|
|
else
|
|
{
|
|
*device = NULL;
|
|
NSLog(@":::FIXME::: surface isn't set. %@ %s", [self description],
|
|
sel_get_name(_cmd));
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) GSSetDevice: (void *)device : (int)x : (int)y
|
|
{
|
|
DESTROY(_surface);
|
|
_surface = [[CairoSurface alloc] initWithDevice: device];
|
|
_offset = NSMakePoint(x, y);
|
|
|
|
[self DPSinitgraphics];
|
|
/*
|
|
NSLog(@"after: surface %p on state %p %@",
|
|
cairo_get_target (_ct), self,
|
|
NSStringFromSize([_surface size]));
|
|
*/
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation CairoGState (Ops)
|
|
/*
|
|
* Color operations
|
|
*/
|
|
- (void) DPScurrentalpha: (float *)a
|
|
{
|
|
//FIXME
|
|
*a = 1.0;
|
|
//*a = cairo_current_alpha(_ct);
|
|
}
|
|
|
|
- (void) DPScurrentcmykcolor: (float *)c : (float *)m : (float *)y :(float *)k
|
|
{
|
|
float r, g, b;
|
|
|
|
[self DPScurrentrgbcolor: &r: &g: &b];
|
|
*c = 1 - r;
|
|
*m = 1 - g;
|
|
*y = 1 - b;
|
|
*k = 0;
|
|
}
|
|
|
|
- (void) DPScurrentgray: (float *)gray
|
|
{
|
|
float r, g, b;
|
|
|
|
[self DPScurrentrgbcolor: &r: &g: &b];
|
|
*gray = (r + g + b) / 3.0;
|
|
}
|
|
|
|
- (void) DPScurrenthsbcolor: (float *)h : (float *)s : (float *)b
|
|
{
|
|
NSColor *color;
|
|
float fr, fg, fb;
|
|
float alpha;
|
|
|
|
[self DPScurrentrgbcolor: &fr: &fg: &fb];
|
|
color = [NSColor colorWithCalibratedRed: fr
|
|
green: fg
|
|
blue: fb
|
|
alpha: 1.0];
|
|
[color getHue: h
|
|
saturation: s
|
|
brightness: b
|
|
alpha: &alpha];
|
|
}
|
|
|
|
- (void) DPScurrentrgbcolor: (float *)r : (float *)g : (float *)b
|
|
{
|
|
double dr, dg, db;
|
|
|
|
//FIXME:
|
|
//cairo_current_rgb_color(_ct, &dr, &dg, &db);
|
|
dr = dg = db = 0.8;
|
|
*r = dr;
|
|
*g = dg;
|
|
*b = db;
|
|
}
|
|
|
|
- (void) DPSsetalpha: (float)a
|
|
{
|
|
// float r, g, b;
|
|
|
|
//FIXME
|
|
//cairo_set_source_rgba(_ct, r, g, b, a);
|
|
}
|
|
|
|
- (void) DPSsetcmykcolor: (float)c : (float)m : (float)y : (float)k
|
|
{
|
|
double r, g, b;
|
|
|
|
r = 1 - c;
|
|
g = 1 - m;
|
|
b = 1 - y;
|
|
cairo_set_source_rgb(_ct, r, g, b);
|
|
}
|
|
|
|
- (void) DPSsetgray: (float)gray
|
|
{
|
|
cairo_set_source_rgb(_ct, gray, gray, gray);
|
|
}
|
|
|
|
- (void) DPSsethsbcolor: (float)h : (float)s : (float)b
|
|
{
|
|
NSColor *color;
|
|
float red, green, blue, alpha;
|
|
|
|
color = [NSColor colorWithCalibratedHue: h
|
|
saturation: s
|
|
brightness: b
|
|
alpha: 1.0];
|
|
[color getRed: &red
|
|
green: &green
|
|
blue: &blue
|
|
alpha: &alpha];
|
|
[self DPSsetrgbcolor: red : green : blue];
|
|
}
|
|
|
|
- (void) DPSsetrgbcolor: (float)r : (float)g: (float)b
|
|
{
|
|
cairo_set_source_rgb(_ct, r, g, b);
|
|
}
|
|
|
|
- (void) GSSetFillColorspace: (void *)spaceref
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSSetStrokeColorspace: (void *)spaceref
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSSetFillColor: (const float *)values
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSSetStrokeColor: (const float *)values
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
/*
|
|
* Text operations
|
|
*/
|
|
|
|
- (void) DPSashow: (float)x : (float)y : (const char *)s
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) DPSawidthshow: (float)cx : (float)cy : (int)c : (float)ax
|
|
: (float)ay : (const char *)s
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) DPScharpath: (const char *)s : (int)b
|
|
{
|
|
char *c = malloc(b + 1);
|
|
|
|
memcpy(c, s, b);
|
|
c[b + 1] = 0;
|
|
|
|
cairo_text_path(_ct, c);
|
|
free(c);
|
|
}
|
|
|
|
- (void) DPSshow: (const char *)s
|
|
{
|
|
cairo_show_text(_ct, s);
|
|
}
|
|
|
|
- (void) DPSwidthshow: (float)x : (float)y : (int)c : (const char *)s
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) DPSxshow: (const char *)s : (const float *)numarray : (int)size
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) DPSxyshow: (const char *)s : (const float *)numarray : (int)size
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) DPSyshow: (const char *)s : (const float *)numarray : (int)size
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSSetCharacterSpacing: (float)extra
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSSetFont: (GSFontInfo *)fontref
|
|
{
|
|
if (_font == fontref)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ASSIGN(_font, fontref);
|
|
//cairo_set_font_face(_ct, [((CairoFontInfo *)_font)->_faceInfo fontFace]);
|
|
//cairo_set_font_matrix(_ct, ((CairoFontInfo *)_font)->matrix);
|
|
}
|
|
|
|
- (void) GSSetFontSize: (float)size
|
|
{
|
|
cairo_set_font_size(_ct, size);
|
|
}
|
|
|
|
- (NSAffineTransform *) GSGetTextCTM
|
|
{
|
|
return [self GSCurrentCTM];
|
|
}
|
|
|
|
- (NSPoint) GSGetTextPosition
|
|
{
|
|
float x, y;
|
|
|
|
[self DPScurrentpoint: &x : &y];
|
|
return NSMakePoint(x, y);
|
|
}
|
|
|
|
- (void) GSSetTextCTM: (NSAffineTransform *)ctm
|
|
{
|
|
[self GSSetCTM: ctm];
|
|
}
|
|
|
|
- (void) GSSetTextDrawingMode: (GSTextDrawingMode)mode
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSSetTextPosition: (NSPoint)loc
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSShowText: (const char *)string : (size_t)length
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) GSShowGlyphs: (const NSGlyph *)glyphs : (size_t)length
|
|
{
|
|
[_font drawGlyphs: glyphs
|
|
length: length
|
|
on: _ct];
|
|
}
|
|
|
|
/*
|
|
* GState operations
|
|
*/
|
|
|
|
- (void) DPSinitgraphics
|
|
{
|
|
cairo_status_t status;
|
|
|
|
DESTROY(_font);
|
|
|
|
if (_ct)
|
|
{
|
|
cairo_destroy(_ct);
|
|
}
|
|
if (!_surface)
|
|
{
|
|
return;
|
|
}
|
|
_ct = cairo_create([_surface surface]);
|
|
status = cairo_status(_ct);
|
|
if (status != CAIRO_STATUS_SUCCESS)
|
|
{
|
|
NSLog(@"Cairo status %s in DPSinitgraphics", cairo_status_to_string(status));
|
|
}
|
|
_flipCairoSurfaceMatrix(_ct, _surface);
|
|
//NSLog(@"in flip %p (%p)", self, cairo_get_target(_ct));
|
|
/* Cairo's default line width is 2.0 */
|
|
cairo_set_line_width(_ct, 1.0);
|
|
}
|
|
|
|
- (void) DPScurrentflat: (float *)flatness
|
|
{
|
|
*flatness = cairo_get_tolerance(_ct);
|
|
}
|
|
|
|
- (void) DPScurrentlinecap: (int *)linecap
|
|
{
|
|
cairo_line_cap_t lc;
|
|
|
|
lc = cairo_get_line_cap(_ct);
|
|
*linecap = lc;
|
|
/*
|
|
switch (lc)
|
|
{
|
|
case CAIRO_LINE_CAP_BUTT:
|
|
*linecap = 0;
|
|
break;
|
|
case CAIRO_LINE_CAP_ROUND:
|
|
*linecap = 1;
|
|
break;
|
|
case CAIRO_LINE_CAP_SQUARE:
|
|
*linecap = 2;
|
|
break;
|
|
default:
|
|
NSLog(@"ERROR Line cap unknown");
|
|
exit(-1);
|
|
}
|
|
*/
|
|
}
|
|
|
|
- (void) DPScurrentlinejoin: (int *)linejoin
|
|
{
|
|
cairo_line_join_t lj;
|
|
|
|
lj = cairo_get_line_join(_ct);
|
|
*linejoin = lj;
|
|
/*
|
|
switch (lj)
|
|
{
|
|
case CAIRO_LINE_JOIN_MITER:
|
|
*linejoin = 0;
|
|
break;
|
|
case CAIRO_LINE_JOIN_ROUND:
|
|
*linejoin = 1;
|
|
break;
|
|
case CAIRO_LINE_JOIN_BEVEL:
|
|
*linejoin = 2;
|
|
break;
|
|
default:
|
|
NSLog(@"ERROR Line join unknown");
|
|
exit(-1);
|
|
}
|
|
*/
|
|
}
|
|
|
|
- (void) DPScurrentlinewidth: (float *)width
|
|
{
|
|
*width = cairo_get_line_width(_ct);
|
|
}
|
|
|
|
- (void) DPScurrentmiterlimit: (float *)limit
|
|
{
|
|
*limit = cairo_get_miter_limit(_ct);
|
|
}
|
|
|
|
- (void) DPScurrentpoint: (float *)x : (float *)y
|
|
{
|
|
double dx, dy;
|
|
|
|
cairo_get_current_point(_ct, &dx, &dy);
|
|
*x = dx;
|
|
*y = dy;
|
|
}
|
|
|
|
- (void) DPScurrentstrokeadjust: (int *)b
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
- (void) DPSsetdash: (const float *)pat : (int)size : (float)offset
|
|
{
|
|
double *dpat;
|
|
int i;
|
|
|
|
i = size;
|
|
dpat = malloc(sizeof(double) * size);
|
|
while (i)
|
|
{
|
|
i--;
|
|
dpat[i] = pat[i];
|
|
}
|
|
cairo_set_dash(_ct, dpat, size, offset);
|
|
free(dpat);
|
|
}
|
|
|
|
- (void) DPSsetflat: (float)flatness
|
|
{
|
|
cairo_set_tolerance(_ct, flatness);
|
|
}
|
|
|
|
- (void) DPSsetlinecap: (int)linecap
|
|
{
|
|
cairo_set_line_cap(_ct, (cairo_line_cap_t)linecap);
|
|
}
|
|
|
|
- (void) DPSsetlinejoin: (int)linejoin
|
|
{
|
|
cairo_set_line_join(_ct, (cairo_line_join_t)linejoin);
|
|
}
|
|
|
|
- (void) DPSsetlinewidth: (float)width
|
|
{
|
|
cairo_set_line_width(_ct, width);
|
|
}
|
|
|
|
- (void) DPSsetmiterlimit: (float)limit
|
|
{
|
|
cairo_set_miter_limit(_ct, limit);
|
|
}
|
|
|
|
- (void) DPSsetstrokeadjust: (int)b
|
|
{
|
|
FIXME();
|
|
}
|
|
|
|
/*
|
|
* Matrix operations
|
|
*/
|
|
|
|
- (void) DPSconcat: (const float *)m
|
|
{
|
|
cairo_matrix_init(&local_matrix, m[0], m[1], m[2], m[3], m[4], m[5]);
|
|
cairo_transform(_ct, &local_matrix);
|
|
}
|
|
|
|
- (void) DPSinitmatrix
|
|
{
|
|
cairo_identity_matrix(_ct);
|
|
_flipCairoSurfaceMatrix(_ct, _surface);
|
|
}
|
|
|
|
- (void) DPSrotate: (float)angle
|
|
{
|
|
cairo_rotate(_ct, angle);
|
|
}
|
|
|
|
- (void) DPSscale: (float)x : (float)y
|
|
{
|
|
cairo_scale(_ct, x, y);
|
|
}
|
|
|
|
- (void) DPStranslate: (float)x : (float)y
|
|
{
|
|
cairo_translate(_ct, x, y);
|
|
}
|
|
|
|
- (void) _flipCairoFont
|
|
{
|
|
cairo_matrix_init_scale(&local_matrix, 1, -1);
|
|
cairo_set_font_matrix(_ct, &local_matrix);
|
|
}
|
|
|
|
/*
|
|
static void
|
|
_log_matrix(cairo_t * ct)
|
|
{
|
|
cairo_get_matrix(ct, &local_matrix);
|
|
|
|
NSLog(@"%g %g %g %g %g %g", local_matrix.xx, local_matrix.yx, local_matrix.xy,
|
|
local_matrix.yy, local_matrix.x0, local_matrix.y0);
|
|
}
|
|
*/
|
|
|
|
- (NSAffineTransform *) GSCurrentCTM
|
|
{
|
|
NSAffineTransform *transform;
|
|
NSAffineTransformStruct tstruct;
|
|
cairo_matrix_t flip_matrix;
|
|
|
|
transform = [NSAffineTransform transform];
|
|
cairo_get_matrix(_ct, &local_matrix);
|
|
/*
|
|
NSLog(@"Before flip %f %f, %f, %f, %f, %f", local_matrix.xx, local_matrix.yx,
|
|
local_matrix.xy, local_matrix.yy, local_matrix.x0, local_matrix.y0);
|
|
*/
|
|
if (_surface)
|
|
{
|
|
cairo_matrix_init_translate(&flip_matrix, 0, -[_surface size].height);
|
|
cairo_matrix_multiply(&local_matrix, &local_matrix, &flip_matrix);
|
|
}
|
|
cairo_matrix_init_scale(&flip_matrix, 1, -1);
|
|
cairo_matrix_multiply(&local_matrix, &local_matrix, &flip_matrix);
|
|
/*
|
|
NSLog(@"After flip %f %f, %f, %f, %f, %f", local_matrix.xx, local_matrix.yx,
|
|
local_matrix.xy, local_matrix.yy, local_matrix.x0, local_matrix.y0);
|
|
*/
|
|
tstruct.m11 = local_matrix.xx;
|
|
tstruct.m12 = local_matrix.yx;
|
|
tstruct.m21 = local_matrix.xy;
|
|
tstruct.m22 = local_matrix.yy;
|
|
tstruct.tX = local_matrix.x0;
|
|
tstruct.tY = local_matrix.y0;
|
|
[transform setTransformStruct:tstruct];
|
|
return transform;
|
|
}
|
|
|
|
- (void) GSSetCTM: (NSAffineTransform *)ctm
|
|
{
|
|
NSAffineTransformStruct tstruct;
|
|
|
|
_flipCairoSurfaceMatrix(_ct, _surface);
|
|
tstruct = [ctm transformStruct];
|
|
cairo_matrix_init(&local_matrix,
|
|
tstruct.m11, tstruct.m12,
|
|
tstruct.m21, tstruct.m22,
|
|
tstruct.tX, tstruct.tY);
|
|
cairo_transform(_ct, &local_matrix);
|
|
}
|
|
|
|
- (void) GSConcatCTM: (NSAffineTransform *)ctm
|
|
{
|
|
NSAffineTransformStruct tstruct;
|
|
|
|
tstruct = [ctm transformStruct];
|
|
cairo_matrix_init(&local_matrix,
|
|
tstruct.m11, tstruct.m12,
|
|
tstruct.m21, tstruct.m22,
|
|
tstruct.tX, tstruct.tY);
|
|
cairo_transform(_ct, &local_matrix);
|
|
}
|
|
|
|
/*
|
|
* Paint operations
|
|
*/
|
|
|
|
- (NSPoint) currentPoint
|
|
{
|
|
double dx, dy;
|
|
|
|
cairo_get_current_point(_ct, &dx, &dy);
|
|
return NSMakePoint(dx, dy);
|
|
}
|
|
|
|
- (void) DPSarc: (float)x : (float)y : (float)r : (float)angle1 : (float)angle2
|
|
{
|
|
cairo_arc(_ct, x, y, r, angle1 * M_PI / 180, angle2 * M_PI / 180);
|
|
}
|
|
|
|
- (void) DPSarcn: (float)x : (float)y : (float)r : (float)angle1 : (float)angle2
|
|
{
|
|
cairo_arc_negative(_ct, x, y, r, angle1 * M_PI / 180, angle2 * M_PI / 180);
|
|
}
|
|
|
|
- (void) DPSarct: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)r
|
|
{
|
|
FIXME();
|
|
/*
|
|
cairo_arc_to(_ct, x1, y1, x2, y2, r);
|
|
*/
|
|
/*
|
|
NSBezierPath *newPath;
|
|
|
|
newPath = [[NSBezierPath alloc] init];
|
|
if ((path != nil) && ([path elementCount] != 0))
|
|
{
|
|
[newPath lineToPoint: [self currentPoint]];
|
|
}
|
|
[newPath appendBezierPathWithArcFromPoint: NSMakePoint(x1, y1)
|
|
toPoint: NSMakePoint(x2, y2)
|
|
radius: r];
|
|
[newPath transformUsingAffineTransform: ctm];
|
|
CHECK_PATH;
|
|
[path appendBezierPath: newPath];
|
|
RELEASE(newPath);
|
|
*/
|
|
}
|
|
|
|
- (void) DPSclip
|
|
{
|
|
cairo_clip(_ct);
|
|
}
|
|
|
|
- (void) DPSclosepath
|
|
{
|
|
cairo_close_path(_ct);
|
|
}
|
|
|
|
- (void) DPScurveto: (float)x1 : (float)y1 : (float)x2
|
|
: (float)y2 : (float)x3 : (float)y3
|
|
{
|
|
cairo_curve_to(_ct, x1, y1, x2, y2, x3, y3);
|
|
}
|
|
|
|
- (void) DPSeoclip
|
|
{
|
|
cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_EVEN_ODD);
|
|
cairo_clip(_ct);
|
|
cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_WINDING);
|
|
}
|
|
|
|
- (void) DPSeofill
|
|
{
|
|
cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_EVEN_ODD);
|
|
cairo_fill(_ct);
|
|
cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_WINDING);
|
|
}
|
|
|
|
- (void) DPSfill
|
|
{
|
|
cairo_fill(_ct);
|
|
}
|
|
|
|
- (void) DPSflattenpath
|
|
{
|
|
cairo_path_t *path;
|
|
|
|
path = cairo_copy_path_flat(_ct);
|
|
cairo_new_path(_ct);
|
|
cairo_append_path(_ct, path);
|
|
cairo_path_destroy(path);
|
|
}
|
|
|
|
- (void) DPSinitclip
|
|
{
|
|
cairo_reset_clip(_ct);
|
|
}
|
|
|
|
- (void) DPSlineto: (float)x : (float)y
|
|
{
|
|
cairo_line_to(_ct, x, y);
|
|
}
|
|
|
|
- (void) DPSmoveto: (float)x : (float)y
|
|
{
|
|
cairo_move_to(_ct, x, y);
|
|
}
|
|
|
|
- (void) DPSnewpath
|
|
{
|
|
cairo_new_path(_ct);
|
|
}
|
|
|
|
- (void) DPSpathbbox: (float *)llx : (float *)lly : (float *)urx : (float *)ury
|
|
{
|
|
NSBezierPath *path = [NSBezierPath bezierPathFromCairo: _ct];
|
|
NSRect rect = [path controlPointBounds];
|
|
|
|
if (llx)
|
|
*llx = NSMinX(rect);
|
|
if (lly)
|
|
*lly = NSMinY(rect);
|
|
if (urx)
|
|
*urx = NSMaxX(rect);
|
|
if (ury)
|
|
*ury = NSMaxY(rect);
|
|
}
|
|
|
|
- (void) DPSrcurveto: (float)x1 : (float)y1 : (float)x2
|
|
: (float)y2 : (float)x3 : (float)y3
|
|
{
|
|
cairo_rel_curve_to(_ct, x1, y1, x2, y2, x3, y3);
|
|
}
|
|
|
|
- (void) DPSrectclip: (float)x : (float)y : (float)w : (float)h
|
|
{
|
|
cairo_new_path(_ct);
|
|
cairo_move_to(_ct, x, y);
|
|
cairo_rel_line_to(_ct, w, 0);
|
|
cairo_rel_line_to(_ct, 0, h);
|
|
cairo_rel_line_to(_ct, -w, 0);
|
|
cairo_close_path(_ct);
|
|
cairo_clip(_ct);
|
|
cairo_new_path(_ct);
|
|
}
|
|
|
|
- (void) DPSrectfill: (float)x : (float)y : (float)w : (float)h
|
|
{
|
|
cairo_save(_ct);
|
|
cairo_new_path(_ct);
|
|
cairo_move_to(_ct, x, y);
|
|
cairo_rel_line_to(_ct, w, 0);
|
|
cairo_rel_line_to(_ct, 0, h);
|
|
cairo_rel_line_to(_ct, -w, 0);
|
|
cairo_close_path(_ct);
|
|
cairo_fill(_ct);
|
|
cairo_restore(_ct);
|
|
}
|
|
|
|
- (void) DPSrectstroke: (float)x : (float)y : (float)w : (float)h
|
|
{
|
|
cairo_save(_ct);
|
|
cairo_new_path(_ct);
|
|
cairo_move_to(_ct, x, y);
|
|
cairo_rel_line_to(_ct, w, 0);
|
|
cairo_rel_line_to(_ct, 0, h);
|
|
cairo_rel_line_to(_ct, -w, 0);
|
|
cairo_close_path(_ct);
|
|
cairo_stroke(_ct);
|
|
cairo_restore(_ct);
|
|
}
|
|
|
|
- (void) DPSreversepath
|
|
{
|
|
NSBezierPath *path = [NSBezierPath bezierPathFromCairo: _ct];
|
|
|
|
path = [path bezierPathByReversingPath];
|
|
cairo_new_path(_ct);
|
|
[path appendBezierPathToCairo: _ct];
|
|
}
|
|
|
|
- (void) DPSrlineto: (float)x : (float)y
|
|
{
|
|
cairo_rel_line_to(_ct, x, y);
|
|
}
|
|
|
|
- (void) DPSrmoveto: (float)x : (float)y
|
|
{
|
|
cairo_rel_move_to(_ct, x, y);
|
|
}
|
|
|
|
- (void) DPSstroke
|
|
{
|
|
cairo_stroke(_ct);
|
|
}
|
|
|
|
- (void) GSSendBezierPath: (NSBezierPath *)path
|
|
{
|
|
cairo_new_path(_ct);
|
|
[path appendBezierPathToCairo: _ct];
|
|
}
|
|
|
|
- (void) GSRectClipList: (const NSRect *)rects : (int)count
|
|
{
|
|
int i;
|
|
NSRect union_rect;
|
|
|
|
if (count == 0)
|
|
return;
|
|
|
|
/* FIXME see gsc
|
|
The specification is not clear if the union of the rects
|
|
should produce the new clip rect or if the outline of all rects
|
|
should be used as clip path.
|
|
*/
|
|
union_rect = rects[0];
|
|
for (i = 1; i < count; i++)
|
|
union_rect = NSUnionRect(union_rect, rects[i]);
|
|
|
|
[self DPSrectclip: NSMinX(union_rect) : NSMinY(union_rect)
|
|
: NSWidth(union_rect) : NSHeight(union_rect)];
|
|
}
|
|
|
|
- (void) GSRectFillList: (const NSRect *)rects : (int)count
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
[self DPSrectfill: NSMinX(rects[i]) : NSMinY(rects[i])
|
|
: NSWidth(rects[i]) : NSHeight(rects[i])];
|
|
}
|
|
}
|
|
|
|
/*
|
|
static NSString *
|
|
_opName(NSCompositingOperation op)
|
|
{
|
|
switch (op)
|
|
{
|
|
case NSCompositeClear:
|
|
return @"NSCompositeClear";
|
|
|
|
case NSCompositeCopy:
|
|
return @"NSCompositeCopy";
|
|
|
|
case NSCompositeSourceOver:
|
|
return @"NSCompositeSourceOver";
|
|
|
|
case NSCompositeSourceIn:
|
|
return @"NSCompositeSourceIn";
|
|
|
|
case NSCompositeSourceOut:
|
|
return @"NSCompositeSourceOut";
|
|
|
|
case NSCompositeSourceAtop:
|
|
return @"NSCompositeSourceAtop";
|
|
|
|
case NSCompositeDestinationOver:
|
|
return @"NSCompositeDestinationOver";
|
|
|
|
case NSCompositeDestinationIn:
|
|
return @"NSCompositeDestinationIn";
|
|
|
|
case NSCompositeDestinationOut:
|
|
return @"NSCompositeDestinationOut";
|
|
|
|
case NSCompositeDestinationAtop:
|
|
return @"NSCompositeDestinationAtop";
|
|
|
|
case NSCompositeXOR:
|
|
return @"NSCompositeXOR";
|
|
|
|
case NSCompositePlusDarker:
|
|
return @"NSCompositePlusDarker";
|
|
|
|
case NSCompositeHighlight:
|
|
return @"NSCompositeHighlight";
|
|
|
|
case NSCompositePlusLighter:
|
|
return @"NSCompositePlusLighter";
|
|
|
|
default:
|
|
return @"default";
|
|
|
|
}
|
|
}
|
|
*/
|
|
|
|
static void
|
|
_set_op(cairo_t * ct, NSCompositingOperation op)
|
|
{
|
|
switch (op)
|
|
{
|
|
case NSCompositeClear:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_CLEAR);
|
|
break;
|
|
case NSCompositeCopy:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
|
|
break;
|
|
case NSCompositeSourceOver:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_OVER);
|
|
break;
|
|
case NSCompositeSourceIn:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_IN);
|
|
break;
|
|
case NSCompositeSourceOut:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_OUT);
|
|
break;
|
|
case NSCompositeSourceAtop:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_ATOP);
|
|
break;
|
|
case NSCompositeDestinationOver:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_DEST_OVER);
|
|
break;
|
|
case NSCompositeDestinationIn:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_DEST_IN);
|
|
break;
|
|
case NSCompositeDestinationOut:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_DEST_OUT);
|
|
break;
|
|
case NSCompositeDestinationAtop:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_DEST_ATOP);
|
|
break;
|
|
case NSCompositeXOR:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_XOR);
|
|
break;
|
|
case NSCompositePlusDarker:
|
|
// FIXME
|
|
break;
|
|
case NSCompositeHighlight:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_SATURATE);
|
|
break;
|
|
case NSCompositePlusLighter:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_ADD);
|
|
break;
|
|
default:
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
|
|
}
|
|
}
|
|
|
|
- (void) DPSimage: (NSAffineTransform *)matrix : (int)pixelsWide
|
|
: (int)pixelsHigh : (int)bitsPerSample
|
|
: (int)samplesPerPixel : (int)bitsPerPixel
|
|
: (int)bytesPerRow : (BOOL)isPlanar
|
|
: (BOOL)hasAlpha : (NSString *)colorSpaceName
|
|
: (const unsigned char *const[5])data
|
|
{
|
|
cairo_format_t format;
|
|
NSAffineTransformStruct tstruct;
|
|
cairo_surface_t *surface;
|
|
unsigned char *tmp;
|
|
int i = 0;
|
|
int j;
|
|
int index;
|
|
unsigned int pixels = pixelsHigh * pixelsWide;
|
|
const unsigned char *bits = data[0];
|
|
unsigned char *rowData;
|
|
|
|
/*
|
|
NSLog(@"%@ DPSimage %dx%d (%p)", self, pixelsWide, pixelsHigh,
|
|
cairo_current_target_surface (_ct));
|
|
*/
|
|
if (isPlanar || !([colorSpaceName isEqualToString: NSDeviceRGBColorSpace] ||
|
|
[colorSpaceName isEqualToString: NSCalibratedRGBColorSpace]))
|
|
{
|
|
NSLog(@"Image format not support");
|
|
return;
|
|
}
|
|
|
|
// default is 8 bit grayscale
|
|
if (!bitsPerSample)
|
|
bitsPerSample = 8;
|
|
if (!samplesPerPixel)
|
|
samplesPerPixel = 1;
|
|
|
|
// FIXME - does this work if we are passed a planar image but no hints ?
|
|
if (!bitsPerPixel)
|
|
bitsPerPixel = bitsPerSample * samplesPerPixel;
|
|
if (!bytesPerRow)
|
|
bytesPerRow = (bitsPerPixel * pixelsWide) / 8;
|
|
|
|
/* make sure its sane - also handles row padding if hint missing */
|
|
while ((bytesPerRow * 8) < (bitsPerPixel * pixelsWide))
|
|
bytesPerRow++;
|
|
|
|
switch (bitsPerPixel)
|
|
{
|
|
case 32:
|
|
rowData = (unsigned char *)bits;
|
|
tmp = objc_malloc(pixels * 4);
|
|
index = 0;
|
|
|
|
for (i = 0; i < pixelsHigh; i++)
|
|
{
|
|
unsigned char *d = rowData;
|
|
|
|
for (j = 0; j < pixelsWide; j++)
|
|
{
|
|
tmp[index++] = d[2];
|
|
tmp[index++] = d[1];
|
|
tmp[index++] = d[0];
|
|
tmp[index++] = d[3];
|
|
d += 4;
|
|
}
|
|
rowData += bytesPerRow;
|
|
}
|
|
bits = tmp;
|
|
format = CAIRO_FORMAT_ARGB32;
|
|
break;
|
|
case 24:
|
|
rowData = (unsigned char *)bits;
|
|
tmp = objc_malloc(pixels * 4);
|
|
index = 0;
|
|
|
|
for (i = 0; i < pixelsHigh; i++)
|
|
{
|
|
unsigned char *d = rowData;
|
|
|
|
for (j = 0; j < pixelsWide; j++)
|
|
{
|
|
tmp[index++] = d[2];
|
|
tmp[index++] = d[1];
|
|
tmp[index++] = d[0];
|
|
tmp[index++] = 0;
|
|
d += 3;
|
|
}
|
|
rowData += bytesPerRow;
|
|
}
|
|
bits = tmp;
|
|
format = CAIRO_FORMAT_RGB24;
|
|
break;
|
|
default:
|
|
NSLog(@"Image format not support");
|
|
return;
|
|
}
|
|
// [self DPSinitclip];
|
|
|
|
tstruct = [matrix transformStruct];
|
|
/*
|
|
NSLog(@"%g %g %g %g %g %g",
|
|
tstruct.m11, tstruct.m12,
|
|
tstruct.m21, tstruct.m22,
|
|
tstruct.tX, tstruct.tY);
|
|
*/
|
|
cairo_save(_ct);
|
|
_flipCairoSurfaceMatrix(_ct, _surface);
|
|
cairo_matrix_init(&local_matrix,
|
|
tstruct.m11, tstruct.m12,
|
|
tstruct.m21, tstruct.m22,
|
|
tstruct.tX, tstruct.tY);
|
|
cairo_transform(_ct, &local_matrix);
|
|
|
|
surface = cairo_image_surface_create_for_data((void*)bits,
|
|
format,
|
|
pixelsWide,
|
|
pixelsHigh,
|
|
pixelsWide * 4);
|
|
|
|
if (surface == NULL)
|
|
{
|
|
NSLog(@"Image surface could not be created");
|
|
if (bits != data[0])
|
|
{
|
|
objc_free((unsigned char *)bits);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
cairo_set_source_surface(_ct, surface, 0, 0);
|
|
if (_viewIsFlipped)
|
|
{
|
|
cairo_rectangle(_ct, 0, -pixelsHigh, pixelsWide, pixelsHigh);
|
|
}
|
|
else
|
|
{
|
|
cairo_rectangle(_ct, 0, 0, pixelsWide, pixelsHigh);
|
|
}
|
|
cairo_fill(_ct);
|
|
cairo_surface_destroy(surface);
|
|
cairo_restore(_ct);
|
|
|
|
if (bits != data[0])
|
|
{
|
|
objc_free((unsigned char *)bits);
|
|
}
|
|
|
|
}
|
|
|
|
- (void) compositerect: (NSRect)aRect op: (NSCompositingOperation)op
|
|
{
|
|
_set_op(_ct, op);
|
|
cairo_rectangle(_ct, NSMinX(aRect), NSMinY(aRect), NSWidth(aRect),
|
|
NSHeight(aRect));
|
|
cairo_fill(_ct);
|
|
}
|
|
|
|
- (void) compositeGState: (CairoGState *)source
|
|
fromRect: (NSRect)aRect
|
|
toPoint: (NSPoint)aPoint
|
|
op: (NSCompositingOperation)op
|
|
fraction: (float)delta
|
|
{
|
|
cairo_surface_t *src;
|
|
double minx, miny;
|
|
double width, height;
|
|
|
|
/*
|
|
NSLog(NSStringFromRect(aRect));
|
|
NSLog(NSStringFromPoint(aPoint));
|
|
NSLog(@"src %p(%p,%@) des %p(%p,%@)",
|
|
source,cairo_get_target(source->_ct),NSStringFromSize([source->_surface size]),
|
|
self,cairo_get_target(_ct),NSStringFromSize([_surface size]));
|
|
*/
|
|
|
|
cairo_save(_ct);
|
|
_set_op(_ct, op);
|
|
|
|
src = cairo_get_target(source->_ct);
|
|
minx = NSMinX(aRect);
|
|
miny = NSMinY(aRect);
|
|
width = NSWidth(aRect);
|
|
height = NSHeight(aRect);
|
|
/*
|
|
cairo_user_to_device(source->_ct, &minx, &miny);
|
|
cairo_user_to_device_distance(source->_ct, &width, &height);
|
|
cairo_device_to_user(_ct, &minx, &miny);
|
|
cairo_device_to_user_distance(_ct, &width, &height);
|
|
NSLog(@"Rect %@ = %f, %f, %f, %f", NSStringFromRect(aRect), minx, miny, width, height);
|
|
*/
|
|
cairo_set_source_surface(_ct, src, aPoint.x - minx, aPoint.y - miny);
|
|
cairo_rectangle (_ct, aPoint.x, aPoint.y, width, height);
|
|
/*
|
|
cairo_set_source_surface(_ct, src, aPoint.x - NSMinX(aRect), aPoint.y - NSMinY(aRect));
|
|
cairo_rectangle (_ct, aPoint.x, aPoint.y, NSWidth(aRect), NSHeight(aRect));
|
|
*/
|
|
|
|
if (delta < 1.0)
|
|
{
|
|
cairo_pattern_t *pattern;
|
|
|
|
pattern = cairo_pattern_create_rgba(1.0, 1.0, 1.0, delta);
|
|
cairo_mask(_ct, pattern);
|
|
cairo_pattern_destroy(pattern);
|
|
}
|
|
cairo_fill(_ct);
|
|
cairo_restore(_ct);
|
|
}
|
|
|
|
- (void) compositeGState: (CairoGState *)source
|
|
fromRect: (NSRect)aRect
|
|
toPoint: (NSPoint)aPoint
|
|
op: (NSCompositingOperation)op
|
|
{
|
|
[self compositeGState: source
|
|
fromRect: aRect
|
|
toPoint: aPoint
|
|
op: op
|
|
fraction: 1.0];
|
|
}
|
|
|
|
- (void) dissolveGState: (CairoGState *)source
|
|
fromRect: (NSRect)aRect
|
|
toPoint: (NSPoint)aPoint
|
|
delta: (float)delta
|
|
{
|
|
[self compositeGState: source
|
|
fromRect: aRect
|
|
toPoint: aPoint
|
|
op: NSCompositeSourceOver
|
|
fraction: delta];
|
|
}
|
|
|
|
@end
|