commit cabbe4281263cb2e5f9b0d30a3bdfe4eff24bf84 Author: ericwa Date: Mon Jan 4 23:28:16 2010 +0000 Add opal to gnustep/libs/ git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/opal/trunk@29208 72102866-910b-0410-8b05-ffd578937521 diff --git a/CGAffineTransform.c b/CGAffineTransform.c new file mode 100644 index 0000000..50ac874 --- /dev/null +++ b/CGAffineTransform.c @@ -0,0 +1,64 @@ +/** CGAffineTransform + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define IN_CGAFFINETRANSFORM_C +#include "CGAffineTransform.h" +#undef IN_CGAFFINETRANSFORM_C +#include +#include "opal.h" + +const CGAffineTransform CGAffineTransformIdentity = {1,0,0,1,0,0}; + +CGAffineTransform CGAffineTransformMakeRotation(float angle) +{ + CGAffineTransform matrix; + float cosa = cos(angle); + float sina = sin(angle); + + matrix.a = matrix.d = cosa; + matrix.b = sina; + matrix.c = -sina; + matrix.tx = matrix.ty = 0; + + return matrix; +} + +CGAffineTransform CGAffineTransformInvert(CGAffineTransform t) +{ + CGAffineTransform inv; + float det; + + det = t.a * t.d - t.b *t.c; + if (det == 0) { + errlog("%s:%d: Cannot invert matrix, determinant is 0\n", + __FILE__, __LINE__); + return t; + } + + inv.a = t.d / det; + inv.b = -t.b / det; + inv.c = -t.c / det; + inv.d = t.a / det; + inv.tx = (t.c * t.ty - t.d * t.tx) / det; + inv.ty = (t.b * t.tx - t.a * t.ty) / det; + + return inv; +} diff --git a/CGAffineTransform.h b/CGAffineTransform.h new file mode 100644 index 0000000..b8ec2fc --- /dev/null +++ b/CGAffineTransform.h @@ -0,0 +1,216 @@ +/** CGAffineTransform + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGAffineTransform_h +#define OPAL_CGAffineTransform_h + +#include +#include + +/* Data Types */ + +typedef struct CGAffineTransform +{ + float a; + float b; + float c; + float d; + float tx; + float ty; +} CGAffineTransform; + +/* Constants */ + +extern const CGAffineTransform CGAffineTransformIdentity; + +/* Functions */ + +/* All but the most complex functions are declared static inline in this + * header file so that they are maximally efficient. In order to provide + * true functions (for code modules that don't have this header) this + * header is included in CGAffineTransform.c where the functions are no longer + * declared inline. + */ +#ifdef IN_CGAFFINETRANSFORM_C +#define GS_AFTR_SCOPE extern +#define GS_AFTR_ATTR +#else +#define GS_AFTR_SCOPE static inline +#define GS_AFTR_ATTR __attribute__((unused)) +#endif + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformMake( + float a, + float b, + float c, + float d, + float tx, + float ty +) GS_AFTR_ATTR; + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformMakeTranslation( + float tx, + float ty +) GS_AFTR_ATTR; + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformMakeScale( + float sx, + float sy +) GS_AFTR_ATTR; + +CGAffineTransform CGAffineTransformMakeRotation(float angle); + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformConcat( + CGAffineTransform t1, + CGAffineTransform t2 +) GS_AFTR_ATTR; + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformTranslate( + CGAffineTransform t, + float tx, + float ty +) GS_AFTR_ATTR; + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformScale( + CGAffineTransform t, + float sx, + float sy +) GS_AFTR_ATTR; + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformRotate( + CGAffineTransform t, + float angle +) GS_AFTR_ATTR; + +CGAffineTransform CGAffineTransformInvert(CGAffineTransform t); + +GS_AFTR_SCOPE CGPoint CGPointApplyAffineTransform( + CGPoint point, + CGAffineTransform t +) GS_AFTR_ATTR; + +GS_AFTR_SCOPE CGSize CGSizeApplyAffineTransform( + CGSize size, + CGAffineTransform t +) GS_AFTR_ATTR; + +/* Inlined functions */ + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformMake( + float a, float b, float c, float d, float tx, float ty) +{ + CGAffineTransform matrix; + + matrix.a = a; + matrix.b = b; + matrix.c = c; + matrix.d = d; + matrix.tx = tx; + matrix.ty = ty; + + return matrix; +} + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformMakeTranslation( + float tx, float ty) +{ + CGAffineTransform matrix; + + matrix = CGAffineTransformIdentity; + matrix.tx = tx; + matrix.ty = ty; + + return matrix; +} + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformMakeScale(float sx, float sy) +{ + CGAffineTransform matrix; + + matrix = CGAffineTransformIdentity; + matrix.a = sx; + matrix.d = sy; + + return matrix; +} + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformConcat( + CGAffineTransform t1, CGAffineTransform t2) +{ + CGAffineTransform t; + + t.a = t1.a * t2.a + t1.b * t2.c; + t.b = t1.a * t2.b + t1.b * t2.d; + t.c = t1.c * t2.a + t1.d * t2.c; + t.d = t1.c * t2.b + t1.d * t2.d; + t.tx = t1.tx * t2.a + t1.ty * t2.c + t2.tx; + t.ty = t1.tx * t2.b + t1.ty * t2.d + t2.ty; + + return t; +} + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformTranslate( + CGAffineTransform t, float tx, float ty) +{ + t.tx += tx * t.a + ty * t.c; + t.ty += tx * t.b + ty * t.d; + + return t; +} + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformScale( + CGAffineTransform t, float sx, float sy) +{ + t.a *= sx; + t.b *= sx; + t.c *= sy; + t.d *= sy; + + return t; +} + +GS_AFTR_SCOPE CGAffineTransform CGAffineTransformRotate( + CGAffineTransform t, float angle) +{ + return CGAffineTransformConcat(CGAffineTransformMakeRotation(angle), t); +} + +GS_AFTR_SCOPE CGPoint CGPointApplyAffineTransform( + CGPoint point, CGAffineTransform t) +{ + return CGPointMake(t.a * point.x + t.c * point.y + t.tx, + t.b * point.x + t.d * point.y + t.ty); +} + +GS_AFTR_SCOPE CGSize CGSizeApplyAffineTransform( + CGSize size, CGAffineTransform t) +{ + CGSize r; + + r = CGSizeMake(t.a * size.width + t.c * size.height, + t.b * size.width + t.d * size.height); + if (r.width < 0) r.width = -r.width; + if (r.height < 0) r.height = -r.height; + + return r; +} + +#endif /* OPAL_CGAffineTransform_h */ diff --git a/CGBase.h b/CGBase.h new file mode 100644 index 0000000..d90fde0 --- /dev/null +++ b/CGBase.h @@ -0,0 +1,36 @@ +/** CGBase + + C Interface to graphics drawing library + + Copyright (C) 2009 Eric Wasylishen + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGBase_h +#define OPAL_CGBase_h + +#include + +#define CGFLOAT_DEFINED 1 +#define CGFLOAT_TYPE double +#define CGFLOAT_IS_DOUBLE 1 +#define CGFLOAT_MIN DBL_MIN +#define CGFLOAT_MAX DBL_MAX + +typedef CGFLOAT_TYPE CGFloat; + +#endif + diff --git a/CGBitmapContext.h b/CGBitmapContext.h new file mode 100644 index 0000000..b9ad6d7 --- /dev/null +++ b/CGBitmapContext.h @@ -0,0 +1,57 @@ +/** CGBitmapContext + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGBitMapContext_h +#define OPAL_CGBitMapContext_h + +#include + +/* Functions */ + +CGContextRef CGBitmapContextCreate( + void *data, + size_t width, + size_t height, + size_t bitsPerComponent, + size_t bytesPerRow, + CGColorSpaceRef colorspace, + CGImageAlphaInfo alphaInfo +); + +CGImageAlphaInfo CGBitmapContextGetAlphaInfo(CGContextRef ctx); + +size_t CGBitmapContextGetBitsPerComponent (CGContextRef ctx); + +size_t CGBitmapContextGetBitsPerPixel (CGContextRef ctx); + +size_t CGBitmapContextGetBytesPerRow (CGContextRef ctx); + +CGColorSpaceRef CGBitmapContextGetColorSpace(CGContextRef ctx); + +void *CGBitmapContextGetData(CGContextRef ctx); + +size_t CGBitmapContextGetHeight(CGContextRef ctx); + +size_t CGBitmapContextGetWidth(CGContextRef ctx); + +CGImageRef CGBitmapContextCreateImage(CGContextRef ctx); + +#endif /* OPAL_CGBitMapContext_h */ diff --git a/CGColor.c b/CGColor.c new file mode 100644 index 0000000..c72b67a --- /dev/null +++ b/CGColor.c @@ -0,0 +1,109 @@ +/** CGColor + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "opal.h" +#include "stdlib.h" + +typedef struct CGColor +{ + struct objbase base; + CGColorSpaceRef cspace; + float *comps; +} CGColor; + +CGColorRef CGColorCreate(CGColorSpaceRef colorspace, const float components[]) +{ + CGColorRef clr; + size_t nc, i; + + clr = opal_obj_alloc("CGColor", sizeof(CGColor)); + if (!clr) return NULL; + + nc = CGColorSpaceGetNumberOfComponents(colorspace); + clr->comps = malloc((nc+1)*sizeof(float)); + if (!clr->comps) { + errlog("%s:%d: malloc failed\n", __FILE__, __LINE__); + free(clr); + return NULL; + } + clr->cspace = colorspace; + CGColorSpaceRetain(colorspace); + for (i=0; i<=nc; i++) + clr->comps[i] = components[i]; + + return clr; +} + +void opal_dealloc_CGColor(void *clr) +{ + CGColorRef c = clr; + + CGColorSpaceRelease(c->cspace); + free(c->comps); + free(c); +} + +CGColorRef CGColorRetain(CGColorRef clr) +{ + return (clr ? opal_obj_retain(clr) : clr); +} + +void CGColorRelease(CGColorRef clr) +{ + if(clr) opal_obj_release(clr); +} + +CGColorRef CGColorCreateCopy(CGColorRef clr) +{ + return CGColorCreate(clr->cspace, clr->comps); +} + +CGColorRef CGColorCreateCopyWithAlpha(CGColorRef clr, float alpha) +{ + CGColorRef newclr; + + newclr = CGColorCreate(clr->cspace, clr->comps); + if (!newclr) return NULL; + + newclr->comps[CGColorSpaceGetNumberOfComponents(newclr->cspace)] = alpha; + return newclr; +} + +float CGColorGetAlpha(CGColorRef clr) +{ + return clr->comps[CGColorSpaceGetNumberOfComponents(clr->cspace)]; +} + +CGColorSpaceRef CGColorGetColorSpace(CGColorRef clr) +{ + return clr->cspace; +} + +const float *CGColorGetComponents(CGColorRef clr) +{ + return clr->comps; +} + +size_t CGColorGetNumberOfComponents(CGColorRef clr) +{ + return CGColorSpaceGetNumberOfComponents(clr->cspace); +} diff --git a/CGColor.h b/CGColor.h new file mode 100644 index 0000000..7ae330f --- /dev/null +++ b/CGColor.h @@ -0,0 +1,60 @@ +/** CGColor + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGColor_h +#define OPAL_CGColor_h + +#include +#include + +/* Data Types */ + +typedef struct CGColor * CGColorRef; + +/* Functions */ + +CGColorRef CGColorCreate(CGColorSpaceRef colorspace, const float components[]); + +CGColorRef CGColorCreateCopy(CGColorRef clr); + +CGColorRef CGColorCreateCopyWithAlpha(CGColorRef clr, float alpha); + +CGColorRef CGColorCreateWithPattern( + CGColorSpaceRef colorspace, + CGPatternRef pattern, + const float components[] +); + +float CGColorGetAlpha(CGColorRef clr); + +CGColorSpaceRef CGColorGetColorSpace(CGColorRef clr); + +const float *CGColorGetComponents(CGColorRef clr); + +size_t CGColorGetNumberOfComponents(CGColorRef clr); + +CGPatternRef CGColorGetPattern(CGColorRef clr); + +void CGColorRelease(CGColorRef clr); + +CGColorRef CGColorRetain(CGColorRef clr); + +#endif /* OPAL_CGColor_h */ diff --git a/CGColorSpace.c b/CGColorSpace.c new file mode 100644 index 0000000..fc8c711 --- /dev/null +++ b/CGColorSpace.c @@ -0,0 +1,116 @@ +/** CGColorSpace + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* FIXME: Color Management is not implemented yet. Consequently, color spaces + * are usually ignored and assumed to be deviceRGB. With most current equipment + * supporting the sRGB color space, this may be OK in most cases, though. + */ + +#include "CGColorSpace.h" +#include "opal.h" + +typedef struct CGColorSpace +{ + struct objbase base; + int numcomps; + void (*todevice)(double *dest, const float comps[]); +} CGColorSpace; + +static void opal_todev_rgb(double *dest, const float comps[]); +static void opal_todev_gray(double *dest, const float comps[]); + +/* Return these for everything now */ +static CGColorSpace deviceRGB = +{ + {"CGColorSpace", NULL, -1}, + 3, + opal_todev_rgb +}; + +static CGColorSpace deviceGray = +{ + {"CGColorSpace", NULL, -1}, + 1, + opal_todev_gray +}; + +CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void) +{ + return &deviceRGB; +} + +CGColorSpaceRef CGColorSpaceCreateDeviceGray(void) +{ + return &deviceGray; +} + +CGColorSpaceRef CGColorSpaceCreateWithName(opal_GenericColorSpaceNames name) +{ + switch (name) { + case kCGColorSpaceGenericGray: + return CGColorSpaceCreateDeviceGray(); + case kCGColorSpaceGenericRGB: + return CGColorSpaceCreateDeviceRGB(); + case kCGColorSpaceGenericCMYK: + default: + errlog("%s:%d: Unknown colorspace name\n", __FILE__, __LINE__); + return NULL; + } +} + +CGColorSpaceRef CGColorSpaceRetain(CGColorSpaceRef cs) +{ + /* NOP */ + return cs; +} + +void CGColorSpaceRelease(CGColorSpaceRef cs) +{ + /* NOP */ +} + +size_t CGColorSpaceGetNumberOfComponents(CGColorSpaceRef cs) +{ + return cs->numcomps; +} + +static void opal_todev_rgb(double *dest, const float comps[]) +{ + dest[0] = comps[0]; + dest[1] = comps[1]; + dest[2] = comps[2]; + dest[3] = comps[3]; +} + +static void opal_todev_gray(double *dest, const float comps[]) +{ + dest[0] = comps[0]; + dest[1] = comps[0]; + dest[2] = comps[0]; + dest[3] = comps[1]; +} + +/* FIXME: This sould really convert to the color space of the device, + * but Cairo only knows about RGBA, so we convert to that */ +void opal_cspace_todev(CGColorSpaceRef cs, double *dest, const float comps[]) +{ + cs->todevice(dest, comps); +} diff --git a/CGColorSpace.h b/CGColorSpace.h new file mode 100644 index 0000000..e6cf792 --- /dev/null +++ b/CGColorSpace.h @@ -0,0 +1,101 @@ +/** CGColorSpace + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGColorSpace_h +#define OPAL_CGColorSpace_h + +#include + +/* Data Types */ + +typedef struct CGColorSpace * CGColorSpaceRef; + +/* Constants */ + +typedef enum CGColorRenderingIntent { + kCGRenderingIntentDefault = 0, + kCGRenderingIntentAbsoluteColorimetric = 1, + kCGRenderingIntentRelativeColorimetric = 2, + kCGRenderingIntentPerceptual = 3, + kCGRenderingIntentSaturation = 4 +} CGColorRenderingIntent; + +typedef enum opal_GenericColorSpaceNames { + kCGColorSpaceGenericGray = 0, + kCGColorSpaceGenericRGB = 1, + kCGColorSpaceGenericCMYK = 2 +} opal_GenericColorSpaceNames; + +/* Functions */ + +CGColorSpaceRef CGColorSpaceCreateDeviceGray(void); + +CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void); + +CGColorSpaceRef CGColorSpaceCreateDeviceCMYK(void); + +CGColorSpaceRef CGColorSpaceCreateCalibratedGray( + const float *whitePoint, + const float *blackPoint, + float gamma +); + +CGColorSpaceRef CGColorSpaceCreateCalibratedRGB( + const float *whitePoint, + const float *blackPoint, + const float *gamma, + const float *matrix +); + +CGColorSpaceRef CGColorSpaceCreateLab( + const float *whitePoint, + const float *blackPoint, + const float *range +); + +CGColorSpaceRef CGColorSpaceCreateICCBased( + size_t nComponents, + const float *range, + CGDataProviderRef profile, + CGColorSpaceRef alternateSpace +); + +CGColorSpaceRef CGColorSpaceCreateIndexed( + CGColorSpaceRef baseSpace, + size_t lastIndex, + const unsigned char *colorTable +); + +CGColorSpaceRef CGColorSpaceCreateWithPlatformColorSpace( + void *platformColorSpace +); + +CGColorSpaceRef CGColorSpaceCreateWithName(opal_GenericColorSpaceNames name); + +CGColorSpaceRef CGColorSpaceCreatePattern(CGColorSpaceRef baseSpace); + +size_t CGColorSpaceGetNumberOfComponents(CGColorSpaceRef cs); + +CGColorSpaceRef CGColorSpaceRetain(CGColorSpaceRef cs); + +void CGColorSpaceRelease(CGColorSpaceRef cs); + +#endif /* OPAL_CGColorSpace_h */ diff --git a/CGContext-private.h b/CGContext-private.h new file mode 100644 index 0000000..60cfead --- /dev/null +++ b/CGContext-private.h @@ -0,0 +1,53 @@ +/** CGContext + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGContext_private_h +#define OPAL_CGContext_private_h + +#include +#include +#include "opal.h" + +typedef struct ct_additions ct_additions; +struct ct_additions +{ + ct_additions *next; /* for Save/Restore */ + double alpha; + CGColorRef fill_color; + cairo_pattern_t *fill_cp; + CGColorRef stroke_color; + cairo_pattern_t *stroke_cp; +}; + +typedef struct CGContext +{ + struct objbase base; + cairo_t *ct; /* A Cairo context -- destination of this CGContext */ + ct_additions *add; /* Additional things not in Cairo's gstate */ + struct { + double x; + double y; + } txtpos; +} CGContext; + +CGContextRef opal_new_CGContext(cairo_surface_t *target); + +#endif diff --git a/CGContext.c b/CGContext.c new file mode 100644 index 0000000..8a83658 --- /dev/null +++ b/CGContext.c @@ -0,0 +1,838 @@ +/** CGContext + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGContext-private.h" +#include +#include +#include +#include "opal.h" + +/* The default (opaque black) color in a Cairo context, + * used if no other color is set on the context yet */ +static cairo_pattern_t *default_cp; + +extern void opal_surface_flush(cairo_surface_t *target); +extern void opal_cspace_todev(CGColorSpaceRef cs, double *dest, const float comps[]); +extern CGFontRef opal_FontCreateWithName(const char *name); + +void opal_dealloc_CGContext(void *c) +{ + CGContextRef ctx = c; + ct_additions *ctadd, *next; + + ctadd = ctx->add; + while (ctadd) { + CGColorRelease(ctadd->fill_color); + cairo_pattern_destroy(ctadd->fill_cp); + CGColorRelease(ctadd->stroke_color); + cairo_pattern_destroy(ctadd->stroke_cp); + + next = ctadd->next; + free(ctadd); + ctadd = next; + } + + cairo_destroy(ctx->ct); + free(ctx); +} + +CGContextRef opal_new_CGContext(cairo_surface_t *target) +{ + CGContextRef ctx; + cairo_status_t cret; + + ctx = opal_obj_alloc("CGContext", sizeof(CGContext)); + if (!ctx) return NULL; + + ctx->add = NULL; + ctx->ct = cairo_create(target); + cret = cairo_status(ctx->ct); + if (cret) { + errlog("%s:%d: cairo_create status: %s\n", + __FILE__, __LINE__, cairo_status_to_string(cret)); + opal_dealloc_CGContext(ctx); + return NULL; + } + + ctx->add = calloc(1, sizeof(struct ct_additions)); + if (!ctx->add) { + errlog("%s:%d: calloc failed\n", __FILE__, __LINE__); + opal_dealloc_CGContext(ctx); + return NULL; + } + ctx->add->alpha = 1; + + if (!default_cp) { + default_cp = cairo_get_source(ctx->ct); + cairo_pattern_reference(default_cp); + } + + /* Cairo defaults to line width 2.0 (see http://cairographics.org/FAQ) */ + cairo_set_line_width(ctx->ct, 1); + + return ctx; +} + +CGContextRef CGContextRetain(CGContextRef ctx) +{ + return (ctx ? opal_obj_retain(ctx) : NULL); +} + +void CGContextRelease(CGContextRef ctx) +{ + if(ctx) opal_obj_release(ctx); +} + +void CGContextFlush(CGContextRef ctx) +{ + cairo_surface_t *target; + + target = cairo_get_target(ctx->ct); + /* FIXME: This doesn't work for most Cairo backends (including Xlib) */ + /* cairo_surface_flush(target); */ + /* So now we have to do it directly instead */ + opal_surface_flush(target); +} + +void CGContextSynchronize(CGContextRef ctx) +{ + /* FIXME: Could do cairo_surface_mark_dirty here, but that does nothing */ + /* NOP */ +} + +void CGContextBeginPage(CGContextRef ctx, const CGRect *mediaBox) +{ + /* FIXME: should we reset gstate?, mediaBox is ignored */ + cairo_copy_page(ctx->ct); +} + +void CGContextEndPage(CGContextRef ctx) +{ + cairo_show_page(ctx->ct); +} + +void CGContextScaleCTM(CGContextRef ctx, float sx, float sy) +{ + cairo_scale(ctx->ct, sx, sy); +} + +void CGContextTranslateCTM(CGContextRef ctx, float tx, float ty) +{ + cairo_translate(ctx->ct, tx, ty); +} + +void CGContextRotateCTM(CGContextRef ctx, float angle) +{ + cairo_rotate(ctx->ct, angle); +} + +void CGContextConcatCTM(CGContextRef ctx, CGAffineTransform transform) +{ + cairo_matrix_t cmat; + + cmat.xx = transform.a; + cmat.xy = transform.b; + cmat.yx = transform.c; + cmat.yy = transform.d; + cmat.x0 = transform.tx; + cmat.y0 = transform.ty; + + cairo_transform(ctx->ct, &cmat); +} + +CGAffineTransform CGContextGetCTM(CGContextRef ctx) +{ + cairo_matrix_t cmat; + + cairo_get_matrix(ctx->ct, &cmat); + return CGAffineTransformMake(cmat.xx, -cmat.yx, cmat.xy, -cmat.yy, cmat.x0, -cmat.y0); +/* return CGAffineTransformMake(cmat.xx, cmat.xy, cmat.yx, cmat.yy, cmat.x0, cmat.y0); */ +} + +void CGContextSaveGState(CGContextRef ctx) +{ + ct_additions *ctadd; + cairo_status_t cret; + + ctadd = calloc(1, sizeof(struct ct_additions)); + if (!ctadd) { + errlog("%s:%d: calloc failed\n", __FILE__, __LINE__); + return; + } + + cairo_save(ctx->ct); + cret = cairo_status(ctx->ct); + if (cret) { + errlog("%s:%d: cairo_save status: %s\n", + __FILE__, __LINE__, cairo_status_to_string(cret)); + free(ctadd); + return; + } + + *ctadd = *ctx->add; + CGColorRetain(ctadd->fill_color); + cairo_pattern_reference(ctadd->fill_cp); + CGColorRetain(ctadd->stroke_color); + cairo_pattern_reference(ctadd->stroke_cp); + ctadd->next = ctx->add; + ctx->add = ctadd; +} + +void CGContextRestoreGState(CGContextRef ctx) +{ + ct_additions *ctadd; + + if (!ctx->add) return; + + CGColorRelease(ctx->add->fill_color); + cairo_pattern_destroy(ctx->add->fill_cp); + CGColorRelease(ctx->add->stroke_color); + cairo_pattern_destroy(ctx->add->stroke_cp); + ctadd = ctx->add->next; + free(ctx->add); + ctx->add = ctadd; + + cairo_restore(ctx->ct); +} + +void CGContextSetShouldAntialias(CGContextRef ctx, int shouldAntialias) +{ + cairo_set_antialias(ctx->ct, + (shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE)); +} + +void CGContextSetLineWidth(CGContextRef ctx, float width) +{ + cairo_set_line_width(ctx->ct, width); +} + +void CGContextSetLineJoin(CGContextRef ctx, CGLineJoin join) +{ + cairo_set_line_join(ctx->ct, join); +} + +void CGContextSetMiterLimit(CGContextRef ctx, float limit) +{ + cairo_set_miter_limit(ctx->ct, limit); +} + +void CGContextSetLineCap(CGContextRef ctx, CGLineCap cap) +{ + cairo_set_line_cap(ctx->ct, cap); +} + +void CGContextSetLineDash( + CGContextRef ctx, + float phase, + const float lengths[], + size_t count) +{ + double dashes[count]; /* C99 allows this */ + size_t i; + + for (i=0; ict, dashes, count, phase); +} + +void CGContextSetFlatness(CGContextRef ctx, float flatness) +{ + cairo_set_tolerance(ctx->ct, flatness); +} + +void CGContextSetShadow( + CGContextRef ctx, + CGSize offset, + CGFloat radius) +{ + // FIXME: Implement +} + +void CGContextSetShadowWithColor( + CGContextRef ctx, + CGSize offset, + CGFloat radius, + CGColorRef color) +{ + // FIXME: Implement +} + +void CGContextBeginPath(CGContextRef ctx) +{ + cairo_new_path(ctx->ct); +} + +void CGContextClosePath(CGContextRef ctx) +{ + cairo_close_path(ctx->ct); +} + +void CGContextMoveToPoint(CGContextRef ctx, float x, float y) +{ + cairo_move_to(ctx->ct, x, y); +} + +void CGContextAddLineToPoint(CGContextRef ctx, float x, float y) +{ + cairo_line_to(ctx->ct, x, y); +} + +void CGContextAddLines(CGContextRef ctx, const CGPoint points[], size_t count) +{ + size_t i; + + if (count <= 0) return; + CGContextMoveToPoint(ctx, points[0].x, points[0].y); + for (i=1; ict, cp1x, cp1y, cp2x, cp2y, x, y); +} + +void CGContextAddRect(CGContextRef ctx, CGRect rect) +{ + cairo_rectangle(ctx->ct, rect.origin.x, rect.origin.y, + rect.size.width, rect.size.height); +} + +void CGContextAddRects(CGContextRef ctx, const CGRect rects[], size_t count) +{ + size_t i; + + for (i=0; ict, x, y, radius, startAngle, endAngle); + else + cairo_arc(ctx->ct, x, y, radius, startAngle, endAngle); +} + +void CGContextAddArcToPoint( + CGContextRef ctx, + float x1, + float y1, + float x2, + float y2, + float radius) +{ + double x0, y0; + double dx0, dy0, dx2, dy2, xl0, xl2; + double san, n0x, n0y, n2x, n2y, t; + + cairo_get_current_point(ctx->ct, &x0, &y0); + dx0 = x0 - x1; + dy0 = y0 - y1; + xl0 = sqrt(dx0*dx0 + dy0*dy0); + if (xl0 == 0) return; + + dx2 = x2 - x1; + dy2 = y2 - y1; + xl2 = sqrt(dx2*dx2 + dy2*dy2); + + san = dx2*dy0 - dx0*dy2; + if (san == 0) { + CGContextAddLineToPoint(ctx, x1, y1); + return; + } + + if (san < 0) { + n0x = -dy0 / xl0; + n0y = dx0 / xl0; + n2x = dy2 / xl2; + n2y = -dx2 / xl2; + } else { + n0x = dy0 / xl0; + n0y = -dx0 / xl0; + n2x = -dy2 / xl2; + n2y = dx2 / xl2; + } + t = (dx2*n2y - dx2*n0y - dy2*n2x + dy2*n0x) / san; + CGContextAddArc(ctx, + x1 + radius * (t * dx0 + n0x), y1 + radius * (t * dy0 + n0y), + radius, atan2(-n0y, -n0x), atan2(-n2y, -n2x), (san < 0)); +} + +void CGContextStrokePath(CGContextRef ctx) +{ + cairo_status_t cret; + + if(ctx->add->stroke_cp) + cairo_set_source(ctx->ct, ctx->add->stroke_cp); + else + cairo_set_source(ctx->ct, default_cp); + + cairo_stroke(ctx->ct); + cret = cairo_status(ctx->ct); + if (cret) + errlog("%s:%d: cairo_stroke status: %s\n", + __FILE__, __LINE__, cairo_status_to_string(cret)); +} + +static void fill_path(CGContextRef ctx, int eorule, int preserve) +{ + cairo_status_t cret; + + if(ctx->add->fill_cp) + cairo_set_source(ctx->ct, ctx->add->fill_cp); + else + cairo_set_source(ctx->ct, default_cp); + + if (eorule) cairo_set_fill_rule(ctx->ct, CAIRO_FILL_RULE_EVEN_ODD); + cairo_fill_preserve(ctx->ct); + if (eorule) cairo_set_fill_rule(ctx->ct, CAIRO_FILL_RULE_WINDING); + if (!preserve) cairo_new_path(ctx->ct); + cret = cairo_status(ctx->ct); + if (cret) + errlog("%s:%d: cairo_fill status: %s\n", + __FILE__, __LINE__, cairo_status_to_string(cret)); +} + +void CGContextFillPath(CGContextRef ctx) +{ + fill_path(ctx, 0, 0); +} + +void CGContextEOFillPath(CGContextRef ctx) +{ + fill_path(ctx, 1, 0); +} + +void CGContextDrawPath(CGContextRef ctx, CGPathDrawingMode mode) +{ + switch (mode) { + case kCGPathFill: + case kCGPathEOFill: + fill_path(ctx, (mode == kCGPathEOFill), 0); + break; + case kCGPathFillStroke: + case kCGPathEOFillStroke: + fill_path(ctx, (mode == kCGPathEOFillStroke), 1); + /* fall through */ + case kCGPathStroke: + CGContextStrokePath(ctx); + break; + default: + errlog("%s:%d: CGContextDrawPath invalid CGPathDrawingMode: %d\n", + __FILE__, __LINE__, mode); + } +} + +void CGContextStrokeRect(CGContextRef ctx, CGRect rect) +{ + CGContextBeginPath(ctx); + CGContextAddRect(ctx, rect); + CGContextStrokePath(ctx); +} + +void CGContextStrokeRectWithWidth(CGContextRef ctx, CGRect rect, float width) +{ + CGContextSetLineWidth(ctx, width); + CGContextStrokeRect(ctx, rect); + /* Line width is not restored (see Technical QA1045) */ +} + +void CGContextFillRect(CGContextRef ctx, CGRect rect) +{ + CGContextBeginPath(ctx); + CGContextAddRect(ctx, rect); + CGContextFillPath(ctx); +} + +void CGContextFillRects(CGContextRef ctx, const CGRect rects[], size_t count) +{ + CGContextBeginPath(ctx); + CGContextAddRects(ctx, rects, count); + CGContextFillPath(ctx); +} + +void CGContextStrokeLineSegments( + CGContextRef ctx, + const CGPoint points[], + size_t count) +{ + size_t i; + + CGContextBeginPath(ctx); + for (i=1; ict, &x, &y); + return CGPointMake(x, y); +} + +void CGContextClip(CGContextRef ctx) +{ + cairo_clip(ctx->ct); +} + +void CGContextEOClip(CGContextRef ctx) +{ + cairo_set_fill_rule(ctx->ct, CAIRO_FILL_RULE_EVEN_ODD); + CGContextClip(ctx); + cairo_set_fill_rule(ctx->ct, CAIRO_FILL_RULE_WINDING); +} + +void CGContextClipToRect(CGContextRef ctx, CGRect rect) +{ + CGContextBeginPath(ctx); + CGContextAddRect(ctx, rect); + CGContextClip(ctx); +} + +void CGContextClipToRects(CGContextRef ctx, const CGRect rects[], size_t count) +{ + CGContextBeginPath(ctx); + CGContextAddRects(ctx, rects, count); + CGContextClip(ctx); +} + +static inline void set_color(cairo_pattern_t **cp, CGColorRef clr, double alpha) +{ + double cc[4]; + cairo_pattern_t *newcp; + cairo_status_t cret; + + opal_cspace_todev(CGColorGetColorSpace(clr), cc, CGColorGetComponents(clr)); + newcp = cairo_pattern_create_rgba(cc[0], cc[1], cc[2], cc[3]*alpha); + cret = cairo_pattern_status(newcp); + if (cret) { + errlog("%s:%d: cairo_pattern_create_rgba status: %s\n", + __FILE__, __LINE__, cairo_status_to_string(cret)); + return; + } + cairo_pattern_destroy(*cp); + *cp = newcp; +} + +void CGContextSetFillColorWithColor(CGContextRef ctx, CGColorRef color) +{ + CGColorRelease(ctx->add->fill_color); + ctx->add->fill_color = color; + CGColorRetain(color); + set_color(&ctx->add->fill_cp, color, ctx->add->alpha); +} + +void CGContextSetStrokeColorWithColor(CGContextRef ctx, CGColorRef color) +{ + CGColorRelease(ctx->add->stroke_color); + ctx->add->stroke_color = color; + CGColorRetain(color); + set_color(&ctx->add->stroke_cp, color, ctx->add->alpha); +} + +void CGContextSetAlpha(CGContextRef ctx, float alpha) +{ + if (alpha < 0) + alpha = 0; + else if (alpha > 1) + alpha = 1; + ctx->add->alpha = alpha; + // FIXME: Should we really check that these are non-null? + if (ctx->add->stroke_color) + set_color(&ctx->add->stroke_cp, ctx->add->stroke_color, ctx->add->alpha); + if (ctx->add->fill_color) + set_color(&ctx->add->fill_cp, ctx->add->fill_color, ctx->add->alpha); +} + +void CGContextSetFillColorSpace(CGContextRef ctx, CGColorSpaceRef colorspace) +{ + float *components; + CGColorRef color; + size_t nc; + + nc = CGColorSpaceGetNumberOfComponents(colorspace); + components = calloc(nc+1, sizeof(float)); + if (components) { + errlog("%s:%d: calloc failed\n", __FILE__, __LINE__); + return; + } + /* Default is an opaque, zero intensity color (usually black) */ + components[nc] = 1; + color = CGColorCreate(colorspace, components); + free(components); + CGContextSetFillColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetStrokeColorSpace(CGContextRef ctx, CGColorSpaceRef colorspace) +{ + float *components; + CGColorRef color; + size_t nc; + + nc = CGColorSpaceGetNumberOfComponents(colorspace); + components = calloc(nc+1, sizeof(float)); + if (components) { + errlog("%s:%d: calloc failed\n", __FILE__, __LINE__); + return; + } + /* Default is an opaque, zero intensity color (usually black) */ + components[nc] = 1; + color = CGColorCreate(colorspace, components); + free(components); + CGContextSetStrokeColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetFillColor(CGContextRef ctx, const float components[]) +{ + CGColorSpaceRef cs; + CGColorRef color; + + cs = CGColorGetColorSpace(ctx->add->fill_color); + color = CGColorCreate(cs, components); + CGContextSetFillColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetStrokeColor(CGContextRef ctx, const float components[]) +{ + CGColorSpaceRef cs; + CGColorRef color; + + cs = CGColorGetColorSpace(ctx->add->stroke_color); + color = CGColorCreate(cs, components); + CGContextSetStrokeColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetGrayFillColor(CGContextRef ctx, float gray, float alpha) +{ + float comps[2]; + CGColorSpaceRef cs; + CGColorRef color; + + comps[0] = gray; + comps[1] = alpha; + cs = CGColorSpaceCreateDeviceGray(); + color = CGColorCreate(cs, comps); + CGColorSpaceRelease(cs); + CGContextSetFillColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetGrayStrokeColor(CGContextRef ctx, float gray, float alpha) +{ + float comps[2]; + CGColorSpaceRef cs; + CGColorRef color; + + comps[0] = gray; + comps[1] = alpha; + cs = CGColorSpaceCreateDeviceGray(); + color = CGColorCreate(cs, comps); + CGColorSpaceRelease(cs); + CGContextSetStrokeColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetRGBFillColor(CGContextRef ctx, + float r, float g, float b, float alpha) +{ + float comps[4]; + CGColorSpaceRef cs; + CGColorRef color; + + comps[0] = r; + comps[1] = g; + comps[2] = b; + comps[3] = alpha; + cs = CGColorSpaceCreateDeviceRGB(); + color = CGColorCreate(cs, comps); + CGColorSpaceRelease(cs); + CGContextSetFillColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetRGBStrokeColor(CGContextRef ctx, + float r, float g, float b, float alpha) +{ + float comps[4]; + CGColorSpaceRef cs; + CGColorRef color; + + comps[0] = r; + comps[1] = g; + comps[2] = b; + comps[3] = alpha; + cs = CGColorSpaceCreateDeviceRGB(); + color = CGColorCreate(CGColorSpaceCreateDeviceRGB(), comps); + CGColorSpaceRelease(cs); + CGContextSetStrokeColorWithColor(ctx, color); + CGColorRelease(color); +} + +void CGContextSetFont(CGContextRef ctx, CGFontRef font) +{ + if (!font) { + errlog("%s:%d: CGContextSetFont got NULL\n", __FILE__, __LINE__); + return; + } + cairo_set_font_face(ctx->ct, (cairo_font_face_t *)font); +} + +void CGContextSetFontSize(CGContextRef ctx, float size) +{ + cairo_matrix_t fm; + + /* The 10 * 96/72 factor is a heuristic. 1/96 is the cairo default unit, + * 1/72 is the default in Postscript and PDF but why is *10 needed? + * Nevertheless, it seems to produce about the right results. */ + cairo_matrix_init_scale(&fm, size * 10 * 96.0/72.0, -size * 10 * 96.0/72.0); + cairo_set_font_matrix(ctx->ct, &fm); +} + +void CGContextSelectFont( + CGContextRef ctx, + const char *name, + float size, + CGTextEncoding textEncoding) +{ + /* FIXME: textEncoding is ignored */ + CGContextSetFont(ctx, opal_FontCreateWithName(name)); + CGContextSetFontSize(ctx, size); +} + +void CGContextSetTextPosition(CGContextRef ctx, float x, float y) +{ + ctx->txtpos.x = x; + ctx->txtpos.y = y; +} + +CGPoint CGContextGetTextPosition(CGContextRef ctx) +{ + return CGPointMake(ctx->txtpos.x, ctx->txtpos.y); +} + +void CGContextShowText(CGContextRef ctx, const char *cstring, size_t length) +{ + double x, y; + + cairo_get_current_point(ctx->ct, &x, &y); + cairo_move_to(ctx->ct, ctx->txtpos.x, ctx->txtpos.y); + + /* FIXME: All text is currently drawn with fill color. + * Should support other text drawing modes. */ + if(ctx->add->fill_cp) + cairo_set_source(ctx->ct, ctx->add->fill_cp); + else + cairo_set_source(ctx->ct, default_cp); + + /* FIXME: length is ignored, \0 terminated string is assumed */ + cairo_show_text(ctx->ct, cstring); + + cairo_get_current_point(ctx->ct, &ctx->txtpos.x, &ctx->txtpos.y); + cairo_move_to(ctx->ct, x, y); +} + +void CGContextShowTextAtPoint( + CGContextRef ctx, + float x, + float y, + const char *cstring, + size_t length) +{ + CGContextSetTextPosition(ctx, x, y); + CGContextShowText(ctx, cstring, length); +} + +void CGContextBeginTransparencyLayer( + CGContextRef ctx, + CFDictionaryRef auxiliaryInfo) +{ + // Save cairo state, to match CGContextBeginTransparencyLayerWithRect + cairo_save(ctx->ct); + + // Save Opal state, and set alpha to 1 and shadows off (within the + // transparency layer) + CGContextSaveGState(ctx); + CGContextSetAlpha(ctx, 1.0); + CGContextSetShadowWithColor(ctx, CGSizeMake(0,0), 0, NULL); + + cairo_push_group(ctx->ct); +} + +void CGContextBeginTransparencyLayerWithRect( + CGContextRef ctx, + CGRect rect, + CFDictionaryRef auxiliaryInfo) +{ + // Save cairo state because we are goint to clip to the given rect + cairo_save(ctx->ct); + cairo_new_path(ctx->ct); + CGContextAddRect(ctx, rect); + cairo_clip(ctx->ct); + + // Save Opal state, and set alpha to 1 and shadows off (within the + // transparency layer) + CGContextSaveGState(ctx); + CGContextSetAlpha(ctx, 1.0); + CGContextSetShadowWithColor(ctx, CGSizeMake(0,0), 0, NULL); + + cairo_push_group(ctx->ct); +} + +void CGContextEndTransparencyLayer(CGContextRef ctx) +{ + cairo_pop_group_to_source(ctx->ct); + + // Paint the contents of the transparency layer. Note that we look at the + // Opal state beneath the current one for the alpha value because + // we want the alpha value before CGContextSaveGState was called + // in CGContextBeginTransparencyLayer + cairo_paint_with_alpha(ctx->ct, ctx->add->next->alpha); + + // Now undo the change to alpha and shadow state + CGContextRestoreGState(ctx); + + // Undo the clipping (if any) + cairo_restore(ctx->ct); +} diff --git a/CGContext.h b/CGContext.h new file mode 100644 index 0000000..909e0c5 --- /dev/null +++ b/CGContext.h @@ -0,0 +1,428 @@ +/** CGContext + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGContext_h +#define OPAL_CGContext_h + +/* Data Types */ + +typedef struct CGContext * CGContextRef; + +#include +#include +#include +#include +#include +#include +#include + +/* Constants */ + +typedef enum CGBlendMode { + kCGBlendModeNormal = 0, + kCGBlendModeMultiply = 1, + kCGBlendModeScreen = 2, + kCGBlendModeOverlay = 3, + kCGBlendModeDarken = 4, + kCGBlendModeLighten = 5, + kCGBlendModeColorDodge = 6, + kCGBlendModeColorBurn = 7, + kCGBlendModeSoftLight = 8, + kCGBlendModeHardLight = 9, + kCGBlendModeDifference = 10, + kCGBlendModeExclusion = 11, + kCGBlendModeHue = 12, + kCGBlendModeSaturation = 13, + kCGBlendModeColor = 14, + kCGBlendModeLuminosity = 15 +} CGBlendMode; + +typedef enum CGInterpolationQuality { + kCGInterpolationDefault = 0, + kCGInterpolationNone = 1, + kCGInterpolationLow = 2, + kCGInterpolationHigh = 3 +} CGInterpolationQuality; + +typedef enum CGLineCap { + kCGLineCapButt = 0, + kCGLineCapRound = 1, + kCGLineCapSquare = 2 +} CGLineCap; + +typedef enum CGLineJoin { + kCGLineJoinMiter = 0, + kCGLineJoinRound = 1, + kCGLineJoinBevel = 2 +} CGLineJoin; + +typedef enum CGTextDrawingMode { + kCGTextFill = 0, + kCGTextStroke = 1, + kCGTextFillStroke = 2, + kCGTextInvisible = 3, + kCGTextFillClip = 4, + kCGTextStrokeClip = 5, + kCGTextFillStrokeClip = 6, + kCGTextClip = 7 +} CGTextDrawingMode; + +typedef enum CGTextEncoding { + kCGEncodingFontSpecific = 0, + kCGEncodingMacRoman = 1 +} CGTextEncoding; + +/* Functions */ + +/* Managing Graphics Contexts */ + +CGContextRef CGContextRetain(CGContextRef ctx); + +void CGContextRelease(CGContextRef ctx); + +void CGContextFlush(CGContextRef ctx); + +void CGContextSynchronize(CGContextRef ctx); + +/* Defining Pages */ + +void CGContextBeginPage(CGContextRef ctx, const CGRect *mediaBox); + +void CGContextEndPage(CGContextRef ctx); + +/* Transforming the Coordinate Space of the Page */ + +void CGContextScaleCTM(CGContextRef ctx, float sx, float sy); + +void CGContextTranslateCTM(CGContextRef ctx, float tx, float ty); + +void CGContextRotateCTM(CGContextRef ctx, float angle); + +void CGContextConcatCTM(CGContextRef ctx, CGAffineTransform transform); + +CGAffineTransform CGContextGetCTM(CGContextRef ctx); + +/* Saving and Restoring the Graphics State */ + +void CGContextSaveGState(CGContextRef ctx); + +void CGContextRestoreGState(CGContextRef ctx); + +/* Setting Graphics State Attributes */ + +void CGContextSetShouldAntialias(CGContextRef ctx, int shouldAntialias); + +void CGContextSetLineWidth(CGContextRef ctx, float width); + +void CGContextSetLineJoin(CGContextRef ctx, CGLineJoin join); + +void CGContextSetMiterLimit(CGContextRef ctx, float limit); + +void CGContextSetLineCap(CGContextRef ctx, CGLineCap cap); + +void CGContextSetLineDash( + CGContextRef ctx, + float phase, + const float lengths[], + size_t count +); + +void CGContextSetFlatness(CGContextRef ctx, float flatness); + +CGInterpolationQuality CGContextGetInterpolationQuality(CGContextRef ctx); + +void CGContextSetInterpolationQuality( + CGContextRef ctx, + CGInterpolationQuality quality +); + +void CGContextSetPatternPhase (CGContextRef ctx, CGSize phase); + +void CGContextSetFillPattern( + CGContextRef ctx, + CGPatternRef pattern, + const float components[] +); + +void CGContextSetStrokePattern( + CGContextRef ctx, + CGPatternRef pattern, + const float components[] +); + +void CGContextSetShouldSmoothFonts(CGContextRef ctx, int shouldSmoothFonts); + +void CGContextSetBlendMode(CGContextRef ctx, CGBlendMode mode); + +void CGContextSetAllowsAntialiasing(CGContextRef ctx, int allowsAntialiasing); + +void CGContextSetShadow( + CGContextRef ctx, + CGSize offset, + CGFloat radius +); + +void CGContextSetShadowWithColor( + CGContextRef ctx, + CGSize offset, + CGFloat radius, + CGColorRef color +); + +/* Constructing Paths */ + +void CGContextBeginPath(CGContextRef ctx); + +void CGContextClosePath(CGContextRef ctx); + +void CGContextMoveToPoint(CGContextRef ctx, float x, float y); + +void CGContextAddLineToPoint(CGContextRef ctx, float x, float y); + +void CGContextAddLines(CGContextRef ctx, const CGPoint points[], size_t count); + +void CGContextAddCurveToPoint( + CGContextRef ctx, + float cp1x, + float cp1y, + float cp2x, + float cp2y, + float x, + float y +); + +void CGContextAddQuadCurveToPoint( + CGContextRef ctx, + float cpx, + float cpy, + float x, + float y +); + +void CGContextAddRect(CGContextRef ctx, CGRect rect); + +void CGContextAddRects(CGContextRef ctx, const CGRect rects[], size_t count); + +void CGContextAddArc( + CGContextRef ctx, + float x, + float y, + float radius, + float startAngle, + float endAngle, + int clockwise +); + +void CGContextAddArcToPoint( + CGContextRef ctx, + float x1, + float y1, + float x2, + float y2, + float radius +); + +void CGContextAddPath(CGContextRef ctx, CGPathRef path); + +void CGContextAddEllipseInRect(CGContextRef ctx, CGRect rect); + +/* Painting Paths */ + +void CGContextStrokePath(CGContextRef ctx); + +void CGContextFillPath(CGContextRef ctx); + +void CGContextEOFillPath(CGContextRef ctx); + +void CGContextDrawPath(CGContextRef ctx, CGPathDrawingMode mode); + +void CGContextStrokeRect(CGContextRef ctx, CGRect rect); + +void CGContextStrokeRectWithWidth(CGContextRef ctx, CGRect rect, float width); + +void CGContextFillRect(CGContextRef ctx, CGRect rect); + +void CGContextFillRects(CGContextRef ctx, const CGRect rects[], size_t count); + +void CGContextClearRect(CGContextRef c, CGRect rect); + +void CGContextFillEllipseInRect(CGContextRef ctx, CGRect rect); + +void CGContextStrokeEllipseInRect(CGContextRef ctx, CGRect rect); + +void CGContextStrokeLineSegments( + CGContextRef ctx, + const CGPoint points[], + size_t count +); + +/* Obtaining Path Information */ + +int CGContextIsPathEmpty(CGContextRef ctx); + +CGPoint CGContextGetPathCurrentPoint(CGContextRef ctx); + +CGRect CGContextGetPathBoundingBox(CGContextRef ctx); + +/* Clipping Paths */ + +void CGContextClip(CGContextRef ctx); + +void CGContextEOClip(CGContextRef ctx); + +void CGContextClipToRect(CGContextRef ctx, CGRect rect); + +void CGContextClipToRects(CGContextRef ctx, const CGRect rects[], size_t count); + +/* Setting the Color Space and Colors */ + +void CGContextSetFillColorWithColor(CGContextRef ctx, CGColorRef color); + +void CGContextSetStrokeColorWithColor(CGContextRef ctx, CGColorRef color); + +void CGContextSetAlpha(CGContextRef ctx, float alpha); + +void CGContextSetFillColorSpace(CGContextRef ctx, CGColorSpaceRef colorspace); + +void CGContextSetStrokeColorSpace(CGContextRef ctx, CGColorSpaceRef colorspace); + +void CGContextSetFillColor(CGContextRef ctx, const float components[]); + +void CGContextSetStrokeColor(CGContextRef ctx, const float components[]); + +void CGContextSetGrayFillColor(CGContextRef ctx, float gray, float alpha); + +void CGContextSetGrayStrokeColor(CGContextRef ctx, float gray, float alpha); + +void CGContextSetRGBFillColor( + CGContextRef ctx, + float r, + float g, + float b, + float alpha +); + +void CGContextSetRGBStrokeColor( + CGContextRef ctx, + float r, + float g, + float b, + float alpha +); + +void CGContextSetCMYKFillColor( + CGContextRef ctx, + float c, + float m, + float y, + float k, + float alpha +); + +void CGContextSetCMYKStrokeColor( + CGContextRef ctx, + float c, + float m, + float y, + float k, + float alpha +); + +void CGContextSetRenderingIntent(CGContextRef ctx, CGColorRenderingIntent intent); + +/* Drawing Images */ + +void CGContextDrawImage(CGContextRef ctx, CGRect rect, CGImageRef image); + +/* Drawing PDF Documents */ +#if 0 +void CGContextDrawPDFDocument( + CGContextRef ctx, + CGRect rect, + CGPDFDocumentRef document, + int page +); + +void CGContextDrawPDFPage(CGContextRef ctx, CGPDFPageRef page); +#endif + +/* Drawing Text */ + +void CGContextSetFont(CGContextRef ctx, CGFontRef font); + +void CGContextSetFontSize(CGContextRef ctx, float size); + +void CGContextSelectFont( + CGContextRef ctx, + const char *name, + float size, + CGTextEncoding textEncoding +); + +void CGContextSetCharacterSpacing(CGContextRef ctx, float spacing); + +void CGContextSetTextDrawingMode(CGContextRef ctx, CGTextDrawingMode mode); + +void CGContextSetTextPosition(CGContextRef ctx, float x, float y); + +CGPoint CGContextGetTextPosition(CGContextRef ctx); + +void CGContextSetTextMatrix(CGContextRef ctx, CGAffineTransform transform); + +CGAffineTransform CGContextGetTextMatrix(CGContextRef ctx); + +void CGContextShowText(CGContextRef ctx, const char *cstring, size_t length); + +void CGContextShowTextAtPoint( + CGContextRef ctx, + float x, + float y, + const char *cstring, + size_t length +); + +void CGContextShowGlyphs(CGContextRef ctx, const CGGlyph *g, size_t count); + +void CGContextShowGlyphsAtPoint( + CGContextRef ctx, + float x, + float y, + const CGGlyph *g, + size_t count +); + +/* Transparency Layers */ + +void CGContextBeginTransparencyLayer( + CGContextRef ctx, + CFDictionaryRef auxiliaryInfo +); + +void CGContextBeginTransparencyLayerWithRect( + CGContextRef ctx, + CGRect rect, + CFDictionaryRef auxiliaryInfo +); + +void CGContextEndTransparencyLayer(CGContextRef ctx); + +#endif /* OPAL_CGContext_h */ + diff --git a/CGDataConsumer.h b/CGDataConsumer.h new file mode 100644 index 0000000..033d7d9 --- /dev/null +++ b/CGDataConsumer.h @@ -0,0 +1,62 @@ +/** CGDataConsumer + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGDataConsumer_h +#define OPAL_CGDataConsumer_h + +#include + +/* Data Types */ + +typedef void * CGDataConsumerRef; + +/* Callbacks */ + +typedef size_t (*CGDataConsumerPutBytesCallback)( + void *info, + const void *buffer, + size_t count +); + +typedef void (*CGDataConsumerReleaseInfoCallback)(void *info); + +typedef struct CGDataConsumerCallbacks +{ + CGDataConsumerPutBytesCallback putBytes; + CGDataConsumerReleaseInfoCallback releaseConsumer; +} CGDataConsumerCallbacks; + +/* Functions */ + +CGDataConsumerRef CGDataConsumerCreate( + void *info, + const CGDataConsumerCallbacks *callbacks +); + +/* CGDataConsumerRef CGDataConsumerCreateWithCFData(CFMutableDataRef data); */ + +/* CGDataConsumerRef CGDataConsumerCreateWithURL(CFURLRef url); */ + +void CGDataConsumerRelease(CGDataConsumerRef consumer); + +CGDataConsumerRef CGDataConsumerRetain(CGDataConsumerRef consumer); + +#endif /* OPAL_CGDataConsumer_h */ diff --git a/CGDataProvider-private.h b/CGDataProvider-private.h new file mode 100644 index 0000000..2cda41d --- /dev/null +++ b/CGDataProvider-private.h @@ -0,0 +1,45 @@ +/** CGDataProvider + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGDataProvider.h" +#include "opal.h" + +typedef struct CGDataProvider +{ + struct objbase base; + CGDataProviderCallbacks cb; + void *info; +} CGDataProvider; + +static inline size_t opal_DataProviderRead(CGDataProviderRef dp, void *buffer, size_t count) +{ + return dp->cb.getBytes(dp->info, buffer, count); +} + +static inline void opal_DataProviderSkip(CGDataProviderRef dp, size_t count) +{ + return dp->cb.skipBytes(dp->info, count); +} + +static inline void opal_DataProviderRewind(CGDataProviderRef dp) +{ + return dp->cb.rewind(dp->info); +} diff --git a/CGDataProvider.c b/CGDataProvider.c new file mode 100644 index 0000000..ee56d89 --- /dev/null +++ b/CGDataProvider.c @@ -0,0 +1,177 @@ +/** CGDataProvider + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGDataProvider-private.h" +#include +#include + +typedef struct DirectInfo { + size_t offset; + CGDataProviderDirectAccessCallbacks cb; + void *info; + + size_t size; + const void *data; + void (*releaseData)(void *info, const void *data, size_t size); +} DirectInfo; + +static size_t opal_DirectGetBytes(void *info, void *buffer, size_t count) +{ + DirectInfo *i = info; + + if (i->data) { + if (i->offset + count > i->size) count = i->size - i->offset; + if (count) memcpy(buffer, i->data + i->offset, count); + } else { + count = i->cb.getBytes(i->info, buffer, i->offset, count); + } + i->offset += count; + return count; +} + +static void opal_DirectSkipBytes(void *info, size_t count) +{ + ((DirectInfo *)info)->offset += count; +} + +static void opal_DirectRewind(void *info) +{ + ((DirectInfo *)info)->offset = 0; +} + +static void opal_DirectReleaseInfo(void *info) +{ + DirectInfo *i = info; + + if (i->releaseData) i->releaseData(i->info, i->data, i->size); + if (i->cb.releaseProvider) i->cb.releaseProvider(i->info); + free(i); +} + +static CGDataProviderCallbacks opal_DirectCallbacks = { + opal_DirectGetBytes, + opal_DirectSkipBytes, + opal_DirectRewind, + opal_DirectReleaseInfo +}; + +static void opal_DirectReleaseData(void *info, const void *data, size_t size) +{ + DirectInfo *i = info; + + if (i->cb.releaseBytePointer) i->cb.releaseBytePointer(i->info, i->data); +} + +void opal_dealloc_CGDataProvider(void *d) +{ + CGDataProviderRef dp = d; + + if (dp->cb.releaseProvider) dp->cb.releaseProvider(dp->info); + free(dp); +} + +CGDataProviderRef CGDataProviderCreate( + void *info, const CGDataProviderCallbacks *callbacks) +{ + CGDataProviderRef dp; + + if (!(callbacks && callbacks->getBytes && + callbacks->skipBytes && callbacks->rewind)) + return NULL; + + dp = opal_obj_alloc("CGDataProvider", sizeof(CGDataProvider)); + if (!dp) return NULL; + + dp->cb = *callbacks; + dp->info = info; + + return dp; +} + +static inline CGDataProviderRef opal_CreateDirectAccess( + void *info, size_t size, const CGDataProviderDirectAccessCallbacks *callbacks) +{ + CGDataProviderRef dp; + DirectInfo *i; + + i = calloc(1, sizeof(DirectInfo)); + if (!i) { + errlog("%s:%d: calloc failed\n", __FILE__, __LINE__); + return NULL; + } + + dp = CGDataProviderCreate(i, &opal_DirectCallbacks); + if (!dp) { + free(i); + return NULL; + } + + if (callbacks) i->cb = *callbacks; + i->info = info; + i->size = size; + if (i->cb.getBytePointer) { + i->data = i->cb.getBytePointer(info); + if (i->data) i->releaseData = opal_DirectReleaseData; + } + + return dp; +} + +CGDataProviderRef CGDataProviderCreateDirectAccess( + void *info, size_t size, const CGDataProviderDirectAccessCallbacks *callbacks) +{ + if (!size) return NULL; + if (!(callbacks && (callbacks->getBytes || callbacks->getBytePointer))) + return NULL; + + return opal_CreateDirectAccess(info, size, callbacks); +} + +CGDataProviderRef CGDataProviderCreateWithData( + void *info, + const void *data, + size_t size, + void (*releaseData)(void *info, const void *data, size_t size)) +{ + CGDataProviderRef dp; + DirectInfo *i; + + if (!size || !data) return NULL; + + dp = opal_CreateDirectAccess(info, size, NULL); + if (!dp) return NULL; + + i = dp->info; + i->data = data; + i->releaseData = releaseData; + + return dp; +} + +CGDataProviderRef CGDataProviderRetain(CGDataProviderRef provider) +{ + return (provider ? opal_obj_retain(provider) : NULL); +} + +void CGDataProviderRelease(CGDataProviderRef provider) +{ + if(provider) opal_obj_release(provider); +} diff --git a/CGDataProvider.h b/CGDataProvider.h new file mode 100644 index 0000000..08b83bb --- /dev/null +++ b/CGDataProvider.h @@ -0,0 +1,109 @@ +/** CGDataProvider + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGDataProvider_h +#define OPAL_CGDataProvider_h + +#include + +/* Data Types */ + +typedef struct CGDataProvider * CGDataProviderRef; + +/* Callbacks */ + +typedef void *(*CGDataProviderGetBytePointerCallback)(void *info); + +typedef size_t (*CGDataProviderGetBytesAtOffsetCallback)( + void *info, + void *buffer, + size_t offset, + size_t count +); + +typedef size_t (*CGDataProviderGetBytesCallback)( + void *info, + void *buffer, + size_t count +); + +typedef void (*CGDataProviderSkipBytesCallback)(void *info, size_t count); + +typedef void (*CGDataProviderReleaseBytePointerCallback)( + void *info, + const void *pointer +); + +typedef void (*CGDataProviderReleaseDataCallback)( + void *info, + const void *data, + size_t size +); + +typedef void (*CGDataProviderReleaseInfoCallback)(void *info); + +typedef void (*CGDataProviderRewindCallback)(void *info); + +typedef struct CGDataProviderCallbacks +{ + CGDataProviderGetBytesCallback getBytes; + CGDataProviderSkipBytesCallback skipBytes; + CGDataProviderRewindCallback rewind; + CGDataProviderReleaseInfoCallback releaseProvider; +} CGDataProviderCallbacks; + +typedef struct CGDataProviderDirectAccessCallbacks +{ + CGDataProviderGetBytePointerCallback getBytePointer; + CGDataProviderReleaseBytePointerCallback releaseBytePointer; + CGDataProviderGetBytesAtOffsetCallback getBytes; + CGDataProviderReleaseInfoCallback releaseProvider; +} CGDataProviderDirectAccessCallbacks; + +/* Functions */ + +CGDataProviderRef CGDataProviderCreate( + void *info, + const CGDataProviderCallbacks *callbacks +); + +CGDataProviderRef CGDataProviderCreateDirectAccess( + void *info, + size_t size, + const CGDataProviderDirectAccessCallbacks *callbacks +); + +CGDataProviderRef CGDataProviderCreateWithData( + void *info, + const void *data, + size_t size, + void (*releaseData)(void *info, const void *data, size_t size) +); + +/* CGDataProviderRef CGDataProviderCreateWithCFData(CFDataRef data); */ + +/* CGDataProviderRef CGDataProviderCreateWithURL(CFURLRef url); */ + +CGDataProviderRef CGDataProviderRetain(CGDataProviderRef provider); + +void CGDataProviderRelease(CGDataProviderRef provider); + +#endif /* OPAL_CGDataProvider_h */ diff --git a/CGFont.c b/CGFont.c new file mode 100644 index 0000000..378db5f --- /dev/null +++ b/CGFont.c @@ -0,0 +1,212 @@ +/** CGFont + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGFont.h" +#include +#include +#include "cairo-ft.h" +#include FT_LIST_H +#include "opal.h" + +/* We just return a (cairo_font_face_t *) as a (CGFontRef) */ + +static FcPattern *opal_FcPatternCreateFromName(const char *name); + +/* We keep an LRU cache of patterns looked up by name to avoid calling + * fontconfig too frequently (like when refreshing a window repeatedly) */ +/* But we cache patterns and let cairo handle FT_Face objects because of + * memory management problems (lack of reference counting on FT_Face) */ +/* We can't use Freetype's Cache Manager to implement our cache because its API + * seems to be in a flux (for other than Face, CMap, Image and SBit at least) */ + +/* Number of entries to keep in the cache */ +#define CACHE_SIZE 10 + +static FT_ListRec pattern_cache; + +typedef struct cache_entry { + FT_ListNodeRec node; + unsigned int hash; + FcPattern *pat; +} cache_entry; + +typedef struct iter_state { + unsigned int hash; + FcPattern *pat; + int cnt; +} iter_state; + +static FT_Error cache_iterator(FT_ListNode node, void *user) +{ + cache_entry *entry = (cache_entry *)node; + iter_state *state = user; + + state->cnt++; + if (!node) return 1; + if (entry->hash == state->hash) { + state->pat = entry->pat; + FT_List_Up(&pattern_cache, node); + return 2; + } + return 0; +} + +static unsigned int hash_string(const char *str) +{ + unsigned int hash; + + for (hash = 0; *str != '\0'; str++) + hash = 31 * hash + *str; + + return hash; +} + +static FcPattern *opal_FcPatternCacheLookup(const char *name) +{ + iter_state state; + + state.cnt = 0; + state.pat = NULL; + state.hash = hash_string(name); + FT_List_Iterate(&pattern_cache, cache_iterator, &state); + + if (state.pat) + return state.pat; + + state.pat = opal_FcPatternCreateFromName(name); + if (!state.pat) return NULL; + + if (state.cnt >= CACHE_SIZE) { /* Remove last entry from the cache */ + FT_ListNode node; + + node = pattern_cache.tail; + FT_List_Remove(&pattern_cache, node); + FcPatternDestroy(((cache_entry *)node)->pat); + free(node); + } + /* Add new entry to the cache */ + { + cache_entry *entry; + + entry = calloc(1, sizeof(*entry)); + if (!entry) { + errlog("%s:%d: calloc failed\n", __FILE__, __LINE__); + return state.pat; + } + entry->hash = state.hash; + entry->pat = state.pat; + FT_List_Insert(&pattern_cache, (FT_ListNode)entry); + } + return state.pat; +} + +/* End of cache related things */ + +CGFontRef opal_FontCreateWithName(const char *name) +{ + FcPattern *pat; + + pat = opal_FcPatternCacheLookup(name); + if(pat) + return (CGFontRef)cairo_ft_font_face_create_for_pattern(pat); + else + return NULL; +} + +CGFontRef CGFontCreateWithPlatformFont(void *platformFontReference) +{ + cairo_font_face_t *cfont; + cairo_status_t cret; + + /* FIXME: The FT_Face should not be freed until cairo is done with it */ + cfont = cairo_ft_font_face_create_for_ft_face(platformFontReference, + FT_LOAD_DEFAULT); + cret = cairo_font_face_status(cfont); + if (cret) { + errlog("%s:%d: cairo_ft_font_face_create status: %s\n", + __FILE__, __LINE__, cairo_status_to_string(cret)); + cairo_font_face_destroy(cfont); + return NULL; + } + + return (CGFontRef)cfont; +} + +CGFontRef CGFontRetain(CGFontRef font) +{ + return (CGFontRef)cairo_font_face_reference((cairo_font_face_t *)font); +} + +void CGFontRelease(CGFontRef font) +{ + cairo_font_face_destroy((cairo_font_face_t *)font); +} + +static FcPattern *opal_FcPatternCreateFromName(const char *name) +{ + char *family, *traits; + FcPattern *pat; + FcResult fcres; + FcBool success; + + if (!name) return NULL; + family = strdup(name); + pat = FcPatternCreate(); + if (!family || !pat) goto error; + + /* Try to parse a Postscript font name and make a corresponding pattern */ + /* Consider everything up to the first dash to be the family name */ + traits = strchr(family, '-'); + if (traits) { + *traits = '\0'; + traits++; + } + success = FcPatternAddString(pat, FC_FAMILY, (FcChar8 *)family); + if (!success) goto error; + if (traits) { + /* FIXME: The following is incomplete and may also be wrong */ + /* Fontconfig assumes Medium Roman Regular so don't care about theese */ + if (strstr(traits, "Bold")) + success |= FcPatternAddInteger(pat, FC_WEIGHT, FC_WEIGHT_BOLD); + if (strstr(traits, "Italic")) + success |= FcPatternAddInteger(pat, FC_SLANT, FC_SLANT_ITALIC); + if (strstr(traits, "Oblique")) + success |= FcPatternAddInteger(pat, FC_SLANT, FC_SLANT_OBLIQUE); + if (strstr(traits, "Condensed")) + success |= FcPatternAddInteger(pat, FC_WIDTH, FC_WIDTH_CONDENSED); + if (!success) goto error; + } + + success = FcConfigSubstitute(NULL, pat, FcMatchPattern); + if (!success) goto error; + FcDefaultSubstitute(pat); + pat = FcFontMatch(NULL, pat, &fcres); + if (!pat) goto error; + free(family); + return pat; + +error: + errlog("%s:%d: opal_FcPatternCreateFromName failed\n", __FILE__, __LINE__); + if (family) free (family); + if (pat) FcPatternDestroy(pat); + return NULL; +} + diff --git a/CGFont.h b/CGFont.h new file mode 100644 index 0000000..f56655f --- /dev/null +++ b/CGFont.h @@ -0,0 +1,49 @@ +/** CGFont + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGFont_h +#define OPAL_CGFont_h + +/* Data Types */ + +typedef struct CGFont * CGFontRef; + +typedef unsigned short CGGlyph; + +typedef unsigned short CGFontIndex; + +/* Constants */ + +enum { + kCGFontIndexMax = ((1 << 16) - 2), + kCGFontIndexInvalid = ((1 << 16) - 1), + kCGGlyphMax = kCGFontIndexMax +}; + +/* Functions */ + +CGFontRef CGFontCreateWithPlatformFont(void *platformFontReference); + +CGFontRef CGFontRetain(CGFontRef font); + +void CGFontRelease(CGFontRef font); + +#endif /* OPAL_CGFont_h */ diff --git a/CGFunction.h b/CGFunction.h new file mode 100644 index 0000000..1e10761 --- /dev/null +++ b/CGFunction.h @@ -0,0 +1,60 @@ +/** CGFunction + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGFunction_h +#define OPAL_CGFunction_h + +/* Data Types */ + +typedef struct CGFunction *CGFunctionRef; + +/* Callbacks */ + +typedef void (*CGFunctionEvaluateCallback)( + void *info, + const float *inData, + float *outData +); + +typedef void (*CGFunctionReleaseInfoCallback)(void *info); + +typedef struct CGFunctionCallbacks { + unsigned int version; + CGFunctionEvaluateCallback evaluate; + CGFunctionReleaseInfoCallback releaseInfo +} CGFunctionCallbacks; + +/* Functions */ + +CGFunctionRef CGFunctionCreate( + void *info, + size_t domainDimension, + const float *domain, + size_t rangeDimension, + const float *range, + const CGFunctionCallbacks *callbacks +); + +CGFunctionRef CGFunctionRetain(CGFunctionRef function); + +void CGFunctionRelease(CGFunctionRef function); + +#endif /* OPAL_CGFunction_h */ diff --git a/CGGeometry.c b/CGGeometry.c new file mode 100644 index 0000000..c4d11fb --- /dev/null +++ b/CGGeometry.c @@ -0,0 +1,208 @@ +/** CGGeometry + + C Interface to graphics drawing library + - geometry routines + + Copyright (C) 1995,2002 Free Software Foundation, Inc. + Author: Adam Fedor + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Define IN_CGGEOMETRY_C so that the header can provide non-inline + * versions of the function implementations for us. + */ +#define IN_CGGEOMETRY_C +#include +#undef IN_CGGEOMETRY_C +#define _ISOC99_SOURCE +#include + +/* Constants */ +const CGPoint CGPointZero = {0,0}; + +const CGSize CGSizeZero = {0,0}; + +const CGRect CGRectZero = {{0,0},{0,0}}; + +const CGRect CGRectNull = {{NAN,NAN},{NAN,NAN}}; + +const CGRect CGRectInfinite = {{INFINITY,INFINITY},{INFINITY,INFINITY}}; + +/* Functions */ + +int CGRectIsNull(CGRect rect) +{ + return (isnan(rect.origin.x) || isnan(rect.origin.y) || + isnan(rect.size.width) || isnan(rect.size.height)) ? 1 : 0; +} + +int CGRectIsInfinite(CGRect rect) +{ + return (isinf(rect.origin.x) || isinf(rect.origin.y) || + isinf(rect.size.width) || isinf(rect.size.height)) ? 1 : 0; +} + +CGRect CGRectIntegral(CGRect rect) +{ + rect = CGRectStandardize(rect); + /* The order of the following is relevant: we change values we already used */ + rect.size.width = ceil(rect.origin.x + rect.size.width); + rect.size.height = ceil(rect.origin.y + rect.size.height); + rect.origin.x = floor(rect.origin.x); + rect.origin.y = floor(rect.origin.y); + rect.size.width -= rect.origin.x; + rect.size.height -= rect.origin.y; + return rect; +} + +CGRect CGRectIntersection(CGRect r1, CGRect r2) +{ + CGRect rect; + + /* If both of them are empty we can return r2 as an empty rect, + so this covers all cases: */ + if (CGRectIsEmpty(r1)) + return r2; + else if (CGRectIsEmpty(r2)) + return r1; + + r1 = CGRectStandardize(r1); + r2 = CGRectStandardize(r2); + + if (r1.origin.x + r1.size.width <= r2.origin.x || + r2.origin.x + r2.size.width <= r1.origin.x || + r1.origin.y + r1.size.height <= r2.origin.y || + r2.origin.y + r2.size.height <= r1.origin.y) + return CGRectNull; + + rect.origin.x = (r1.origin.x > r2.origin.x ? r1.origin.x : r2.origin.x); + rect.origin.y = (r1.origin.y > r2.origin.y ? r1.origin.y : r2.origin.y); + + if (r1.origin.x + r1.size.width < r2.origin.x + r2.size.width) + rect.size.width = r1.origin.x + r1.size.width - rect.origin.x; + else + rect.size.width = r2.origin.x + r2.size.width - rect.origin.x; + + if (r1.origin.y + r1.size.height < r2.origin.y + r2.size.height) + rect.size.width = r1.origin.y + r1.size.height - rect.origin.y; + else + rect.size.width = r2.origin.y + r2.size.height - rect.origin.y; + + return rect; +} + +void CGRectDivide(CGRect rect, CGRect *slice, CGRect *remainder, + float amount, CGRectEdge edge) +{ + static CGRect srect; + static CGRect rrect; + + if (!slice) + slice = &srect; + if (!remainder) + remainder = &rrect; + if (amount < 0) + amount = 0; + + rect = CGRectStandardize(rect); + *slice = rect; + *remainder = rect; + switch (edge) { + case CGRectMinXEdge: + remainder->origin.x += amount; + if (amount < rect.size.width) { + slice->size.width = amount; + remainder->size.width -= amount; + } else { + remainder->size.width = 0; + } + break; + case CGRectMinYEdge: + remainder->origin.y += amount; + if (amount < rect.size.height) { + slice->size.height = amount; + remainder->size.height -= amount; + } else { + remainder->size.height = 0; + } + break; + case CGRectMaxXEdge: + if (amount < rect.size.width) { + slice->origin.x += rect.size.width - amount; + slice->size.width = amount; + remainder->size.width -= amount; + } else { + remainder->size.width = 0; + } + break; + case CGRectMaxYEdge: + if (amount < rect.size.height) { + slice->origin.y += rect.size.height - amount; + slice->size.height = amount; + remainder->size.height -= amount; + } else { + remainder->size.height = 0; + } + break; + default: + break; + } +} + +#ifndef MAX +#define MAX(a,b) \ + ({typeof(a) _MAX_a = (a); typeof(b) _MAX_b = (b); \ + _MAX_a > _MAX_b ? _MAX_a : _MAX_b; }) +#define GS_DEFINED_MAX +#endif + +#ifndef MIN +#define MIN(a,b) \ + ({typeof(a) _MIN_a = (a); typeof(b) _MIN_b = (b); \ + _MIN_a < _MIN_b ? _MIN_a : _MIN_b; }) +#define GS_DEFINED_MIN +#endif + +CGRect CGRectUnion(CGRect r1, CGRect r2) +{ + CGRect rect; + + /* If both of them are empty we can return r2 as an empty rect, + so this covers all cases: */ + if (CGRectIsEmpty(r1)) + return r2; + else if (CGRectIsEmpty(r2)) + return r1; + + r1 = CGRectStandardize(r1); + r2 = CGRectStandardize(r2); + rect.origin.x = MIN(r1.origin.x, r2.origin.x); + rect.origin.y = MIN(r1.origin.y, r2.origin.y); + rect.size.width = MAX(r1.origin.x + r1.size.width, r2.origin.x + r2.size.width); + rect.size.height = MAX(r1.origin.y + r1.size.height, r2.origin.y + r2.size.height); + return rect; +} + +#ifdef GS_DEFINED_MAX +#undef GS_DEFINED_MAX +#undef MAX +#endif + +#ifdef GS_DEFINED_MIN +#undef GS_DEFINED_MIN +#undef MIN +#endif diff --git a/CGGeometry.h b/CGGeometry.h new file mode 100644 index 0000000..1241384 --- /dev/null +++ b/CGGeometry.h @@ -0,0 +1,350 @@ +/** CGGeometry + + C Interface to graphics drawing library + - geometry routines + + Copyright (C) 1995,2002 Free Software Foundation, Inc. + Author: Adam Fedor + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGGeometry_h +#define OPAL_CGGeometry_h + +/* Data Types */ + +typedef struct CGPoint +{ + float x; + float y; +} CGPoint; + +typedef struct CGSize +{ + float width; + float height; +} CGSize; + +typedef struct CGRect +{ + CGPoint origin; + CGSize size; +} CGRect; + +/* Constants */ + +typedef enum CGRectEdge +{ + CGRectMinXEdge = 0, + CGRectMinYEdge = 1, + CGRectMaxXEdge = 2, + CGRectMaxYEdge = 3 +} CGRectEdge; + +/** Point at 0,0 */ +extern const CGPoint CGPointZero; + +/** Zero size */ +extern const CGSize CGSizeZero; + +/** Zero-size rectangle at 0,0 */ +extern const CGRect CGRectZero; + +/** An invalid rectangle */ +extern const CGRect CGRectNull; + +/** A rectangle with infinite extent */ +extern const CGRect CGRectInfinite; + +/* Functions */ + +/* All but the most complex functions are declared static inline in this + * header file so that they are maximally efficient. In order to provide + * true functions (for code modules that don't have this header) this + * header is included in CGGeometry.c where the functions are no longer + * declared inline. + */ +#ifdef IN_CGGEOMETRY_C +#define GS_GEOM_SCOPE extern +#define GS_GEOM_ATTR +#else +#define GS_GEOM_SCOPE static inline +#define GS_GEOM_ATTR __attribute__((unused)) +#endif + +/* Creating and modifying Geometric Forms */ + +/** Returns a CGPoint having x-coordinate x and y-coordinate y. */ +GS_GEOM_SCOPE CGPoint CGPointMake(float x, float y) GS_GEOM_ATTR; + +/** Returns a CGSize having width width and height height. */ +GS_GEOM_SCOPE CGSize CGSizeMake(float width, float height) GS_GEOM_ATTR; + +/** Returns a CGRect having point of origin (x, y) and size (width, height). */ +GS_GEOM_SCOPE CGRect CGRectMake(float x, float y, float width, float height) GS_GEOM_ATTR; + +/** Returns an equivalent rect which has positive width and heght. */ +GS_GEOM_SCOPE CGRect CGRectStandardize(CGRect rect) GS_GEOM_ATTR; + +/** Returns the rectangle obtained by translating rect + * horizontally by dx and vertically by dy. */ +GS_GEOM_SCOPE CGRect CGRectOffset(CGRect rect, float dx, float dy) GS_GEOM_ATTR; + +/** Returns the rectangle obtained by moving each of rect's + * horizontal sides inward by dy and each of rect's vertical + * sides inward by dx with the center point preserved. A larger + * rectangle can be created by using negative values. */ +GS_GEOM_SCOPE CGRect CGRectInset(CGRect rect, float dx, float dy) GS_GEOM_ATTR; + +/** Returns a rectangle obtained by expanding rect minimally + * so that all four of its defining components are integers. */ +CGRect CGRectIntegral(CGRect rect); + +/** Returns the smallest rectangle which contains both r1 and r2 + * (modulo a set of measure zero). If either of r1 or r2 + * is an empty rectangle, then the other rectangle is returned. + * If both are empty, then the empty rectangle is returned. */ +CGRect CGRectUnion(CGRect r1, CGRect r2); + +/** Returns the largest rectangle which lies in both r1 and r2. + * If r1 and r2 have empty intersection (or, rather, intersection + * of measure zero, since this includes having their intersection + * be only a point or a line), then the empty rectangle is returned. */ +CGRect CGRectIntersection(CGRect r1, CGRect r2); + +/** Divides rect into two rectangles (namely slice and remainder) by + * "cutting" rect---parallel to, and a distance amount from the given edge + * of rect. You may pass 0 in as either of slice or remainder to avoid + * obtaining either of the created rectangles. */ +void CGRectDivide(CGRect rect, CGRect *slice, CGRect *remainder, + float amount, CGRectEdge edge); + +/* Accessing Geometric Attributes */ + +/** Returns the least x-coordinate value still inside rect. */ +GS_GEOM_SCOPE float CGRectGetMinX(CGRect rect) GS_GEOM_ATTR; + +/** Returns the x-coordinate of rect's middle point. */ +GS_GEOM_SCOPE float CGRectGetMidX(CGRect rect) GS_GEOM_ATTR; + +/** Returns the greatest x-coordinate value still inside rect. */ +GS_GEOM_SCOPE float CGRectGetMaxX(CGRect rect) GS_GEOM_ATTR; + +/** Returns the least y-coordinate value still inside rect. */ +GS_GEOM_SCOPE float CGRectGetMinY(CGRect rect) GS_GEOM_ATTR; + +/** Returns the y-coordinate of rect's middle point. */ +GS_GEOM_SCOPE float CGRectGetMidY(CGRect rect) GS_GEOM_ATTR; + +/** Returns the greatest y-coordinate value still inside rect. */ +GS_GEOM_SCOPE float CGRectGetMaxY(CGRect rect) GS_GEOM_ATTR; + +/** Returns rect's width. */ +GS_GEOM_SCOPE float CGRectGetWidth(CGRect rect) GS_GEOM_ATTR; + +/** Returns rect's height. */ +GS_GEOM_SCOPE float CGRectGetHeight(CGRect rect) GS_GEOM_ATTR; + +/** Returns 1 iff the rect is invalid. */ +int CGRectIsNull(CGRect rect); + +/** Returns 1 iff the area of rect is zero (i.e., iff either + * of rect's width or height is zero or is an invalid rectangle). */ +GS_GEOM_SCOPE int CGRectIsEmpty(CGRect rect) GS_GEOM_ATTR; + +/** Returns 1 iff the rect is infinite. */ +int CGRectIsInfinite(CGRect rect); + +/** Returns 1 iff rect1 and rect2 are intersecting. */ +GS_GEOM_SCOPE int CGRectIntersectsRect(CGRect rect1, CGRect rect2) GS_GEOM_ATTR; + +/** Returns 1 iff rect1 contains rect2. */ +GS_GEOM_SCOPE int CGRectContainsRect(CGRect rect1, CGRect rect2) GS_GEOM_ATTR; + +/** Returns 1 iff point is inside rect. */ +GS_GEOM_SCOPE int CGRectContainsPoint(CGRect rect, CGPoint point) GS_GEOM_ATTR; + +/** Returns 1 iff rect1's and rect2's origin and size are the same. */ +GS_GEOM_SCOPE int CGRectEqualToRect(CGRect rect1, CGRect rect2) GS_GEOM_ATTR; + +/** Returns 1 iff size1's and size2's width and height are the same. */ +GS_GEOM_SCOPE int CGSizeEqualToSize(CGSize size1, CGSize size2) GS_GEOM_ATTR; + +/** Returns 1 iff point1's and point2's x- and y-coordinates are the same. */ +GS_GEOM_SCOPE int CGPointEqualToPoint(CGPoint point1, CGPoint point2) GS_GEOM_ATTR; + +/* Inlined functions */ + +GS_GEOM_SCOPE float CGRectGetMinX(CGRect rect) +{ + if (rect.size.width < 0) + return rect.origin.x + rect.size.width; + else + return rect.origin.x; +} + +GS_GEOM_SCOPE float CGRectGetMidX(CGRect rect) +{ + return rect.origin.x + (rect.size.width / 2.0); +} + +GS_GEOM_SCOPE float CGRectGetMaxX(CGRect rect) +{ + if (rect.size.width < 0) + return rect.origin.x; + else + return rect.origin.x + rect.size.width; +} + +GS_GEOM_SCOPE float CGRectGetMinY(CGRect rect) +{ + if (rect.size.height < 0) + return rect.origin.y + rect.size.height; + else + return rect.origin.y; +} + +GS_GEOM_SCOPE float CGRectGetMidY(CGRect rect) +{ + return rect.origin.y + (rect.size.height / 2.0); +} + +GS_GEOM_SCOPE float CGRectGetMaxY(CGRect rect) +{ + if (rect.size.height < 0) + return rect.origin.y; + else + return rect.origin.y + rect.size.height; +} + +GS_GEOM_SCOPE float CGRectGetWidth(CGRect rect) +{ + return rect.size.width; +} + +GS_GEOM_SCOPE float CGRectGetHeight(CGRect rect) +{ + return rect.size.height; +} + +GS_GEOM_SCOPE int CGRectIsEmpty(CGRect rect) +{ + if (CGRectIsNull(rect)) + return 1; + return ((rect.size.width == 0) || (rect.size.height == 0)) ? 1 : 0; +} + +GS_GEOM_SCOPE int CGRectIntersectsRect(CGRect rect1, CGRect rect2) +{ + return (CGRectIsNull(CGRectIntersection(rect1, rect2)) ? 0 : 1); +} + +GS_GEOM_SCOPE int CGRectContainsRect(CGRect rect1, CGRect rect2) +{ + return CGRectEqualToRect(rect1, CGRectUnion(rect1, rect2)); +} + +GS_GEOM_SCOPE int CGRectContainsPoint(CGRect rect, CGPoint point) +{ + rect = CGRectStandardize(rect); + return ((point.x >= rect.origin.x) && + (point.y >= rect.origin.y) && + (point.x <= rect.origin.x + rect.size.width) && + (point.y <= rect.origin.y + rect.size.height)) ? 1 : 0; +} + +GS_GEOM_SCOPE int CGRectEqualToRect(CGRect rect1, CGRect rect2) +{ + /* FIXME: It is not clear from the docs if {{0,0},{1,1}} and {{1,1},{-1,-1}} + are equal or not. (The text seem to imply that they aren't.) */ + return ((rect1.origin.x == rect2.origin.x) && + (rect1.origin.y == rect2.origin.y) && + (rect1.size.width == rect2.size.width) && + (rect1.size.height == rect2.size.height)) ? 1 : 0; +} + +GS_GEOM_SCOPE int CGSizeEqualToSize(CGSize size1, CGSize size2) +{ + return ((size1.width == size2.width) && + (size1.height == size2.height)) ? 1 : 0; +} + +GS_GEOM_SCOPE int CGPointEqualToPoint(CGPoint point1, CGPoint point2) +{ + return ((point1.x == point2.x) && (point1.y == point2.y)) ? 1 : 0; +} + +GS_GEOM_SCOPE CGPoint CGPointMake(float x, float y) +{ + CGPoint point; + + point.x = x; + point.y = y; + return point; +} + +GS_GEOM_SCOPE CGSize CGSizeMake(float width, float height) +{ + CGSize size; + + size.width = width; + size.height = height; + return size; +} + +GS_GEOM_SCOPE CGRect CGRectMake(float x, float y, float width, float height) +{ + CGRect rect; + + rect.origin.x = x; + rect.origin.y = y; + rect.size.width = width; + rect.size.height = height; + return rect; +} + +GS_GEOM_SCOPE CGRect CGRectStandardize(CGRect rect) +{ + if (rect.size.width < 0) { + rect.origin.x += rect.size.width; + rect.size.width = -rect.size.width; + } + if (rect.size.height < 0) { + rect.origin.y += rect.size.height; + rect.size.height = -rect.size.height; + } + return rect; +} + +GS_GEOM_SCOPE CGRect CGRectOffset(CGRect rect, float dx, float dy) +{ + rect.origin.x += dx; + rect.origin.y += dy; + return rect; +} + +GS_GEOM_SCOPE CGRect CGRectInset(CGRect rect, float dx, float dy) +{ + rect = CGRectStandardize(rect); + rect.origin.x += dx; + rect.origin.y += dy; + rect.size.width -= (2 * dx); + rect.size.height -= (2 * dy); + return rect; +} + +#endif /* OPAL_CGGeometry_h */ diff --git a/CGImage.c b/CGImage.c new file mode 100644 index 0000000..3115024 --- /dev/null +++ b/CGImage.c @@ -0,0 +1,279 @@ +/** CGImage + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGImage.h" +#include "CGDataProvider-private.h" +#include +#include +#include "opal.h" + +typedef struct CGImage +{ + struct objbase base; + int ismask; + + size_t width; + size_t height; + size_t bitsPerComponent; + size_t bitsPerPixel; + size_t bytesPerRow; + CGDataProviderRef dp; + float *decode; + int shouldInterpolate; + /* alphaInfo is always AlphaNone for mask */ + CGImageAlphaInfo alphaInfo; + /* cspace and intent are only set for image */ + CGColorSpaceRef cspace; + CGColorRenderingIntent intent; +} CGImage; + +void opal_dealloc_CGImage(void *i) +{ + CGImageRef img = i; + + CGColorSpaceRelease(img->cspace); + CGDataProviderRelease(img->dp); + if (img->decode) free(img->decode); + free(i); +} + +static inline CGImageRef opal_CreateImage( + size_t width, size_t height, + size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow, + CGDataProviderRef provider, const float *decode, int shouldInterpolate, + size_t numComponents, int hasAlpha) +{ + CGImageRef img; + + if (bitsPerComponent != 8 && bitsPerComponent != 4 && + bitsPerComponent != 2 && bitsPerComponent != 1) { + errlog("%s:%d: Invalid bitsPerComponent (allowed: 1,2,4,8)\n", + __FILE__, __LINE__); + return NULL; + } + if (bitsPerPixel != 32 && bitsPerPixel != 16 && + bitsPerPixel != 8) { + errlog("%s:%d: Unsupported bitsPerPixel (allowed: 8, 16, 32)\n", + __FILE__, __LINE__); + return NULL; + } + if (bitsPerPixel < bitsPerComponent * (numComponents + (hasAlpha ? 1 : 0))) { + errlog("%s:%d: Too few bitsPerPixel for bitsPerComponent\n", + __FILE__, __LINE__); + return NULL; + } + + img = opal_obj_alloc("CGImage", sizeof(CGImage)); + if (!img) return NULL; + if(decode && numComponents) { + size_t i; + + img->decode = malloc(2*numComponents*sizeof(float)); + if (!img->decode) { + errlog("%s:%d: malloc failed\n", __FILE__, __LINE__); + free(img); + return NULL; + } + for(i=0; i<2*numComponents; i++) img->decode[i] = decode[i]; + } + + img->width = width; + img->height = height; + img->bitsPerComponent = bitsPerComponent; + img->bitsPerPixel = bitsPerPixel; + img->bytesPerRow = bytesPerRow; + img->dp = CGDataProviderRetain(provider); + img->shouldInterpolate = shouldInterpolate; + + return img; +} + +CGImageRef CGImageCreate( + size_t width, + size_t height, + size_t bitsPerComponent, + size_t bitsPerPixel, + size_t bytesPerRow, + CGColorSpaceRef colorspace, + CGImageAlphaInfo alphaInfo, + CGDataProviderRef provider, + const float *decode, + int shouldInterpolate, + CGColorRenderingIntent intent) +{ + CGImageRef img; + size_t numComponents; + int hasAlpha; + + if (alphaInfo == kCGImageAlphaOnly) + numComponents = 0; + else + numComponents = CGColorSpaceGetNumberOfComponents(colorspace); + hasAlpha = (alphaInfo == kCGImageAlphaPremultipliedLast) || + (alphaInfo == kCGImageAlphaPremultipliedFirst) || + (alphaInfo == kCGImageAlphaLast) || + (alphaInfo == kCGImageAlphaFirst) || + (alphaInfo == kCGImageAlphaOnly); + + if (!provider || !colorspace) return NULL; + img = opal_CreateImage(width, height, + bitsPerComponent, bitsPerPixel, bytesPerRow, + provider, decode, shouldInterpolate, + numComponents, hasAlpha); + if (!img) return NULL; + + img->alphaInfo = alphaInfo; + img->cspace = CGColorSpaceRetain(colorspace); + img->intent = intent; + + return img; +} + +CGImageRef CGImageMaskCreate( + size_t width, size_t height, + size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow, + CGDataProviderRef provider, const float *decode, int shouldInterpolate) +{ + CGImageRef img; + + if (!provider) return NULL; + img = opal_CreateImage(width, height, + bitsPerComponent, bitsPerPixel, bytesPerRow, + provider, decode, shouldInterpolate, 0, 1); + if (!img) return NULL; + + img->ismask = 1; + + return img; +} + +CGImageRef CGImageRetain(CGImageRef image) +{ + return (image ? opal_obj_retain(image) : NULL); +} + +void CGImageRelease(CGImageRef image) +{ + if(image) opal_obj_release(image); +} + +int CGImageIsMask(CGImageRef image) +{ + return image->ismask; +} + +size_t CGImageGetWidth(CGImageRef image) +{ + return image->width; +} + +size_t CGImageGetHeight(CGImageRef image) +{ + return image->height; +} + +size_t CGImageGetBitsPerComponent(CGImageRef image) +{ + return image->bitsPerComponent; +} + +size_t CGImageGetBitsPerPixel(CGImageRef image) +{ + return image->bitsPerPixel; +} + +size_t CGImageGetBytesPerRow(CGImageRef image) +{ + return image->bytesPerRow; +} + +CGColorSpaceRef CGImageGetColorSpace(CGImageRef image) +{ + return image->cspace; +} + +CGImageAlphaInfo CGImageGetAlphaInfo(CGImageRef image) +{ + return image->alphaInfo; +} + +CGDataProviderRef CGImageGetDataProvider(CGImageRef image) +{ + return image->dp; +} + +const float *CGImageGetDecode(CGImageRef image) +{ + return image->decode; +} + +int CGImageGetShouldInterpolate(CGImageRef image) +{ + return image->shouldInterpolate; +} + +CGColorRenderingIntent CGImageGetRenderingIntent(CGImageRef image) +{ + return image->intent; +} + +cairo_surface_t *opal_CGImageCreateSurfaceForImage(CGImageRef img) +{ + cairo_surface_t *surf; + cairo_format_t cformat; + unsigned char *data; + size_t datalen; + size_t numComponents = 0; + int alphaLast = 0; + int mask; + + /* The target is always 8 BPC 32 BPP for Cairo so should convert to this */ + /* (see also QA1037) */ + if (img->cspace) + numComponents = CGColorSpaceGetNumberOfComponents(img->cspace); + + switch (img->alphaInfo) { + case kCGImageAlphaNone: + case kCGImageAlphaNoneSkipLast: + alphaLast = 1; + case kCGImageAlphaNoneSkipFirst: + break; + case kCGImageAlphaLast: + alphaLast = 1; + case kCGImageAlphaFirst: + numComponents++; + break; + case kCGImageAlphaPremultipliedLast: + case kCGImageAlphaPremultipliedFirst: + errlog("%s:%d: FIXME: premultiplied alpha is not supported\n", + __FILE__, __LINE__); + return NULL; + break; + case kCGImageAlphaOnly: + numComponents = 1; + } + + /* FIXME: implement this */ + /* datalen = */ + + mask = (1 << img->bitsPerComponent) - 1; + +} diff --git a/CGImage.h b/CGImage.h new file mode 100644 index 0000000..76bd873 --- /dev/null +++ b/CGImage.h @@ -0,0 +1,100 @@ +/** CGImage + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGImage_h +#define OPAL_CGImage_h + +#include + +/* Data Types */ + +typedef struct CGImage * CGImageRef; + +/* Constants */ + +typedef enum CGImageAlphaInfo +{ + kCGImageAlphaNone = 0, + kCGImageAlphaPremultipliedLast = 1, + kCGImageAlphaPremultipliedFirst = 2, + kCGImageAlphaLast = 3, + kCGImageAlphaFirst = 4, + kCGImageAlphaNoneSkipLast = 5, + kCGImageAlphaNoneSkipFirst = 6, + kCGImageAlphaOnly = 7 +} CGImageAlphaInfo; + +/* Drawing Images */ + +CGImageRef CGImageCreate( + size_t width, + size_t height, + size_t bitsPerComponent, + size_t bitsPerPixel, + size_t bytesPerRow, + CGColorSpaceRef colorspace, + CGImageAlphaInfo alphaInfo, + CGDataProviderRef provider, + const float *decode, + int shouldInterpolate, + CGColorRenderingIntent intent +); + +CGImageRef CGImageMaskCreate( + size_t width, + size_t height, + size_t bitsPerComponent, + size_t bitsPerPixel, + size_t bytesPerRow, + CGDataProviderRef provider, + const float *decode, + int shouldInterpolate +); + +CGImageRef CGImageRetain(CGImageRef image); + +void CGImageRelease(CGImageRef image); + +int CGImageIsMask(CGImageRef image); + +size_t CGImageGetWidth(CGImageRef image); + +size_t CGImageGetHeight(CGImageRef image); + +size_t CGImageGetBitsPerComponent(CGImageRef image); + +size_t CGImageGetBitsPerPixel(CGImageRef image); + +size_t CGImageGetBytesPerRow(CGImageRef image); + +CGColorSpaceRef CGImageGetColorSpace(CGImageRef image); + +CGImageAlphaInfo CGImageGetAlphaInfo(CGImageRef image); + +CGDataProviderRef CGImageGetDataProvider(CGImageRef image); + +const float *CGImageGetDecode(CGImageRef image); + +int CGImageGetShouldInterpolate(CGImageRef image); + +CGColorRenderingIntent CGImageGetRenderingIntent(CGImageRef image); + +#endif /* OPAL_CGImage_h */ diff --git a/CGLayer.c b/CGLayer.c new file mode 100644 index 0000000..9fdead7 --- /dev/null +++ b/CGLayer.c @@ -0,0 +1,153 @@ +/** CGLayer + + C Interface to graphics drawing library + + Copyright (C) 2009 Eric Wasylishen + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "CGContext-private.h" +#include "opal.h" + +typedef struct CGLayer +{ + struct objbase base; + CGContextRef ctxt; + CGSize size; +} CGLayer; + +void opal_dealloc_CGLayer(void *l) +{ + CGLayerRef layer = l; + CGContextRelease(layer->ctxt); + free(layer); +} + +CGLayerRef CGLayerCreateWithContext( + CGContextRef referenceCtxt, + CGSize size, + CFDictionaryRef auxInfo) +{ + CGLayerRef layer = opal_obj_alloc("CGLayer", sizeof(CGLayer)); + if (!layer) return NULL; + + // size is in user-space units of referenceCtxt, so transform it to device + // space. + double w = size.width, h = size.height; + cairo_user_to_device_distance(referenceCtxt->ct, &w, &h); + + cairo_surface_t *layerSurface = + cairo_surface_create_similar(cairo_get_target(referenceCtxt->ct), + CAIRO_CONTENT_COLOR_ALPHA, + ceil(fabs(w)), + ceil(fabs(h))); + cairo_surface_set_device_offset(layerSurface, 0, ceil(fabs(h))); + layer->ctxt = opal_new_CGContext(layerSurface); + CGContextScaleCTM(layer->ctxt, 1.0, -1.0); + layer->size = size; + + return layer; +} + +CGLayerRef CGLayerRetain(CGLayerRef layer) +{ + return (layer ? opal_obj_retain(layer) : NULL); +} + +void CGLayerRelease(CGLayerRef layer) +{ + if (layer) opal_obj_release(layer); +} + +CGSize CGLayerGetSize(CGLayerRef layer) +{ + return layer->size; +} + +CGContextRef CGLayerGetContext(CGLayerRef layer) +{ + return layer->ctxt; +} + +void CGContextDrawLayerInRect( + CGContextRef destCtxt, + CGRect rect, + CGLayerRef layer) +{ + cairo_t *destCairo = destCtxt->ct; + cairo_save(destCairo); + + cairo_pattern_t *pattern = + cairo_pattern_create_for_surface(cairo_get_target(layer->ctxt->ct)); + + // Horrible code.. but sort-of works. Fix this up ASAP. + + cairo_matrix_t patternMatrix; + cairo_matrix_init_identity(&patternMatrix); + + cairo_matrix_translate(&patternMatrix, 0, layer->size.height); + + cairo_matrix_translate(&patternMatrix, rect.origin.x, rect.origin.y); + cairo_matrix_scale(&patternMatrix, 1, -1); + cairo_matrix_scale(&patternMatrix, + rect.size.width / layer->size.width, + rect.size.height / layer->size.height); + cairo_matrix_translate(&patternMatrix, 0, -layer->size.height); + + + + cairo_matrix_invert(&patternMatrix); + + + cairo_pattern_set_matrix(pattern, &patternMatrix); + + // cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); + + cairo_set_source(destCairo, pattern); + + //cairo_set_source_surface(destCairo, cairo_get_target(layer->ctxt->ct), 20, 20); + + cairo_pattern_destroy(pattern); + + cairo_set_operator(destCairo, CAIRO_OPERATOR_OVER); + //cairo_rectangle(destCairo, rect.origin.x, rect.origin.y, + // rect.size.width, rect.size.height); + //cairo_fill(destCairo); + + cairo_paint(destCairo); + + cairo_restore(destCairo); +} + +void CGContextDrawLayerAtPoint( + CGContextRef destCtxt, + CGPoint point, + CGLayerRef layer) +{ + CGContextDrawLayerInRect(destCtxt, + CGRectMake(point.x, point.y, layer->size.width, layer->size.height), + layer); +} + +#if 0 +CFTypeID CGLayerGetTypeID() +{ + +} +#endif diff --git a/CGLayer.h b/CGLayer.h new file mode 100644 index 0000000..9704e30 --- /dev/null +++ b/CGLayer.h @@ -0,0 +1,60 @@ +/** CGLayer + + C Interface to graphics drawing library + + Copyright (C) 2009 Eric Wasylishen + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGLayer_h +#define OPAL_CGLayer_h + +#include +#include + +typedef struct CGLayer *CGLayerRef; + +CGLayerRef CGLayerCreateWithContext( + CGContextRef referenceCtxt, + CGSize size, + CFDictionaryRef auxInfo +); + +CGLayerRef CGLayerRetain(CGLayerRef layer); + +void CGLayerRelease(CGLayerRef layer); + +CGSize CGLayerGetSize(CGLayerRef layer); + +CGContextRef CGLayerGetContext(CGLayerRef layer); + +void CGContextDrawLayerInRect( + CGContextRef destCtxt, + CGRect rect, + CGLayerRef layer +); + +void CGContextDrawLayerAtPoint( + CGContextRef destCtxt, + CGPoint point, + CGLayerRef layer +); + +#if 0 +CFTypeID CGLayerGetTypeID(); +#endif + +#endif \ No newline at end of file diff --git a/CGPDFContext.h b/CGPDFContext.h new file mode 100644 index 0000000..5988c5a --- /dev/null +++ b/CGPDFContext.h @@ -0,0 +1,35 @@ +/** CGPDFContext + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGPDFContext_h +#define OPAL_CGPDFContext_h + +#include + +/* Functions */ + +CGContextRef CGPDFContextCreate( + CGDataConsumerRef consumer, + const CGRect *mediaBox, + /* CFDictionaryRef */ void *auxiliaryInfo /* ignored */ +); + +#endif /* OPAL_CGPDFContext_h */ diff --git a/CGPDFDocument.h b/CGPDFDocument.h new file mode 100644 index 0000000..77b12b2 --- /dev/null +++ b/CGPDFDocument.h @@ -0,0 +1,70 @@ +/** CGPDFDocument + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGPDFDocument_h +#define OPAL_CGPDFDocument_h + +#include +#include + +/* Data Types */ + +typedef void * CGPDFDocumentRef; + +/* Functions */ + +CGPDFDocumentRef CGPDFDocumentCreateWithProvider(CGDataProviderRef provider); + +#if 0 +CGPDFDocumentRef CGPDFDocumentCreateWithURL(CFURLRef url); + +CGContextRef CGPDFContextCreate( + CGDataConsumerRef consumer, + const CGRect *mediaBox, + CFDictionaryRef auxiliaryInfo +); + +CGContextRef CGPDFContextCreateWithURL( + CFURLRef url, + const CGRect *mediaBox, + CFDictionaryRef auxiliaryInfo +); +#endif + +CGPDFDocumentRef CGPDFDocumentRetain(CGPDFDocumentRef document); + +void CGPDFDocumentRelease(CGPDFDocumentRef document); + +int CGPDFDocumentGetNumberOfPages(CGPDFDocumentRef document); + +CGRect CGPDFDocumentGetMediaBox(CGPDFDocumentRef document, int page); + +CGRect CGPDFDocumentGetCropBox(CGPDFDocumentRef document, int page); + +CGRect CGPDFDocumentGetBleedBox(CGPDFDocumentRef document, int page); + +CGRect CGPDFDocumentGetTrimBox(CGPDFDocumentRef document, int page); + +CGRect CGPDFDocumentGetArtBox(CGPDFDocumentRef document, int page); + +int CGPDFDocumentGetRotationAngle(CGPDFDocumentRef document, int page); + +#endif /* OPAL_CGPDFDocument_h */ diff --git a/CGPath.h b/CGPath.h new file mode 100644 index 0000000..43ce0c8 --- /dev/null +++ b/CGPath.h @@ -0,0 +1,183 @@ +/** CGPath + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGPath_h +#define OPAL_CGPath_h + +/* Constants */ + +typedef enum CGPathElementType { + kCGPathElementMoveToPoint = 0, + kCGPathElementAddLineToPoint = 1, + kCGPathElementAddQuadCurveToPoint = 2, + kCGPathElementAddCurveToPoint = 3, + kCGPathElementCloseSubpath = 4 +} CGPathElementType; + +typedef enum CGPathDrawingMode +{ + kCGPathFill = 0, + kCGPathEOFill = 1, + kCGPathStroke = 2, + kCGPathFillStroke = 3, + kCGPathEOFillStroke = 4 +} CGPathDrawingMode; + +/* Data Types */ + +typedef const struct CGPath * CGPathRef; + +typedef struct CGPath * CGMutablePathRef; + +typedef struct CGPathElement { + CGPathElementType type; + CGPoint *points; +} CGPathElement; + +/* Callbacks */ + +typedef void (*CGPathApplierFunction)(void *info, const CGPathElement *element); + +/* Functions */ + +CGPathRef CGPathCreateCopy(CGPathRef path); + +CGMutablePathRef CGPathCreateMutable(void); + +CGMutablePathRef CGPathCreateMutableCopy(CGPathRef path); + +CGPathRef CGPathRetain(CGPathRef path); + +void CGPathRelease(CGPathRef path); + +int CGPathIsEmpty(CGPathRef path); + +int CGPathEqualToPath(CGPathRef path1, CGPathRef path2); + +int CGPathIsRect(CGPathRef path, CGRect *rect); + +CGRect CGPathGetBoundingBox(CGPathRef path); + +CGPoint CGPathGetCurrentPoint(CGPathRef path); + +int CGPathContainsPoint( + CGPathRef path, + const CGAffineTransform *m, + CGPoint point, + int eoFill +); + +void CGPathAddArc( + CGMutablePathRef path, + const CGAffineTransform *m, + float x, + float y, + float r, + float startAngle, + float endAngle, + int clockwise +); + +void CGPathAddArcToPoint( + CGMutablePathRef path, + const CGAffineTransform *m, + float x1, + float y1, + float x2, + float y2, + float r +); + +void CGPathAddCurveToPoint( + CGMutablePathRef path, + const CGAffineTransform *m, + float cx1, + float cy1, + float cx2, + float cy2, + float x, + float y +); + +void CGPathAddLines( + CGMutablePathRef path, + const CGAffineTransform *m, + const CGPoint points[], + size_t count +); + +void CGPathAddLineToPoint ( + CGMutablePathRef path, + const CGAffineTransform *m, + float x, + float y +); + +void CGPathAddPath( + CGMutablePathRef path1, + const CGAffineTransform *m, + CGPathRef path2 +); + +void CGPathAddQuadCurveToPoint( + CGMutablePathRef path, + const CGAffineTransform *m, + float cx, + float cy, + float x, + float y +); + +void CGPathAddRect( + CGMutablePathRef path, + const CGAffineTransform *m, + CGRect rect +); + +void CGPathAddRects( + CGMutablePathRef path, + const CGAffineTransform *m, + const CGRect rects[], + size_t count +); + +void CGPathApply( + CGPathRef path, + void *info, + CGPathApplierFunction function +); + +void CGPathMoveToPoint( + CGMutablePathRef path, + const CGAffineTransform *m, + float x, + float y +); + +void CGPathCloseSubpath(CGMutablePathRef path); + +void CGPathAddEllipseInRect( + CGMutablePathRef path, + const CGAffineTransform *m, + CGRect rect +); + +#endif /* OPAL_CGPath_h */ diff --git a/CGPattern.h b/CGPattern.h new file mode 100644 index 0000000..8df92a0 --- /dev/null +++ b/CGPattern.h @@ -0,0 +1,67 @@ +/** CGPattern + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGPattern_h +#define OPAL_CGPattern_h + +/* Data Types */ + +typedef void * CGPatternRef; + +/* Constants */ + +typedef enum CGPatternTiling +{ + kCGPatternTilingNoDistortion = 0, + kCGPatternTilingConstantSpacingMinimalDistortion = 1, + kCGPatternTilingConstantSpacing = 2 +} CGPatternTiling; + +/* Callbacks */ + +typedef void(*CGPatternDrawPatternCallback)(void *info, CGContextRef ctx); + +typedef void(*CGPatternReleaseInfoCallback)(void *info); + +typedef struct CGPatternCallbacks { + unsigned int version; + CGPatternDrawPatternCallback drawPattern; + CGPatternReleaseInfoCallback releaseInfo; +} CGPatternCallbacks; + +/* Functions */ + +CGPatternRef CGPatternCreate( + void *info, + CGRect bounds, + CGAffineTransform matrix, + float xStep, + float yStep, + CGPatternTiling tiling, + int isColored, + const CGPatternCallbacks *callbacks +); + +void CGPatternRelease(CGPatternRef pattern); + +CGPatternRef CGPatternRetain(CGPatternRef pattern); + +#endif /* OPAL_CGPattern_h */ diff --git a/CGShading.h b/CGShading.h new file mode 100644 index 0000000..bf538fb --- /dev/null +++ b/CGShading.h @@ -0,0 +1,57 @@ +/** CGShading + + C Interface to graphics drawing library + + Copyright (C) 2006 BALATON Zoltan + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CGShading_h +#define OPAL_CGShading_h + +#include + +/* Data Types */ + +typedef struct CGShading * CGShadingRef; + +/* Functions */ + +CGShadingRef CGShadingCreateAxial ( + CGColorSpaceRef colorspace, + CGPoint start, + CGPoint end, + CGFunctionRef function, + int extendStart, + int extendEnd +); + +CGShadingRef CGShadingCreateRadial( + CGColorSpaceRef colorspace, + CGPoint start, + float startRadius, + CGPoint end, + float endRadius, + CGFunctionRef function, + int extendStart, + int extendEnd +); + +CGShadingRef CGShadingRetain(CGShadingRef shading); + +void CGShadingRelease(CGShadingRef shading); + +#endif /* OPAL_CGShading_h */ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c4792dd --- /dev/null +++ b/COPYING @@ -0,0 +1,515 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper +mail. + +You should also get your employer (if you work as a programmer) or +your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James +Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/CoreFoundation.h b/CoreFoundation.h new file mode 100644 index 0000000..0a45b2f --- /dev/null +++ b/CoreFoundation.h @@ -0,0 +1,33 @@ +/** CoreFoundation + + C Interface to graphics drawing library + + Copyright (C) 2009 Eric Wasylishen + + 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.1 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OPAL_CoreFoundation_h +#define OPAL_CoreFoundation_h + +# ifdef __OBJC__ +@class NSDictionary; +typedef NSDictionary* CFDictionaryRef; +# else +typedef struct cf_dictionary *CFDictionaryRef; +# endif + +#endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6d23222 --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +# Simple Makefile to build libopal.a and some examples +# This should be replaced with a proper build system + +CFLAGS=-Wall -g +CPPFLAGS=-I. -I/usr/local/include -I/usr/local/include/cairo + +# Get the Cairo sources and compile libcairo.a, then set CAIROSRC below. +# Once we start using private Cairo APIs static lib is needed because +# private API functions are not exported in the dynamic lib. + +# For release version of cairo +#CAIROSRC=$(PWD)/cairo-1.4.10/src +#CAIROLIBS=$(CAIROSRC)/.libs/libcairo.a + +# For development version of Cairo +#CAIROSRC=$(PWD)/git/cairo/src +#CAIROLIBS=$(CAIROSRC)/.libs/libcairo.a \ + $(CAIROSRC)/../../pixman/installed/lib/libpixman-1.a +CAIROSRC=/usr/local/include/cairo +CAIROLIBS=/usr/local/lib/libcairo.a /usr/local/lib/libpixman-1.a + +# Portable parts of libopal.a +OPAL_OBJS=CGAffineTransform.o CGColor.o CGColorSpace.o CGContext.o \ + CGDataProvider.o CGFont.o CGImage.o CGLayer.o opal.o +# System specific parts of libopal.a +OPAL-X11_OBJS=opal-x11.o + +EXAMPLES=test test1 test2 test3 test4 cgtest1 texttest arclock qeb2 shapes layers + +LOADLIBES=$(CAIROLIBS) $(shell pkg-config --libs freetype2) \ + -lfontconfig -lX11 -lXrender -lm + +libopal.a: libopal.a($(OPAL_OBJS)) libopal.a($(OPAL-X11_OBJS)) + +CGContext.o: CPPFLAGS+=-I$(CAIROSRC) +CGFont.o: CPPFLAGS+=-I$(CAIROSRC) $(shell pkg-config --cflags freetype2) +CGImage.o: CPPFLAGS+=-I$(CAIROSRC) +opal-x11.o: CPPFLAGS+=-I$(CAIROSRC) + +examples: $(EXAMPLES) + +test: libopal.a +test1: libopal.a +test2: libopal.a +test3: libopal.a +test4: libopal.a +cgtest1: libopal.a +texttest: libopal.a +arclock: libopal.a +qeb2: qeb2-draw.o libopal.a +shapes: arcs.o ovals.o rects.o libopal.a +layers: layers.o libopal.a + +clean: + rm -f *.o *~ +distclean: clean + rm -f libopal.a $(EXAMPLES) + +.PHONY: clean distclean diff --git a/README b/README new file mode 100644 index 0000000..fe07895 --- /dev/null +++ b/README @@ -0,0 +1,24 @@ +==== +Opal +==== + +What is Opal? +------------- + +Opal is a vector drawing library with an API similar to +Quartz 2D . +Opal is built on top of Cairo . + +Opal is also a gemstone consisting of amorphous hydrated +silicon dioxide (SiO2 · nH2O) which is sometimes included +in the quartz group of minerals. + +There is a homepage (which may not be updated too frequently) at + + +The sources are available from the Étoile project repository at + + +*** Warning! *** This version is not yet suitable for general use. +It may be interesting for developers only, contributions are much welcome! +For more information see the TODO file. diff --git a/TODO b/TODO new file mode 100644 index 0000000..93ed14d --- /dev/null +++ b/TODO @@ -0,0 +1,28 @@ +There's a lot to do, really. + +- Add proper build system +- Port to other platforms (Windows anyone?) +- Try different Cairo surfaces (ps, pdf, png, OpenGL, etc.) + +- Implement TextMatrix in CGContext (may need to use internal Cairo APIs) +- Implement missing glyph drawing functions and finish ShowText +- Implement Image drawing +- Implement Patterns and Shading +- Implement Path handling functions +- Implement color management (could use lcms?) + +- Fix device transform in Cairo and get rid of CTM patching hacks + + +Design principles to follow: +============================ +- Build on public Cairo APIs as much as possible, use private APIs only if + there is no appropriate public one or would simplifiy implementation a lot +- Avoid duplicate representatation of the same thing (should not store a copy + of what Cairo already stores to avoid getting out of sync or too many + conversions). Choose between Quartz or Cairo representation and convert to + that and then stick to it. +- Keep performance in mind. This is a low level part of the system that + should be fast, small and stable so follow K.I.S.S. +- Keep dependencies clean, only #include what you need and put functions + that depend on the same thing in one file. diff --git a/arcs.c b/arcs.c new file mode 100644 index 0000000..6ac6e93 --- /dev/null +++ b/arcs.c @@ -0,0 +1,155 @@ +/* + + File: arcs.c + + Abstract: // These are the functions that implement equivalents to the QuickDraw arc drawing APIs, + // FrameArc and PaintArc. + // See DrawProcs.c for sample usage + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Computer, Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Computer, + Inc. may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright © 2005 Apple Computer, Inc., All Rights Reserved + + */ + +#define _BSD_SOURCE +#include +#include +#include "CGContext.h" + +/* +pathForArc : Adds an arc (a segment of an oval) fitting inside a rectangle to the path. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the arc's boundary.. +startAngle : The angle indicating the start of the arc. +arcAngle : The angle indicating the arcŐs extent. +*/ + +void pathForArc(CGContextRef context, CGRect r, int startAngle, int arcAngle) +{ + float start, end; + CGAffineTransform matrix; + + // Save the context's state because we are going to scale it + CGContextSaveGState(context); + + // Create a transform to scale the context so that a radius of 1 maps to the bounds + // of the rectangle, and transform the origin of the context to the center of + // the bounding rectangle. + matrix = CGAffineTransformMake(r.size.width/2, 0, + 0, r.size.height/2, + r.origin.x + r.size.width/2, + r.origin.y + r.size.height/2); + + // Apply the transform to the context + CGContextConcatCTM(context, matrix); + + // Calculate the start and ending angles + if (arcAngle > 0) { + start = (90 - startAngle - arcAngle) * M_PI / 180; + end = (90 - startAngle) * M_PI / 180; + } else { + start = (90 - startAngle) * M_PI / 180; + end = (90 - startAngle - arcAngle) * M_PI / 180; + } + + // Add the Arc to the path + CGContextAddArc(context, 0, 0, 1, start, end, false); + + // Restore the context's state. This removes the translation and scaling + // but leaves the path, since the path is not part of the graphics state. + CGContextRestoreGState(context); +} + +/* +frameArc : Draws an arc of the oval that fits inside a rectangle. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the arc's boundary.. +startAngle : The angle indicating the start of the arc. +arcAngle : The angle indicating the arcŐs extent. +*/ + +void frameArc(CGContextRef context, CGRect r, int startAngle, int arcAngle) +{ + + // Signal the start of a path + CGContextBeginPath(context); + + // Add to the path the arc of the oval that fits inside the rectangle. + pathForArc(context,r,startAngle,arcAngle); + + // Stroke the path + CGContextStrokePath(context); +} + +/* +paintArc : Paints a wedge of the oval that fits inside a rectangle. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the arc's boundary.. +startAngle : The angle indicating the start of the arc. +arcAngle : The angle indicating the arcŐs extent. +*/ + +void paintArc(CGContextRef context, CGRect r, int startAngle, int arcAngle) +{ + float start, end; + + // Signal the start of a path + CGContextBeginPath(context); + + // Set the start of the path to the arcs focal point + CGContextMoveToPoint(context, r.origin.x + r.size.width/2, r.origin.y + r.size.height/2); + + // Add to the path the arc of the oval that fits inside the rectangle. + pathForArc(context,r,startAngle,arcAngle); + + // Complete the path closing the arc at the focal point + CGContextClosePath(context); + + // Fill the path + CGContextFillPath(context); +} diff --git a/layers.c b/layers.c new file mode 100644 index 0000000..29890cf --- /dev/null +++ b/layers.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include + +#define pi 3.14159265358979323846 + +Display *d; +Window win; +CGContextRef ctx; + +extern CGContextRef opal_XWindowContextCreate(Display *d, Window w); + +CGLayerRef makeSampleLayer(CGContextRef ctx){ + CGRect layerBounds = CGRectMake(0,0,50, 50); + CGLayerRef layer = CGLayerCreateWithContext(ctx, layerBounds.size, NULL); + CGContextRef layerCtx = CGLayerGetContext(layer); + + CGContextSetRGBFillColor(layerCtx, 1, 1, 0, 0.5); + CGContextFillRect(layerCtx, layerBounds); + + CGContextSetRGBStrokeColor(layerCtx, 0, 0, 0, 0.7); + CGContextStrokeRect(layerCtx, layerBounds); + + + // Draw a smiley + + CGContextAddArc(layerCtx, 10, 35, 4, 0, 2 * pi, 1); CGContextClosePath(layerCtx); + CGContextAddArc(layerCtx, 40, 35, 4, 0, 2 * pi, 1); CGContextClosePath(layerCtx); + + CGContextAddArc(layerCtx, 12, 15, 4, 0, 2 * pi, 1);CGContextClosePath(layerCtx); + CGContextAddArc(layerCtx, 19, 10, 4, 0, 2 * pi, 1);CGContextClosePath(layerCtx); + CGContextAddArc(layerCtx, 25, 8, 4, 0, 2 * pi, 1);CGContextClosePath(layerCtx); + CGContextAddArc(layerCtx, 31, 10, 4, 0, 2 * pi, 1);CGContextClosePath(layerCtx); + CGContextAddArc(layerCtx, 38, 15, 4, 0, 2 * pi, 1);CGContextClosePath(layerCtx); + + CGContextSetRGBFillColor(layerCtx, 0, 0, 0, 0.7); + CGContextFillPath(layerCtx); + + CGContextSetRGBStrokeColor(layerCtx, 0, 0, 0, 1); + CGContextStrokePath(layerCtx); + + + return layer; +} + +void draw(CGContextRef ctx, CGRect r) +{ + CGContextSetRGBFillColor(ctx, 0, 0, 1, 0.5); + CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 1); + CGContextFillRect(ctx, CGRectMake(10,10,r.size.width - 20, r.size.height - 20)); + CGContextStrokeRect(ctx, CGRectMake(10,10,r.size.width - 20, r.size.height - 20)); + + // Draw some copies of a layer + CGLayerRef layer = makeSampleLayer(ctx); + + // Draw some rotated faces + CGContextSaveGState(ctx); + CGContextTranslateCTM(ctx, 225, 125); + int i; + for (i = 0; i < 3; i++) { + CGContextRotateCTM(ctx, 0.06); + CGContextDrawLayerInRect(ctx, CGRectMake(-145,-110,290,220), layer); + } + CGContextRestoreGState(ctx); + + + + CGContextDrawLayerInRect(ctx, CGRectMake(80,15,290,220), layer); + + CGContextDrawLayerAtPoint(ctx, CGPointMake(100, 170), layer); + CGContextDrawLayerAtPoint(ctx, CGPointMake(300, 170), layer); + + CGContextDrawLayerAtPoint(ctx, CGPointMake(100, 60), layer); + CGContextDrawLayerAtPoint(ctx, CGPointMake(150, 16), layer); + CGContextDrawLayerAtPoint(ctx, CGPointMake(200, 10), layer); + CGContextDrawLayerAtPoint(ctx, CGPointMake(250, 16), layer); + CGContextDrawLayerAtPoint(ctx, CGPointMake(300, 60), layer); + CGLayerRelease(layer); +} + + +int main(int argc, char **argv) +{ + int ret; + CGRect cr; + XSetWindowAttributes wa; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) { + fprintf(stderr,"Cannot open display: %s\n", XDisplayName(NULL)); + exit(EXIT_FAILURE); + } + printf("Opened display %s\n", DisplayString(d)); + + cr = CGRectMake(0,0,500,250); + wa.background_pixel = WhitePixel(d, DefaultScreen(d)); + wa.event_mask = ExposureMask | ButtonReleaseMask; + + /* Create a window */ + win = XCreateWindow(d, /* Display */ + DefaultRootWindow(d), /* Parent */ + cr.origin.x, cr.origin.y, /* x, y */ + cr.size.width, cr.size.height, /* width, height */ + 0, /* border_width */ + CopyFromParent, /* depth */ + InputOutput, /* class */ + CopyFromParent, /* visual */ + CWBackPixel | CWEventMask, /* valuemask */ + &wa); /* attributes */ + printf("XCreateWindow returned: %lx\n", win); + + /* Map the window */ + ret = XMapRaised(d, win); + printf("XMapRaised returned: %x\n", ret); + + /* Create a CGContext */ + ctx = opal_XWindowContextCreate(d, win); + if (!ctx) { + fprintf(stderr,"Cannot create context\n"); + exit(EXIT_FAILURE); + } + printf("Created context\n"); + + while(1) + { + XNextEvent(d,&e); + switch(e.type) + { + case Expose: + /* Dispose multiple events */ + while (XCheckTypedEvent(d, Expose, &e)); + /* Draw window contents */ + if(e.xexpose.count == 0) { + CGContextSaveGState(ctx); + XClearWindow(d, win); + draw(ctx, cr); + CGContextRestoreGState(ctx); + } + break; + + case ButtonRelease: + /* Finish program */ + CGContextRelease(ctx); + XCloseDisplay(d); + exit(EXIT_SUCCESS); + break; + } + } + return(EXIT_SUCCESS); +} diff --git a/opal-x11.c b/opal-x11.c new file mode 100644 index 0000000..33b9b4a --- /dev/null +++ b/opal-x11.c @@ -0,0 +1,83 @@ +/** opal-x11 + + C Interface to graphics drawing library + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: BALATON Zoltan + Date: 2006 + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. + */ + +#include +#include +#include +#include "opal.h" + +/* Internal cairo API, declare it here to avoid dependencies of cairoint.h */ +extern void _cairo_surface_set_device_scale(cairo_surface_t *surface, + double sx, double sy); + +/* Keys we use to attach additional data to Xlib surfaces */ +static cairo_user_data_key_t XWindow; + +extern CGContextRef opal_new_CGContext(cairo_surface_t *target); + +CGContextRef opal_XWindowContextCreate(Display *d, Window w) +{ + CGContextRef ctx; + XWindowAttributes wa; + cairo_surface_t *target; + int ret; + + ret = XGetWindowAttributes(d, w, &wa); + if (!ret) { + errlog("%s:%d: XGetWindowAttributes returned %d\n", __FILE__, __LINE__, ret); + return NULL; + } + + target = cairo_xlib_surface_create(d, w, wa.visual, wa.width, wa.height); + + /* May not need this but left here for reference */ + ret = cairo_surface_set_user_data(target, &XWindow, (void *)w, NULL); + if (ret) { + errlog("%s:%d: cairo_surface_set_user_data %d\n", + __FILE__, __LINE__, cairo_status_to_string(CAIRO_STATUS_NO_MEMORY)); + cairo_surface_destroy(target); + return NULL; + } + + /* Flip coordinate system */ + cairo_surface_set_device_offset(target, 0, wa.height); + /* FIXME: The scale part of device transform does not work correctly in + * cairo so for now we have to patch the CTM! This should really be fixed + * in cairo and then the ScaleCTM call below and the hacks in GetCTM in + * CGContext should be removed in favour of the following line: */ + /* _cairo_surface_set_device_scale(target, 1.0, -1.0); */ + + ctx = opal_new_CGContext(target); + CGContextScaleCTM(ctx, 1.0, -1.0); + cairo_surface_destroy(target); + + return ctx; +} + +void opal_surface_flush(cairo_surface_t *target) +{ + XFlush(cairo_xlib_surface_get_display(target)); +} diff --git a/opal.c b/opal.c new file mode 100644 index 0000000..e0de94a --- /dev/null +++ b/opal.c @@ -0,0 +1,91 @@ +/** opal + + C Interface to graphics drawing library + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: BALATON Zoltan + Date: 2006 + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. + */ + +#include +#include +#include +#include +#include "opal.h" + +extern void opal_dealloc_CGContext(void *); +extern void opal_dealloc_CGLayer(void *); +extern void opal_dealloc_CGColor(void *); +extern void opal_dealloc_CGImage(void *); +extern void opal_dealloc_CGDataProvider(void *); + +static struct objbase objtypes[] = { + {"CGContext", opal_dealloc_CGContext}, + {"CGLayer", opal_dealloc_CGLayer}, + {"CGColor", opal_dealloc_CGColor}, + {"CGImage", opal_dealloc_CGImage}, + {"CGDataProvider", opal_dealloc_CGDataProvider}, + {NULL} +}; + +void errlog(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +void *opal_obj_alloc(const char *name, size_t size) +{ + int typeidx; + struct objbase *obj; + + for (typeidx=0; objtypes[typeidx].name; typeidx++) + if (strcmp(objtypes[typeidx].name, name) == 0) break; + if (!objtypes[typeidx].name) { + errlog("obj_alloc: Failed to create an unknown object: %s\n", name); + return NULL; + } + + obj = calloc(1, size); + if (!obj) { + errlog("obj_alloc: calloc failed for %s\n", name); + return NULL; + } + *obj = objtypes[typeidx]; + obj->rc = 1; + + return obj; +} + +void *opal_obj_retain(void *obj) +{ + ((struct objbase *)obj)->rc++; + return obj; +} + +void opal_obj_release(void *obj) +{ + struct objbase *o = obj; + + if (--o->rc == 0) o->dealloc(obj); +} diff --git a/opal.h b/opal.h new file mode 100644 index 0000000..cd2610d --- /dev/null +++ b/opal.h @@ -0,0 +1,46 @@ +/** opal + + C Interface to graphics drawing library + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: BALATON Zoltan + Date: 2006 + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. + */ + +/* This file is private for Opal and should not be included by clients! */ + +#ifndef OPAL_OPAL_H +#define OPAL_OPAL_H + +#include + +struct objbase +{ + char *name; + void (*dealloc)(void *); + unsigned long int rc; /* reference counter */ +}; + +extern void errlog(const char *fmt, ...); +extern void *opal_obj_alloc(const char *name, size_t size); +extern void *opal_obj_retain(void *obj); +extern void opal_obj_release(void *obj); + +#endif /* OPAL_OPAL_H */ diff --git a/ovals.c b/ovals.c new file mode 100644 index 0000000..bfbf55d --- /dev/null +++ b/ovals.c @@ -0,0 +1,131 @@ +/* + + File: ovals.c + + Abstract: // These are the functions that implement equivalents to the QuickDraw oval + // drawing APIs, FrameOval and PaintOval. + // See DrawProcs.c for sample usage + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Computer, Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Computer, + Inc. may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright © 2005 Apple Computer, Inc., All Rights Reserved + + */ + +#define _BSD_SOURCE +#include +#include +#include "CGContext.h" + + /* +addOvalToPath : Adds to the context a path for an oval just inside the bounding rectangle that you specify. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the ovalŐs boundary. +*/ + +void addOvalToPath(CGContextRef context, CGRect r) +{ + CGAffineTransform matrix; + + // Save the context's state because we are going to transform and scale it + CGContextSaveGState(context); + + // Create a transform to scale the context so that a radius of 1 + // is equal to the bounds of the rectangle, and transform the origin + // of the context to the center of the bounding rectangle. The + // center of the bounding rectangle will now be the center of + // the oval. + matrix = CGAffineTransformMake((r.size.width)/2, 0, + 0, (r.size.height)/2, + r.origin.x + (r.size.width)/2, + r.origin.y + (r.size.height)/2); + + // Apply the transform to the context + CGContextConcatCTM(context, matrix); + + // Signal the start of a path + CGContextBeginPath(context); + + // Add a circle to the path. After the circle is transformed by the + // context's transformation matrix, it will become an oval lying + // just inside the bounding rectangle. + CGContextAddArc(context, 0, 0, 1, 0, 2*M_PI, true); + + // Restore the context's state. This removes the translation and scaling but leaves + // the path, since the path is not part of the graphics state. + CGContextRestoreGState(context); +} + + +/* +paintOval : Paints the interior of an oval just inside the bounding rectangle that you specify. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the ovalŐs boundary. +*/ + +void paintOval(CGContextRef context, CGRect r) +{ + // Add a path for the oval to this context + addOvalToPath(context,r); + + // Fill the oval + CGContextFillPath(context); +} + +/* +frameOval : Draws an outline of an oval just inside the bounding rectangle that you specify. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the ovalŐs boundary. +*/ +void frameOval(CGContextRef context, CGRect r) +{ + // Add a path for the oval to this context + addOvalToPath(context,r); + + // Stroke the path + CGContextStrokePath(context); +} diff --git a/qeb2-draw.c b/qeb2-draw.c new file mode 100644 index 0000000..f398bd8 --- /dev/null +++ b/qeb2-draw.c @@ -0,0 +1,185 @@ +/* + File: myDraw.m + + Description: Quartz 2D early bird sample from WWDC 2001 + + Author: DH + + Copyright: © Copyright 2000 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleŐs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Change History (most recent first): + +*/ + + +/* + * myDraw.m + * + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + */ + +#include +#include + +#define kNumOfExamples 4 +#define PI 3.14159265358979323846 + +/* + * myDraw is called whenever the view is updated. + * context - CG context to draw into + * windowRect - rectangle defining the window rectangle + */ + +void drawRandomPaths(CGContextRef context, int w, int h) +{ + int i; + for (i = 0; i < 20; i++) { + int numberOfSegments = rand() % 8; + int j; + float sx, sy; + + CGContextBeginPath(context); + sx = rand()%w; sy = rand()%h; + CGContextMoveToPoint(context, rand()%w, rand()%h); + for (j = 0; j < numberOfSegments; j++) { + if (j % 2) { + CGContextAddLineToPoint(context, rand()%w, rand()%h); + } + else { + CGContextAddCurveToPoint(context, rand()%w, rand()%h, + rand()%w, rand()%h, rand()%h, rand()%h); + } + } + if(i % 2) { + CGContextAddCurveToPoint(context, rand()%w, rand()%h, + rand()%w, rand()%h, sx, sy); + CGContextClosePath(context); + CGContextSetRGBFillColor(context, (float)(rand()%256)/255, + (float)(rand()%256)/255, (float)(rand()%256)/255, + (float)(rand()%256)/255); + CGContextFillPath(context); + } + else { + CGContextSetLineWidth(context, (rand()%10)+2); + CGContextSetRGBStrokeColor(context, (float)(rand()%256)/255, + (float)(rand()%256)/255, (float)(rand()%256)/255, + (float)(rand()%256)/255); + CGContextStrokePath(context); + } + } +} + +void myDraw(CGContextRef context, CGRect* contextRect) +{ + int i; + int w, h; + static int n = 0; + + w = contextRect->size.width; + h = contextRect->size.height; + + switch (n) { + case 0: + // Draw random rectangles (some stroked some filled) + for (i = 0; i < 20; i++) { + if(i % 2) { + CGContextSetRGBFillColor(context, (float)(rand()%256)/255, + (float)(rand()%256)/255, (float)(rand()%256)/255, + (float)(rand()%256)/255); + CGContextFillRect(context, CGRectMake(rand()%w, rand()%h, rand()%w, rand()%h)); + } + else { + CGContextSetLineWidth(context, (rand()%10)+2); + CGContextSetRGBStrokeColor(context, (float)(rand()%256)/255, + (float)(rand()%256)/255, (float)(rand()%256)/255, + (float)(rand()%256)/255); + CGContextStrokeRect(context, CGRectMake(rand()%w, rand()%h, rand()%w, rand()%h)); + } + } + break; + case 1: + // Draw random circles (some stroked, some filled) + for (i = 0; i < 20; i++) { + CGContextBeginPath(context); + CGContextAddArc(context, rand()%w, rand()%h, rand()%((w>h) ? h : w), 0, 2*PI, 0); + CGContextClosePath(context); + + if(i % 2) { + CGContextSetRGBFillColor(context, (float)(rand()%256)/255, + (float)(rand()%256)/255, (float)(rand()%256)/255, + (float)(rand()%256)/255); + CGContextFillPath(context); + } + else { + CGContextSetLineWidth(context, (rand()%10)+2); + CGContextSetRGBStrokeColor(context, (float)(rand()%256)/255, + (float)(rand()%256)/255, (float)(rand()%256)/255, + (float)(rand()%256)/255); + CGContextStrokePath(context); + } + } + break; + case 2: + drawRandomPaths(context, w, h); + break; + case 3: + /* Clipping example - draw random path through a circular clip */ + CGContextBeginPath(context); + CGContextAddArc(context, w/2, h/2, ((w>h) ? h : w)/2, 0, 2*PI, 0); + CGContextClosePath(context); + CGContextClip(context); + + // Draw something into the clip + drawRandomPaths(context, w, h); + + // Draw an clip path on top as a black stroked circle. + CGContextBeginPath(context); + CGContextAddArc(context, w/2, h/2, ((w>h) ? h : w)/2, 0, 2*PI, 0); + CGContextClosePath(context); + CGContextSetLineWidth(context, 1); + CGContextSetRGBStrokeColor(context, 0, 0, 0, 1); + CGContextStrokePath(context); + break; + + default: + break; + } + + n = ((n+1) % kNumOfExamples); +} diff --git a/qeb2.c b/qeb2.c new file mode 100644 index 0000000..63ee62c --- /dev/null +++ b/qeb2.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +Display *d; +Window win; +CGContextRef ctx; + +extern CGContextRef opal_XWindowContextCreate(Display *d, Window w); +extern void myDraw(CGContextRef context, CGRect* contextRect); + +int main(int argc, char **argv) +{ + int ret; + CGRect cr; + XSetWindowAttributes wa; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) { + fprintf(stderr,"Cannot open display: %s\n", XDisplayName(NULL)); + exit(EXIT_FAILURE); + } + printf("Opened display %s\n", DisplayString(d)); + + cr = CGRectMake(0,0,545,391); + wa.background_pixel = WhitePixel(d, DefaultScreen(d)); + wa.event_mask = ExposureMask | ButtonReleaseMask; + + /* Create a window */ + win = XCreateWindow(d, /* Display */ + DefaultRootWindow(d), /* Parent */ + cr.origin.x, cr.origin.y, /* x, y */ + cr.size.width, cr.size.height, /* width, height */ + 0, /* border_width */ + CopyFromParent, /* depth */ + InputOutput, /* class */ + CopyFromParent, /* visual */ + CWBackPixel | CWEventMask, /* valuemask */ + &wa); /* attributes */ + printf("XCreateWindow returned: %lx\n", win); + + /* Map the window */ + ret = XMapRaised(d, win); + printf("XMapRaised returned: %x\n", ret); + + /* Create a CGContext */ + ctx = opal_XWindowContextCreate(d, win); + if (!ctx) { + fprintf(stderr,"Cannot create context\n"); + exit(EXIT_FAILURE); + } + printf("Created context\n"); + + while(1) + { + XNextEvent(d,&e); + switch(e.type) + { + case Expose: + /* Dispose multiple events */ + while (XCheckTypedEvent(d, Expose, &e)); + /* Draw window contents */ + if(e.xexpose.count == 0) { + CGContextSaveGState(ctx); + XClearWindow(d, win); + myDraw(ctx, &cr); + CGContextRestoreGState(ctx); + } + break; + + case ButtonRelease: + /* Finish program */ + CGContextRelease(ctx); + XCloseDisplay(d); + exit(EXIT_SUCCESS); + break; + } + } +} diff --git a/rects.c b/rects.c new file mode 100644 index 0000000..f8113d3 --- /dev/null +++ b/rects.c @@ -0,0 +1,171 @@ +/* + + File: rects.c + + Abstract: // These are the functions that implement equivalents to the QuickDraw rect, + // drawing APIs, FrameRect, PaintRect. + // See DrawProcs.c for sample usage + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Computer, Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Computer, + Inc. may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright © 2005 Apple Computer, Inc., All Rights Reserved + + */ + +#include "CGContext.h" + +/* +frameRect : Draws the outline of a rectangle. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the rectangle's boundary. +*/ +void frameRect(CGContextRef context, CGRect r) +{ + CGContextStrokeRect(context, r); +} + +/* +paintRect : Paints the interior of an rectangle. + +Parameter Descriptions +context : The CG context to render to. +r : The CG rectangle that defines the rectangle's boundary. +*/ +void paintRect(CGContextRef context, CGRect r) +{ + CGContextFillRect(context, r); +} + +/* +addRoundedRectToPath : Adds a rectangle with rounded courners to the current CG path + +Parameter Descriptions +rect : The CG rectangle that defines the rectangle's boundary. +ovalWidth : The width of the CG rectangle that encloses the rounded corners +ovalHeight : The height of the CG rectangle that encloses the rounded corners +context : The CG context to render to. +*/ + +static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, + float ovalHeight) +{ + float fw, fh; + // If the width or height of the corner oval is zero, then it reduces to a right angle, + // so instead of a rounded rectangle we have an ordinary one. + if (ovalWidth == 0 || ovalHeight == 0) { + CGContextAddRect(context, rect); + return; + } + + // Save the context's state so that the translate and scale can be undone with a call + // to CGContextRestoreGState. + CGContextSaveGState(context); + + // Translate the origin of the contex to the lower left corner of the rectangle. + CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect)); + + //Normalize the scale of the context so that the width and height of the arcs are 1.0 + CGContextScaleCTM(context, ovalWidth, ovalHeight); + + // Calculate the width and height of the rectangle in the new coordinate system. + fw = CGRectGetWidth(rect) / ovalWidth; + fh = CGRectGetHeight(rect) / ovalHeight; + + // CGContextAddArcToPoint adds an arc of a circle to the context's path (creating the rounded + // corners). It also adds a line from the path's last point to the begining of the arc, making + // the sides of the rectangle. + CGContextMoveToPoint(context, fw, fh/2); // Start at lower right corner + CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); // Top right corner + CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); // Top left corner + CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); // Lower left corner + CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // Back to lower right + + // Close the path + CGContextClosePath(context); + + // Restore the context's state. This removes the translation and scaling + // but leaves the path, since the path is not part of the graphics state. + CGContextRestoreGState(context); +} + +/* +fillRoundedRect : fills a rounded rectangle with the current fill color + +Parameter Descriptions +rect : The CG rectangle that defines the rectangle's boundary. +ovalWidth : The width of the CG rectangle that encloses the rounded corners +ovalHeight : The height of the CG rectangle that encloses the rounded corners +context : The CG context to render to. +*/ +void fillRoundedRect(CGContextRef context, CGRect rect, float ovalWidth, float + ovalHeight) +{ + // Signal the start of a path + CGContextBeginPath(context); + // Add a rounded rect to the path + addRoundedRectToPath(context, rect, ovalWidth, ovalHeight); + // Fill the path + CGContextFillPath(context); +} + + +/* +strokeRoundedRect : Draws a rounded rectangle with the current stroke color + +Parameter Descriptions +rect : The CG rectangle that defines the rectangle's boundary. +ovalWidth : The width of the CG rectangle that encloses the rounded corners +ovalHeight : The height of the CG rectangle that encloses the rounded corners +context : The CG context to render to. +*/ +void strokeRoundedRect(CGContextRef context, CGRect rect, float ovalWidth, + float ovalHeight) +{ + + // Signal the start of a path + CGContextBeginPath(context); + // Add a rounded rect to the path + addRoundedRectToPath(context, rect, ovalWidth, ovalHeight); + // Stroke the path + CGContextStrokePath(context); +} diff --git a/shapes.c b/shapes.c new file mode 100644 index 0000000..69924e7 --- /dev/null +++ b/shapes.c @@ -0,0 +1,312 @@ +#include +#include +#include +#include + +#define pi 3.14159265358979323846 + +Display *d; +Window win; +CGContextRef ctx; + +extern CGContextRef opal_XWindowContextCreate(Display *d, Window w); +extern void frameArc(CGContextRef context, CGRect r, int startAngle, int arcAngle); +extern void paintArc(CGContextRef context, CGRect r, int startAngle, int arcAngle); +extern void frameOval(CGContextRef context, CGRect r); +extern void paintOval(CGContextRef context, CGRect r); +extern void frameRect(CGContextRef context, CGRect r); +extern void paintRect(CGContextRef context, CGRect r); +extern void fillRoundedRect(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight); +extern void strokeRoundedRect(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight); + +void draw(CGContextRef ctx, CGRect r) +{ + CGRect bounds = r; + double a, b; + int count, k; + + CGContextSetRGBFillColor(ctx, 0, 0, 0, 1); + CGContextFillRect(ctx, CGRectMake(0, r.size.height / 2, r.size.width, r.size.height / 2)); + + // Use a transparency layer for the first shape + + CGContextSetAlpha(ctx, 0.5); + CGContextBeginTransparencyLayer(ctx, NULL); + + // Calculate the dimensions for an oval inside the bounding box + a = 0.9 * bounds.size.width/4; + b = 0.3 * bounds.size.height/2; + count = 5; + + // Set the fill color to a partially transparent blue + CGContextSetRGBFillColor(ctx, 0, 0, 1, 1); + + // Set the stroke color to an opaque black + CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 1); + + // Set the line width to be used, in user space units. + CGContextSetLineWidth(ctx, 3); + + // Save the conexts state because we are going to be moving the origin and + // rotating context for drawing, but we would like to restore the current + // state before drawing the next image. + CGContextSaveGState(ctx); + + // Move the origin to the middle of the first image (left side) to draw. + CGContextTranslateCTM(ctx, bounds.size.width/4, bounds.size.height/2); + + // Draw "count" ovals, rotating the context around the newly translated origin + // 1/count radians after drawing each oval + for (k = 0; k < count; k++) + { + // Paint the oval with the fill color + paintOval(ctx, CGRectMake(-a, -b, 2 * a, 2 * b)); + + // Frame the oval with the stroke color + frameOval(ctx, CGRectMake(-a, -b, 2 * a, 2 * b)); + + // Rotate the context around the center of the image + CGContextRotateCTM(ctx, pi / count); + } + // Restore the saved state to a known state for dawing the next image + CGContextRestoreGState(ctx); + + // End the transparency layer + CGContextEndTransparencyLayer(ctx); + + + + // Calculate a bounding box for the rounded rect + a = 0.9 * bounds.size.width/4; + b = 0.3 * bounds.size.height/2; + count = 5; + + // Set the fill color to a partially transparent red + CGContextSetRGBFillColor(ctx, 1, 0, 0, 0.5); + + // Set the stroke color to an opaque black + CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 1); + + // Set the line width to be used, in user space units. + CGContextSetLineWidth(ctx, 3); + + // Save the conexts state because we are going to be moving the origin and + // rotating context for drawing, but we would like to restore the current + // state before drawing the next image. + CGContextSaveGState(ctx); + + // Move the origin to the middle of the second image (right side) to draw. + CGContextTranslateCTM(ctx, bounds.size.width/4 + bounds.size.width/2, bounds.size.height/2); + + for (k = 0; k < count; k++) + { + // Fill then stroke the rounding rect, otherwise the fill would cover the stroke + fillRoundedRect(ctx, CGRectMake(-a, -b, 2 * a, 2 * b), 20, 20); + strokeRoundedRect(ctx, CGRectMake(-a, -b, 2 * a, 2 * b), 20, 20); + // Rotate the context for the next rounded rect + CGContextRotateCTM(ctx, pi / count); + } + CGContextRestoreGState(ctx); +} + + +int main(int argc, char **argv) +{ + int ret; + CGRect cr; + XSetWindowAttributes wa; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) { + fprintf(stderr,"Cannot open display: %s\n", XDisplayName(NULL)); + exit(EXIT_FAILURE); + } + printf("Opened display %s\n", DisplayString(d)); + + cr = CGRectMake(0,0,500,250); + wa.background_pixel = WhitePixel(d, DefaultScreen(d)); + wa.event_mask = ExposureMask | ButtonReleaseMask; + + /* Create a window */ + win = XCreateWindow(d, /* Display */ + DefaultRootWindow(d), /* Parent */ + cr.origin.x, cr.origin.y, /* x, y */ + cr.size.width, cr.size.height, /* width, height */ + 0, /* border_width */ + CopyFromParent, /* depth */ + InputOutput, /* class */ + CopyFromParent, /* visual */ + CWBackPixel | CWEventMask, /* valuemask */ + &wa); /* attributes */ + printf("XCreateWindow returned: %lx\n", win); + + /* Map the window */ + ret = XMapRaised(d, win); + printf("XMapRaised returned: %x\n", ret); + + /* Create a CGContext */ + ctx = opal_XWindowContextCreate(d, win); + if (!ctx) { + fprintf(stderr,"Cannot create context\n"); + exit(EXIT_FAILURE); + } + printf("Created context\n"); + + /* Flip coordinate system to match Quickdraw */ + CGContextTranslateCTM(ctx, 0, cr.size.height); + CGContextScaleCTM(ctx, 1.0, -1.0); +#if 0 + /* Draw something */ + // Draw the outer arcs in the left portion of the window + r.size.height = 210; + r.origin.x = 20; + r.origin.y = 20; + r.size.width = 210; + frameArc(ctx, r, 0, 135); + frameArc(ctx, r, 180 - 10, 20); + frameArc(ctx, r, 225, 45); + frameArc(ctx, r, 315 - 20, 40); + + // Draw the inner arcs in the left portion of the window + r.size.height = 145; + r.origin.x = 75; + r.origin.y = 55; + r.size.width = 100; + frameArc(ctx, r, 0, 135); + frameArc(ctx, r, 180 - 10, 20); + frameArc(ctx, r, 225, 45); + frameArc(ctx, r, 315 - 20, 40); + + /* Set the fill color to green. */ + CGContextSetRGBFillColor(ctx, 0, 1, 0, 1); + + // Draw and fill the outer arcs in the right portion of the window + r.size.height = 210; + r.origin.x = 270; + r.origin.y = 20; + r.size.width = 210; + paintArc(ctx, r, 0, 135); + paintArc(ctx, r, 180 - 10, 20); + paintArc(ctx, r, 225, 45); + paintArc(ctx, r, 315 - 20, 40); + + /* Set the fill color to yellow. */ + CGContextSetRGBFillColor(ctx, 1, 1, 0, 1); + + // Draw and fill the inner arcs in the right portion of the window + r.size.height = 145; + r.origin.x = 325; + r.origin.y = 55; + r.size.width = 100; + paintArc(ctx, r, 0, 135); + paintArc(ctx, r, 180 - 10, 20); + paintArc(ctx, r, 225, 45); + paintArc(ctx, r, 315 - 20, 40); + CGContextFlush(ctx); + getchar(); + + XClearWindow(d, win); + // Draw the outer oval in the left portion of the window + r.size.height = 210; + r.origin.x = 20; + r.origin.y = 20; + r.size.width = 210; + frameOval(ctx, r); + + // Draw the inner oval in the left portion of the window + r.size.height = 145; + r.origin.x = 75; + r.origin.y = 55; + r.size.width = 100; + frameOval(ctx, r); + + /* Set the fill color to green. */ + CGContextSetRGBFillColor(ctx, 0, 1, 0, 1); + + // Draw and fill the outter oval in the right portion of the window + r.size.height = 210; + r.origin.x = 270; + r.origin.y = 20; + r.size.width = 210; + paintOval(ctx, r); + + /* Set the fill color to yellow. */ + CGContextSetRGBFillColor(ctx, 1, 1, 0, 1); + + // Draw and fill the inner oval in the right portion of the window + r.size.height = 145; + r.origin.x = 325; + r.origin.y = 55; + r.size.width = 100; + paintOval(ctx, r); + + CGContextFlush(ctx); + getchar(); + + XClearWindow(d, win); + /* Set the stroke color to black. */ + CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 1); + + r.size.height = 210; + r.origin.x = 20; + r.origin.y = 20; + r.size.width = 210; + frameRect(ctx, r); + + r.size.height = 145; + r.origin.x = 75; + r.origin.y = 55; + r.size.width = 100; + frameRect(ctx, r); + + /* Set the fill color to green. */ + CGContextSetRGBFillColor(ctx, 0, 1, 0, 1); + + r.size.height = 210; + r.origin.x = 270; + r.origin.y = 20; + r.size.width = 210; + paintRect(ctx, r); + + /* Set the fill color to yellow. */ + CGContextSetRGBFillColor(ctx, 1, 1, 0, 1); + + r.size.height = 145; + r.origin.x = 325; + r.origin.y = 55; + r.size.width = 100; + paintRect(ctx, r); + + CGContextFlush(ctx); + getchar(); +#endif + + while(1) + { + XNextEvent(d,&e); + switch(e.type) + { + case Expose: + /* Dispose multiple events */ + while (XCheckTypedEvent(d, Expose, &e)); + /* Draw window contents */ + if(e.xexpose.count == 0) { + CGContextSaveGState(ctx); + XClearWindow(d, win); + draw(ctx, cr); + CGContextRestoreGState(ctx); + } + break; + + case ButtonRelease: + /* Finish program */ + CGContextRelease(ctx); + XCloseDisplay(d); + exit(EXIT_SUCCESS); + break; + } + } + + return(EXIT_SUCCESS); +} diff --git a/texttest.c b/texttest.c new file mode 100644 index 0000000..476368d --- /dev/null +++ b/texttest.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include + +Display *d; +Window win; +CGContextRef ctx; +static const char *fontName = "Times-Roman"; + +extern CGContextRef opal_XWindowContextCreate(Display *d, Window w); + +void drawRect(CGContextRef currentContext, CGRect rect) +{ + CGRect pageRect = CGRectMake( 0, 0, rect.size.width, rect.size.height ); + + CGContextBeginPage(currentContext, &pageRect); + + CGContextSetGrayFillColor(currentContext, 0, 1); + + CGContextSelectFont(currentContext, fontName, 1, kCGEncodingMacRoman); + CGContextShowTextAtPoint(currentContext, 40, 200, "1: M x", 6); + + CGContextSelectFont(currentContext, fontName, 2, kCGEncodingMacRoman); + CGContextShowTextAtPoint(currentContext, 40, 150, "2: M x", 6); + + CGContextSelectFont(currentContext, fontName, 3, kCGEncodingMacRoman); + CGContextShowTextAtPoint(currentContext, 40, 100, "3: M x", 6); + + CGContextSelectFont(currentContext, fontName, 4, kCGEncodingMacRoman); + CGContextShowTextAtPoint(currentContext, 40, 50, "4: M x", 6); + + CGContextEndPage(currentContext); + + CGContextFlush(currentContext); +} + +int main(int argc, char **argv) +{ + int ret; + CGRect cr; + XSetWindowAttributes wa; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) { + fprintf(stderr,"Cannot open display: %s\n", XDisplayName(NULL)); + exit(EXIT_FAILURE); + } + printf("Opened display %s\n", DisplayString(d)); + if (argc > 1) + { + fontName = argv[1]; + } + + cr = CGRectMake(0,0,480,360); + wa.background_pixel = WhitePixel(d, DefaultScreen(d)); + wa.event_mask = ExposureMask | ButtonReleaseMask; + + /* Create a window */ + win = XCreateWindow(d, /* Display */ + DefaultRootWindow(d), /* Parent */ + cr.origin.x, cr.origin.y, /* x, y */ + cr.size.width, cr.size.height, /* width, height */ + 0, /* border_width */ + CopyFromParent, /* depth */ + InputOutput, /* class */ + CopyFromParent, /* visual */ + CWBackPixel | CWEventMask, /* valuemask */ + &wa); /* attributes */ + printf("XCreateSimpleWindow returned: %lx\n", win); + + /* Map the window */ + ret = XMapRaised(d, win); + printf("XMapRaised returned: %x\n", ret); + + /* Create a CGContext */ + ctx = opal_XWindowContextCreate(d, win); + if (!ctx) { + fprintf(stderr,"Cannot create context\n"); + exit(EXIT_FAILURE); + } + printf("Created context\n"); + + while(1) + { + XNextEvent(d,&e); + switch(e.type) + { + case Expose: + /* Draw window contents */ + if(e.xexpose.count == 0) { + XClearWindow(d, win); + drawRect(ctx, cr); + } + break; + + case ButtonRelease: + /* Finish program */ + CGContextRelease(ctx); + XCloseDisplay(d); + exit(EXIT_SUCCESS); + break; + } + } +}