rubyquartz 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. data/COPYRIGHT +24 -0
  2. data/History.txt +9 -0
  3. data/Manifest.txt +95 -0
  4. data/README.txt +71 -0
  5. data/Rakefile +51 -0
  6. data/ext/ExportedSymbols.txt +1 -0
  7. data/ext/bitmap.c +129 -0
  8. data/ext/bitmap.h +38 -0
  9. data/ext/bitmap_context.c +67 -0
  10. data/ext/bitmap_context.h +31 -0
  11. data/ext/color.c +145 -0
  12. data/ext/color.h +34 -0
  13. data/ext/colorspace.c +94 -0
  14. data/ext/colorspace.h +33 -0
  15. data/ext/context.c +393 -0
  16. data/ext/context.h +33 -0
  17. data/ext/extconf.rb +48 -0
  18. data/ext/font.c +148 -0
  19. data/ext/font.h +32 -0
  20. data/ext/function.c +124 -0
  21. data/ext/function.h +32 -0
  22. data/ext/image.c +140 -0
  23. data/ext/image.h +31 -0
  24. data/ext/image_source.c +143 -0
  25. data/ext/image_source.h +31 -0
  26. data/ext/pdf_document.c +91 -0
  27. data/ext/pdf_document.h +31 -0
  28. data/ext/pdf_page.c +79 -0
  29. data/ext/pdf_page.h +31 -0
  30. data/ext/point.c +42 -0
  31. data/ext/point.h +32 -0
  32. data/ext/rect.c +45 -0
  33. data/ext/rect.h +32 -0
  34. data/ext/rubyquartz.c +80 -0
  35. data/ext/rubyquartz.h +29 -0
  36. data/ext/rubyquartz_prefix.h +45 -0
  37. data/ext/shading.c +68 -0
  38. data/ext/shading.h +32 -0
  39. data/ext/size.c +42 -0
  40. data/ext/size.h +32 -0
  41. data/ext/text.c +258 -0
  42. data/ext/text.h +39 -0
  43. data/ext/utilities.c +181 -0
  44. data/ext/utilities.h +43 -0
  45. data/lib/rubyquartz.rb +59 -0
  46. data/lib/rubyquartz/bitmap.rb +62 -0
  47. data/lib/rubyquartz/bitmap_context.rb +50 -0
  48. data/lib/rubyquartz/color.rb +68 -0
  49. data/lib/rubyquartz/colorspace.rb +42 -0
  50. data/lib/rubyquartz/context.rb +116 -0
  51. data/lib/rubyquartz/font.rb +48 -0
  52. data/lib/rubyquartz/function.rb +57 -0
  53. data/lib/rubyquartz/image.rb +48 -0
  54. data/lib/rubyquartz/image_source.rb +50 -0
  55. data/lib/rubyquartz/pdf_document.rb +47 -0
  56. data/lib/rubyquartz/pdf_page.rb +54 -0
  57. data/lib/rubyquartz/point.rb +63 -0
  58. data/lib/rubyquartz/rect.rb +127 -0
  59. data/lib/rubyquartz/shading.rb +48 -0
  60. data/lib/rubyquartz/size.rb +39 -0
  61. data/lib/rubyquartz/text.rb +50 -0
  62. data/test/images/TestContext.test_begin_path.png +0 -0
  63. data/test/images/TestContext.test_draw_image.png +0 -0
  64. data/test/images/TestContext.test_draw_path.png +0 -0
  65. data/test/images/TestContext.test_draw_pdf.png +0 -0
  66. data/test/images/TestContext.test_draw_shading_axial.png +0 -0
  67. data/test/images/TestContext.test_draw_text.png +0 -0
  68. data/test/images/TestContext.test_draw_text_baseline_aligned.png +0 -0
  69. data/test/images/TestContext.test_draw_text_flipped.png +0 -0
  70. data/test/images/TestContext.test_draw_text_flipped_non_zero_point.png +0 -0
  71. data/test/images/TestContext.test_draw_text_non_zero_point.png +0 -0
  72. data/test/images/TestContext.test_fill.png +0 -0
  73. data/test/images/TestContext.test_gsave.png +0 -0
  74. data/test/images/TestContext.test_gsave_block.png +0 -0
  75. data/test/images/TestContext.test_line_width.png +0 -0
  76. data/test/images/TestContext.test_lineto.png +0 -0
  77. data/test/images/TestContext.test_rotate.png +0 -0
  78. data/test/images/TestContext.test_rounded_rect.png +0 -0
  79. data/test/images/TestContext.test_scale.png +0 -0
  80. data/test/images/TestContext.test_set_line_dash.png +0 -0
  81. data/test/images/TestContext.test_shadow.png +0 -0
  82. data/test/images/TestContext.test_stroke_rect.png +0 -0
  83. data/test/images/TestContext.test_text_bounds.png +0 -0
  84. data/test/images/TestContext.test_translate.png +0 -0
  85. data/test/inputs/circle.pdf +0 -0
  86. data/test/inputs/wash.png +0 -0
  87. data/test/rubyquartz_test.rb +51 -0
  88. data/test/tc_bitmap_context.rb +43 -0
  89. data/test/tc_color.rb +43 -0
  90. data/test/tc_context.rb +315 -0
  91. data/test/tc_font.rb +54 -0
  92. data/test/tc_image_source.rb +69 -0
  93. data/test/tc_pdf_document.rb +63 -0
  94. data/test/tc_pdf_page.rb +53 -0
  95. data/test/tc_text.rb +39 -0
  96. metadata +156 -0
@@ -0,0 +1,31 @@
1
+ /*
2
+ Copyright (c) 2006, The Omni Group, Inc. All rights reserved.
3
+
4
+ OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE
5
+
6
+ Omni Source Code software is available from The Omni Group on their web
7
+ site at www.omnigroup.com.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a
10
+ copy of this software and associated documentation files (the "Software"),
11
+ to deal in the Software without restriction, including without limitation
12
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
+ and/or sell copies of the Software, and to permit persons to whom the
14
+ Software is furnished to do so, subject to the following conditions:
15
+
16
+ Any original copyright notices and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+ DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ extern void Init_bitmap_context(void);
29
+ extern VALUE bitmap_context_class;
30
+
31
+ extern CGContextRef bitmap_context_get(VALUE self);
data/ext/color.c ADDED
@@ -0,0 +1,145 @@
1
+ /*
2
+ Copyright (c) 2006, The Omni Group, Inc. All rights reserved.
3
+
4
+ OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE
5
+
6
+ Omni Source Code software is available from The Omni Group on their web
7
+ site at www.omnigroup.com.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a
10
+ copy of this software and associated documentation files (the "Software"),
11
+ to deal in the Software without restriction, including without limitation
12
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
+ and/or sell copies of the Software, and to permit persons to whom the
14
+ Software is furnished to do so, subject to the following conditions:
15
+
16
+ Any original copyright notices and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+ DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include "color.h"
29
+
30
+ #include "colorspace.h"
31
+
32
+ #import <AppKit/NSColor.h>
33
+ #import <AppKit/NSGraphicsContext.h>
34
+ #import <Foundation/NSAutoreleasePool.h>
35
+
36
+ @interface _RBQuartzColor : NSObject
37
+ {
38
+ CGColorRef _color;
39
+ }
40
+ - initWithColorRef:(CGColorRef)color;
41
+ @end
42
+
43
+ @implementation _RBQuartzColor
44
+ - initWithColorRef:(CGColorRef)color;
45
+ {
46
+ _color = (CGColorRef)CFRetain(color);
47
+ return self;
48
+ }
49
+ - (void)dealloc;
50
+ {
51
+ CFRelease(_color);
52
+ [super dealloc];
53
+ }
54
+ - (void)set;
55
+ {
56
+ CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
57
+ if (ctx) {
58
+ CGContextSetFillColorWithColor(ctx, _color);
59
+ CGContextSetStrokeColorWithColor(ctx, _color);
60
+ }
61
+ }
62
+ - (void)setFill;
63
+ {
64
+ CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
65
+ if (ctx)
66
+ CGContextSetFillColorWithColor(ctx, _color);
67
+ }
68
+ - (void)setStroke;
69
+ {
70
+ CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
71
+ if (ctx)
72
+ CGContextSetStrokeColorWithColor(ctx, _color);
73
+ }
74
+ @end
75
+
76
+ VALUE color_class;
77
+
78
+ CGColorRef color_get(VALUE self)
79
+ {
80
+ return (CGColorRef)_cftype_get(self, CGColorGetTypeID(), "CGColorRef");
81
+ }
82
+ static void color_set(VALUE self, CGColorRef color)
83
+ {
84
+ _cftype_set(self, CGColorGetTypeID(), "CGColorRef", color);
85
+ }
86
+
87
+ NSColor *color_create_wrapper(CGColorRef color)
88
+ {
89
+ return [[_RBQuartzColor alloc] initWithColorRef:color];
90
+ }
91
+
92
+ static VALUE _color_initialize_with_components(VALUE self, VALUE colorspace, VALUE components)
93
+ {
94
+ components = rb_check_convert_type(components, T_ARRAY, "Array", "to_a");
95
+
96
+ CGColorSpaceRef cs = colorspace_get(colorspace);
97
+ size_t componentIndex, componentCount = CGColorSpaceGetNumberOfComponents(cs) + 1; /* for alpha */
98
+
99
+ float *c = malloc(componentCount * sizeof(c));
100
+ for (componentIndex = 0; componentIndex < componentCount; componentIndex++)
101
+ c[componentIndex] = NUM2DBL(rb_ary_entry(components, componentIndex));
102
+
103
+ CGColorRef color = CGColorCreate(cs, c);
104
+ free(c);
105
+
106
+ if (!color)
107
+ rb_raise(rb_eException, "Unable to create color");
108
+
109
+ color_set(self, color);
110
+ CFRelease(color);
111
+
112
+ return self;
113
+ }
114
+
115
+ static VALUE _color_convert_hsv_to_rgb(VALUE self, VALUE components)
116
+ {
117
+ components = rb_check_convert_type(components, T_ARRAY, "Array", "to_a");
118
+ float h = NUM2DBL(rb_ary_entry(components, 0));
119
+ float s = NUM2DBL(rb_ary_entry(components, 1));
120
+ float v = NUM2DBL(rb_ary_entry(components, 2));
121
+
122
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
123
+ @try {
124
+ NSColor *color = [NSColor colorWithCalibratedHue:h saturation:s brightness:v alpha:1.0f];
125
+
126
+ float red, green, blue, alpha;
127
+ [color getRed:&red green:&green blue:&blue alpha:&alpha];
128
+
129
+ rb_ary_store(components, 0, rb_float_new(red));
130
+ rb_ary_store(components, 1, rb_float_new(green));
131
+ rb_ary_store(components, 2, rb_float_new(blue));
132
+ return self;
133
+ } @finally {
134
+ [pool release];
135
+ }
136
+ rb_raise(rb_eException, "Unable to convert HSV to RGB");
137
+ }
138
+
139
+ void Init_color(void)
140
+ {
141
+ color_class = rb_define_class_under(module, "Color", rb_cObject);
142
+ rb_define_alloc_func(color_class, _cftype_alloc);
143
+ rb_define_private_method(color_class, "_initialize_with_components", _color_initialize_with_components, 2);
144
+ rb_define_module_function(color_class, "convert_hsv_to_rgb", _color_convert_hsv_to_rgb, 1);
145
+ }
data/ext/color.h ADDED
@@ -0,0 +1,34 @@
1
+ /*
2
+ Copyright (c) 2006, The Omni Group, Inc. All rights reserved.
3
+
4
+ OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE
5
+
6
+ Omni Source Code software is available from The Omni Group on their web
7
+ site at www.omnigroup.com.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a
10
+ copy of this software and associated documentation files (the "Software"),
11
+ to deal in the Software without restriction, including without limitation
12
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
+ and/or sell copies of the Software, and to permit persons to whom the
14
+ Software is furnished to do so, subject to the following conditions:
15
+
16
+ Any original copyright notices and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+ DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ extern void Init_color(void);
29
+ extern VALUE color_class;
30
+
31
+ extern CGColorRef color_get(VALUE self);
32
+
33
+ @class NSColor;
34
+ extern NSColor *color_create_wrapper(CGColorRef color);
data/ext/colorspace.c ADDED
@@ -0,0 +1,94 @@
1
+ /*
2
+ Copyright (c) 2006, The Omni Group, Inc. All rights reserved.
3
+
4
+ OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE
5
+
6
+ Omni Source Code software is available from The Omni Group on their web
7
+ site at www.omnigroup.com.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a
10
+ copy of this software and associated documentation files (the "Software"),
11
+ to deal in the Software without restriction, including without limitation
12
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
+ and/or sell copies of the Software, and to permit persons to whom the
14
+ Software is furnished to do so, subject to the following conditions:
15
+
16
+ Any original copyright notices and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+ DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include "colorspace.h"
29
+
30
+ const char *ColorSpaceClassName = "ColorSpace";
31
+
32
+ VALUE colorspace_class;
33
+ static VALUE generic_gray, generic_rgb, generic_cmyk;
34
+
35
+ // TODO: Allow for a 'bitmap' object of some sort so that the backing store can be reused between contexts?
36
+ // TODO: Make color space optional (default to generic rgb)?
37
+ static VALUE colorspace_init_with_name(VALUE self, VALUE name)
38
+ {
39
+ CFStringRef nameString;
40
+
41
+ if (name == generic_gray)
42
+ nameString = kCGColorSpaceGenericGray;
43
+ else if (name == generic_rgb)
44
+ nameString = kCGColorSpaceGenericRGB;
45
+ else if (name == generic_cmyk)
46
+ nameString = kCGColorSpaceGenericCMYK;
47
+ else
48
+ rb_raise(rb_eArgError, "The specified name is not a known colorspace name");
49
+
50
+ CGColorSpaceRef *colorspace;
51
+ Data_Get_Struct(self, CGColorSpaceRef, colorspace);
52
+
53
+ *colorspace = CGColorSpaceCreateWithName(nameString);
54
+ if (!*colorspace)
55
+ rb_raise(rb_eException, "Unable to create the colorspace with the given name");
56
+
57
+ return self;
58
+ }
59
+
60
+ static VALUE colorspace_component_count(VALUE self)
61
+ {
62
+ CGColorSpaceRef *colorspace;
63
+ Data_Get_Struct(self, CGColorSpaceRef, colorspace);
64
+
65
+ if (!colorspace || !*colorspace)
66
+ rb_raise(rb_eException, "Colorspace isn't correctly initialized");
67
+
68
+
69
+ return INT2FIX(CGColorSpaceGetNumberOfComponents(*colorspace));
70
+ }
71
+
72
+
73
+ CGColorSpaceRef colorspace_get(VALUE self)
74
+ {
75
+ return (CGColorSpaceRef)_cftype_get(self, CGColorSpaceGetTypeID(), "CGColorSpaceRef");
76
+ }
77
+
78
+ void Init_colorspace()
79
+ {
80
+ colorspace_class = rb_define_class_under(module, ColorSpaceClassName, rb_cObject);
81
+ rb_define_alloc_func(colorspace_class, _cftype_alloc);
82
+
83
+ rb_define_private_method(colorspace_class, "_init_with_name", colorspace_init_with_name, 1);
84
+ rb_define_method(colorspace_class, "component_count", colorspace_component_count, 0);
85
+
86
+ generic_gray = _symbol_for_string(kCGColorSpaceGenericGray);
87
+ rb_define_const(colorspace_class, "GENERIC_GRAY", generic_gray);
88
+
89
+ generic_rgb = _symbol_for_string(kCGColorSpaceGenericRGB);
90
+ rb_define_const(colorspace_class, "GENERIC_RGB", generic_rgb);
91
+
92
+ generic_cmyk = _symbol_for_string(kCGColorSpaceGenericCMYK);
93
+ rb_define_const(colorspace_class, "GENERIC_CMYK", generic_cmyk);
94
+ }
data/ext/colorspace.h ADDED
@@ -0,0 +1,33 @@
1
+ /*
2
+ Copyright (c) 2006, The Omni Group, Inc. All rights reserved.
3
+
4
+ OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE
5
+
6
+ Omni Source Code software is available from The Omni Group on their web
7
+ site at www.omnigroup.com.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a
10
+ copy of this software and associated documentation files (the "Software"),
11
+ to deal in the Software without restriction, including without limitation
12
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
+ and/or sell copies of the Software, and to permit persons to whom the
14
+ Software is furnished to do so, subject to the following conditions:
15
+
16
+ Any original copyright notices and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+ DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include "ruby.h"
29
+
30
+ extern void Init_colorspace(void);
31
+ extern VALUE colorspace_class;
32
+
33
+ extern CGColorSpaceRef colorspace_get(VALUE self);
data/ext/context.c ADDED
@@ -0,0 +1,393 @@
1
+ /*
2
+ Copyright (c) 2006, The Omni Group, Inc. All rights reserved.
3
+
4
+ OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE
5
+
6
+ Omni Source Code software is available from The Omni Group on their web
7
+ site at www.omnigroup.com.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a
10
+ copy of this software and associated documentation files (the "Software"),
11
+ to deal in the Software without restriction, including without limitation
12
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
+ and/or sell copies of the Software, and to permit persons to whom the
14
+ Software is furnished to do so, subject to the following conditions:
15
+
16
+ Any original copyright notices and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+ DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include "context.h"
29
+
30
+ #include "color.h"
31
+ #include "text.h"
32
+ #include "shading.h"
33
+ #include "image.h"
34
+ #include "pdf_page.h"
35
+
36
+ #import <Cocoa/Cocoa.h>
37
+
38
+ const char *ContextClassName = "Context";
39
+
40
+ VALUE context_class;
41
+
42
+ static VALUE context_init(VALUE self)
43
+ {
44
+ // This is an abstract superclass; you can't directly initialize it.
45
+ if (CLASS_OF(self) == context_class)
46
+ rb_raise(rb_eTypeError, "%s is an abstract class, please create an instance of a subclass", ContextClassName);
47
+ return self;
48
+ }
49
+
50
+ CGContextRef context_get(VALUE self)
51
+ {
52
+ return (CGContextRef)_cftype_get(self, CGContextGetTypeID(), "CGContextRef");
53
+ }
54
+
55
+ static VALUE context_gsave(VALUE self)
56
+ {
57
+ CGContextSaveGState(context_get(self));
58
+ return self;
59
+ }
60
+
61
+ static VALUE context_grestore(VALUE self)
62
+ {
63
+ // TODO: Added depth counter of our own or just depend on CG? It won't raise an exception, but will likely just log a message
64
+ CGContextRestoreGState(context_get(self));
65
+ return self;
66
+ }
67
+
68
+ static VALUE context_scale(VALUE self, VALUE sx, VALUE sy)
69
+ {
70
+ CGContextScaleCTM(context_get(self), NUM2DBL(sx), NUM2DBL(sy));
71
+ return self;
72
+ }
73
+
74
+ static VALUE context_translate(VALUE self, VALUE tx, VALUE ty)
75
+ {
76
+ CGContextTranslateCTM(context_get(self), NUM2DBL(tx), NUM2DBL(ty));
77
+ return self;
78
+ }
79
+
80
+ static VALUE context_rotate(VALUE self, VALUE a)
81
+ {
82
+ CGContextRotateCTM(context_get(self), NUM2DBL(a));
83
+ return self;
84
+ }
85
+
86
+ // ConcatCTM
87
+ // GetCTM
88
+
89
+ static VALUE context_set_line_width(VALUE self, VALUE width)
90
+ {
91
+ CGContextSetLineWidth(context_get(self), NUM2DBL(width));
92
+ return self;
93
+ }
94
+
95
+ // SetLineCap
96
+ // SetLineJoin
97
+ // SetMiterLimit
98
+
99
+ static VALUE context_set_line_dash(VALUE self, VALUE phase, VALUE dash)
100
+ {
101
+ float phaseNumber = NUM2DBL(phase);
102
+
103
+ dash = rb_check_convert_type(dash, T_ARRAY, "Array", "to_a");
104
+ unsigned dashCount = NUM2INT(rb_funcall(dash, rb_intern("size"), 0));
105
+
106
+ // TODO: If an element of the dash array can't be turned into a double, this'll raise and leak the array.
107
+ float *pattern = malloc(sizeof(float) * dashCount);
108
+ unsigned int i;
109
+ for (i = 0; i < dashCount; i++)
110
+ pattern[i] = NUM2DBL(rb_ary_entry(dash, i));
111
+
112
+ CGContextSetLineDash(context_get(self), phaseNumber, pattern, dashCount);
113
+ free(pattern);
114
+
115
+ return self;
116
+ }
117
+
118
+ // SetFlatness
119
+
120
+ static VALUE context_set_alpha(VALUE self, VALUE alpha)
121
+ {
122
+ CGContextSetAlpha(context_get(self), NUM2DBL(alpha));
123
+ return self;
124
+ }
125
+
126
+ // SetBlendMode
127
+
128
+ static VALUE context_begin_path(VALUE self)
129
+ {
130
+ CGContextBeginPath(context_get(self));
131
+ return self;
132
+ }
133
+
134
+ static VALUE context_moveto(VALUE self, VALUE x, VALUE y)
135
+ {
136
+ CGContextMoveToPoint(context_get(self), NUM2DBL(x), NUM2DBL(y));
137
+ return self;
138
+ }
139
+
140
+ static VALUE context_lineto(VALUE self, VALUE x, VALUE y)
141
+ {
142
+ CGContextAddLineToPoint(context_get(self), NUM2DBL(x), NUM2DBL(y));
143
+ return self;
144
+ }
145
+
146
+ // CGContextAddCurveToPoint
147
+ // CGContextAddQuadCurveToPoint
148
+
149
+ static VALUE context_close_path(VALUE self)
150
+ {
151
+ CGContextClosePath(context_get(self));
152
+ return self;
153
+ }
154
+
155
+ static VALUE context_add_rect(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h)
156
+ {
157
+ CGRect r = CGRectMake(NUM2DBL(x), NUM2DBL(y), NUM2DBL(w), NUM2DBL(h));
158
+ CGContextAddRect(context_get(self), r);
159
+ return self;
160
+ }
161
+
162
+ // CGContextAddRects
163
+ // CGContextAddLines
164
+ // CGContextAddEllipseInRect
165
+ // CGContextAddArc
166
+
167
+ static VALUE context_arc_to_point(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE radius)
168
+ {
169
+ CGContextAddArcToPoint(context_get(self), NUM2DBL(x1), NUM2DBL(y1), NUM2DBL(x2), NUM2DBL(y2), NUM2DBL(radius));
170
+ return self;
171
+ }
172
+
173
+ // CGContextAddPath
174
+ // CGContextReplacePathWithStrokedPath
175
+ // CGContextIsPathEmpty
176
+ // CGContextGetPathCurrentPoint
177
+ // CGContextGetPathBoundingBox
178
+ // CGContextPathContainsPoint
179
+
180
+ static VALUE context_draw_path(VALUE self, VALUE mode)
181
+ {
182
+ CGContextDrawPath(context_get(self), NUM2UINT(mode));
183
+ return self;
184
+ }
185
+
186
+ static VALUE context_fill(VALUE self)
187
+ {
188
+ CGContextFillPath(context_get(self));
189
+ return self;
190
+ }
191
+
192
+ // CGContextEOFillPath
193
+
194
+ static VALUE context_stroke(VALUE self)
195
+ {
196
+ CGContextStrokePath(context_get(self));
197
+ return self;
198
+ }
199
+
200
+ static VALUE context_fill_rect(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h)
201
+ {
202
+ CGContextFillRect(context_get(self), CGRectMake(NUM2DBL(x), NUM2DBL(y), NUM2DBL(w), NUM2DBL(h)));
203
+ return self;
204
+ }
205
+
206
+ // CGContextFillRects
207
+
208
+ static VALUE context_stroke_rect(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h)
209
+ {
210
+ CGContextStrokeRect(context_get(self), CGRectMake(NUM2DBL(x), NUM2DBL(y), NUM2DBL(w), NUM2DBL(h)));
211
+ return self;
212
+ }
213
+
214
+ // CGContextStrokeRectWithWidth
215
+ // CGContextClearRect
216
+ // CGContextFillEllipseInRect
217
+ // CGContextStrokeEllipseInRect
218
+ // CGContextStrokeLineSegments
219
+
220
+ static VALUE context_clip(VALUE self)
221
+ {
222
+ CGContextClip(context_get(self));
223
+ return self;
224
+ }
225
+
226
+ // CGContextEOClip
227
+ // CGContextClipToMask
228
+ // CGContextGetClipBoundingBox
229
+ // CGContextClipToRect
230
+ // CGContextClipToRects
231
+
232
+ static VALUE context_set_fill_color(VALUE self, VALUE color)
233
+ {
234
+ CGContextSetFillColorWithColor(context_get(self), color_get(color));
235
+ return self;
236
+ }
237
+
238
+ static VALUE context_set_stroke_color(VALUE self, VALUE color)
239
+ {
240
+ CGContextSetStrokeColorWithColor(context_get(self), color_get(color));
241
+ return self;
242
+ }
243
+
244
+ // CGContextSetFillColorSpace
245
+ // CGContextSetStrokeColorSpace
246
+ // CGContextSetFillColor
247
+ // CGContextSetStrokeColor
248
+ // CGContextSetFillPattern
249
+ // CGContextSetStrokePattern
250
+ // CGContextSetPatternPhase
251
+ // CGContextSetGrayFillColor
252
+ // CGContextSetGrayStrokeColor
253
+ // CGContextSetRGBFillColor
254
+ // CGContextSetRGBStrokeColor
255
+ // CGContextSetCMYKFillColor
256
+ // CGContextSetCMYKStrokeColor
257
+ // CGContextSetRenderingIntent
258
+
259
+ static VALUE context_draw_image(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h, VALUE image)
260
+ {
261
+ CGRect rect = CGRectMake(NUM2DBL(x), NUM2DBL(y), NUM2DBL(w), NUM2DBL(h));
262
+ CGContextDrawImage(context_get(self), rect, image_get(image));
263
+ return self;
264
+ }
265
+
266
+ // CGContextDrawImage
267
+ // CGContextGetInterpolationQuality
268
+ // CGContextSetInterpolationQuality
269
+
270
+ static VALUE context_set_shadow_with_color(VALUE self, VALUE offset_x, VALUE offset_y, VALUE blur, VALUE color)
271
+ {
272
+ CGContextSetShadowWithColor(context_get(self), CGSizeMake(NUM2DBL(offset_x), NUM2DBL(offset_y)), NUM2DBL(blur), color_get(color));
273
+ return self;
274
+ }
275
+
276
+ // CGContextSetShadow
277
+
278
+ static VALUE context_draw_shading(VALUE self, VALUE shading)
279
+ {
280
+ CGContextDrawShading(context_get(self), shading_get(shading));
281
+ return self;
282
+ }
283
+
284
+ // CGContextSetCharacterSpacing
285
+ // CGContextSetTextPosition
286
+ // CGContextGetTextPosition
287
+ // CGContextSetTextMatrix
288
+ // CGContextGetTextMatrix
289
+ // CGContextSetTextDrawingMode
290
+ // CGContextSetFont
291
+ // CGContextSetFontSize
292
+ // CGContextSelectFont
293
+ // CGContextShowText
294
+ // CGContextShowGlyphs
295
+ // CGContextShowGlyphsWithAdvances
296
+ // CGContextShowTextAtPoint
297
+ // CGContextShowGlyphsAtPoint
298
+
299
+ static VALUE context_draw_pdf_page(VALUE self, VALUE page_value)
300
+ {
301
+ CGContextDrawPDFPage(context_get(self), pdf_page_get(page_value));
302
+ return self;
303
+ }
304
+
305
+ // CGContextDrawPDFDocument -- deprecated
306
+ // CGContextBeginPage
307
+ // CGContextEndPage
308
+ // CGContextRetain
309
+ // CGContextRelease
310
+ // CGContextFlush
311
+ // CGContextSynchronize
312
+ // CGContextSetShouldAntialias
313
+ // CGContextSetAllowsAntialiasing
314
+ // CGContextSetShouldSmoothFonts
315
+ // CGContextBeginTransparencyLayer
316
+ // CGContextEndTransparencyLayer
317
+ // CGContextGetUserSpaceToDeviceSpaceTransform
318
+ // CGContextConvertPointToDeviceSpace
319
+ // CGContextConvertPointToUserSpace
320
+ // CGContextConvertSizeToDeviceSpace
321
+ // CGContextConvertSizeToUserSpace
322
+ // CGContextConvertRectToDeviceSpace
323
+ // CGContextConvertRectToUserSpace
324
+
325
+ static VALUE context_draw_text(VALUE self, VALUE text, VALUE x, VALUE y, VALUE draw_background)
326
+ {
327
+ CGContextRef ctx = context_get(self);
328
+ Text *t = text_get(text);
329
+ NSPoint pt = NSMakePoint(NUM2DBL(x), NUM2DBL(y));
330
+ BOOL bg = RTEST(draw_background);
331
+
332
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
333
+ NSGraphicsContext *oldGC = [NSGraphicsContext currentContext];
334
+ @try {
335
+ // NOTE: We are safe here, but on the CG list it was noted that deallocating a CGPDF context has a special meaning and retaining it via NSGraphicsContext can break stuff.
336
+ NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]; // flipped is meaningless here since we aren't using NSView
337
+ [NSGraphicsContext setCurrentContext:gc];
338
+
339
+ NSLayoutManager *layoutManager = t->layoutManager;
340
+ NSRange glyphRange = NSMakeRange(0, [layoutManager numberOfGlyphs]);
341
+ if (glyphRange.length) {
342
+ if (bg)
343
+ [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:pt];
344
+ [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:pt];
345
+ }
346
+ return self;
347
+ } @catch (NSException *exc) {
348
+ NSLog(@"%s -- %@", __PRETTY_FUNCTION__, exc);
349
+ } @finally {
350
+ [NSGraphicsContext setCurrentContext:oldGC];
351
+ [pool release];
352
+ }
353
+ rb_raise(rb_eArgError, "Unable to draw Text");
354
+ }
355
+
356
+ void Init_context(void)
357
+ {
358
+ context_class = rb_define_class_under(module, ContextClassName, rb_cObject);
359
+ rb_define_alloc_func(context_class, _cftype_alloc);
360
+
361
+ rb_define_method(context_class, "initialize", context_init, 0);
362
+ rb_define_private_method(context_class, "_gsave", context_gsave, 0);
363
+ rb_define_method(context_class, "grestore", context_grestore, 0);
364
+ rb_define_method(context_class, "scale", context_scale, 2);
365
+ rb_define_method(context_class, "translate", context_translate, 2);
366
+ rb_define_method(context_class, "rotate", context_rotate, 1);
367
+
368
+ rb_define_method(context_class, "line_width=", context_set_line_width, 1);
369
+ rb_define_method(context_class, "set_line_dash", context_set_line_dash, 2);
370
+ rb_define_method(context_class, "set_alpha", context_set_alpha, 1);
371
+ rb_define_method(context_class, "begin_path", context_begin_path, 0);
372
+ rb_define_method(context_class, "moveto", context_moveto, 2);
373
+ rb_define_method(context_class, "lineto", context_lineto, 2);
374
+ rb_define_method(context_class, "close_path", context_close_path, 0);
375
+ rb_define_method(context_class, "add_rect", context_add_rect, 4);
376
+ rb_define_method(context_class, "arc_to_point", context_arc_to_point, 5);
377
+ rb_define_private_method(context_class, "_draw_path", context_draw_path, 1);
378
+ rb_define_method(context_class, "fill", context_fill, 0);
379
+ rb_define_method(context_class, "stroke", context_stroke, 0);
380
+ rb_define_private_method(context_class, "_fill_rect", context_fill_rect, 4);
381
+ rb_define_private_method(context_class, "_stroke_rect", context_stroke_rect, 4);
382
+ rb_define_method(context_class, "clip", context_clip, 0);
383
+ rb_define_method(context_class, "fill_color=", context_set_fill_color, 1);
384
+ rb_define_method(context_class, "stroke_color=", context_set_stroke_color, 1);
385
+ rb_define_method(context_class, "draw_image", context_draw_image, 5);
386
+ rb_define_method(context_class, "shadow", context_set_shadow_with_color, 4);
387
+ rb_define_method(context_class, "draw_shading", context_draw_shading, 1);
388
+
389
+ rb_define_method(context_class, "draw_pdf_page", context_draw_pdf_page, 1);
390
+
391
+ rb_define_method(context_class, "_draw_text", context_draw_text, 4);
392
+ }
393
+