~ubuntu-branches/ubuntu/wily/lua-lgi/wily-proposed

« back to all changes in this revision

Viewing changes to lgi/override/cairo.lua

  • Committer: Package Import Robot
  • Author(s): Enrico Tassi
  • Date: 2012-06-25 13:36:04 UTC
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: package-import@ubuntu.com-20120625133604-3v03ss7t7cwdmp6z
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
--
9
9
------------------------------------------------------------------------------
10
10
 
11
 
local assert, pairs, ipairs, setmetatable, table, rawget
12
 
   = assert, pairs, ipairs, setmetatable, table, rawget
 
11
local assert, pairs, ipairs, setmetatable, table, rawget, type
 
12
   = assert, pairs, ipairs, setmetatable, table, rawget, type
13
13
local lgi = require 'lgi'
14
14
local cairo = lgi.cairo
15
15
 
23
23
cairo._module = core.module('cairo', 2)
24
24
local module_gobject = core.gi.cairo.resolve
25
25
 
 
26
-- Versioning support.
 
27
function cairo.version_encode(major, minor, micro)
 
28
   return 10000 * major + 100 * minor + micro
 
29
end
 
30
cairo.version = core.callable.new {
 
31
   addr = cairo._module.cairo_version, ret = ti.int } ()
 
32
cairo.version_string = core.callable.new {
 
33
   addr = cairo._module.cairo_version_string, ret = ti.utf8 } ()
 
34
 
26
35
-- Load some constants.
27
36
cairo._constant = {
28
37
   MIME_TYPE_JP2 = 'image/jp2',
52
61
 
53
62
-- Load definitions of all boxed records.
54
63
cairo._struct = cairo._struct or {}
55
 
for _, struct in pairs {
 
64
for index, struct in pairs {
56
65
   'Context', 'Device', 'Surface', 'Rectangle', 'ScaledFont', 'FontFace',
57
66
   'FontOptions', 'Region', 'RectangleInt', 'Path', 'TextExtents',
58
67
   'FontExtents', 'Matrix', 'ImageSurface', 'PdfSurface', 'PsSurface',
59
68
   'RecordingSurface', 'SvgSurface', 'ToyFontFace', 'RectangleList',
 
69
   'SolidPattern', 'SurfacePattern', 'GradientPattern', 'LinearPattern',
 
70
   'RadialPattern',
 
71
   MeshPattern = cairo.version_encode(1, 12, 0),
60
72
} do
61
 
   local lower = struct:gsub('([%l%d])([%u])', '%1_%2'):lower()
62
 
   local gtype = ffi.load_gtype(
63
 
      module_gobject, 'cairo_gobject_' .. lower .. '_get_type')
64
 
   local obj = component.create(gtype, record.struct_mt, 'cairo.' .. struct)
65
 
   cairo._struct[struct] = obj
 
73
   local since = 0
 
74
   if type(index) == 'string' then
 
75
      since = struct
 
76
      struct = index
 
77
   end
 
78
   if cairo.version >= since then
 
79
      local lower = struct:gsub('([%l%d])([%u])', '%1_%2'):lower()
 
80
      local gtype = ffi.load_gtype(
 
81
         module_gobject, 'cairo_gobject_' .. lower .. '_get_type')
 
82
      local obj = component.create(gtype, record.struct_mt, 'cairo.' .. struct)
 
83
      cairo._struct[struct] = obj
 
84
   end
66
85
end
67
86
 
68
87
local path_data_header = component.create(nil, record.struct_mt)
142
161
      },
143
162
   },
144
163
 
 
164
   {  'FontExtents',
 
165
      fields = {
 
166
         { 'ascent', ti.double },
 
167
         { 'descent', ti.double },
 
168
         { 'height', ti.double },
 
169
         { 'max_x_advance', ti.double },
 
170
         { 'max_y_advance', ti.double },
 
171
      },
 
172
   },
 
173
 
 
174
   {  'TextExtents',
 
175
      fields = {
 
176
         { 'x_bearing', ti.double },
 
177
         { 'y_bearing', ti.double },
 
178
         { 'width', ti.double },
 
179
         { 'height', ti.double },
 
180
         { 'x_advance', ti.double },
 
181
         { 'y_advance', ti.double },
 
182
      },
 
183
   },
 
184
 
145
185
   {  'Context',
 
186
      cprefix = '',
146
187
      methods = {
147
188
         create = { static = true, ret = { cairo.Context, xfer = true },
148
189
                    cairo.Surface },
152
193
         get_target = { ret = cairo.Surface},
153
194
         push_group = {},
154
195
         push_group_with_content = { cairo.Content },
155
 
         pop_group = {},
 
196
         pop_group = { ret = { cairo.Pattern, xfer = true } },
156
197
         pop_group_to_source = {},
157
198
         get_group_target = { ret = cairo.Surface },
158
199
         set_source_rgb = { ti.double, ti.double, ti.double },
183
224
                          { ti.double, dir = 'out' },
184
225
                          { ti.double, dir = 'out' },
185
226
                          { ti.double, dir = 'out' } },
186
 
         in_clip = { ret = ti.boolean },
 
227
         in_clip = { ret = ti.boolean, ti.double, ti.double },
187
228
         reset_clip = {},
188
229
         copy_clip_rectangle_list = {
189
230
            ret = { cairo.RectangleList, xfer = true } },
193
234
                          { ti.double, dir = 'out' },
194
235
                          { ti.double, dir = 'out' },
195
236
                          { ti.double, dir = 'out' } },
196
 
         in_fill = { ti.double, ti.double },
 
237
         in_fill = { ret = ti.boolean, ti.double, ti.double },
197
238
         mask = { cairo.Pattern },
198
239
         mask_surface = { cairo.Pattern, ti.double, ti.double },
199
240
         paint = {},
204
245
                            { ti.double, dir = 'out' },
205
246
                            { ti.double, dir = 'out' },
206
247
                            { ti.double, dir = 'out' } },
207
 
         in_stroke = { ti.double, ti.double },
 
248
         in_stroke = { ret = ti.boolean, ti.double, ti.double },
208
249
         copy_page = {},
209
250
         show_page = {},
210
251
 
278
319
 
279
320
   {  'Pattern',
280
321
      methods = {
 
322
         status = { ret = cairo.Status },
 
323
         set_extend = { cairo.Extend },
 
324
         get_extend = { ret = cairo.Extend },
 
325
         set_filter = { cairo.Filter },
 
326
         get_filter = { ret = cairo.Filter },
 
327
         set_matrix = { cairo.Matrix },
 
328
         get_matrix = { cairo.Matrix },
 
329
         get_type = { ret = cairo.PatternType },
 
330
      },
 
331
      properties = { 'status', 'extend', 'filter', 'type' },
 
332
   },
 
333
 
 
334
   {  'SolidPattern', parent = cairo.Pattern,
 
335
      cprefix = 'pattern_',
 
336
      methods = {
 
337
         create_rgb = { static = true, ret = { cairo.Pattern, xfer = true },
 
338
                        ti.double, ti.double, ti.double },
 
339
         create_rgba = { static = true, ret = { cairo.Pattern, xfer = true },
 
340
                         ti.double, ti.double, ti.double, ti.double },
 
341
         get_rgba = { ret = cairo.Status,
 
342
                      { ti.double, dir = 'out' },
 
343
                      { ti.double, dir = 'out' },
 
344
                      { ti.double, dir = 'out' },
 
345
                      { ti.double, dir = 'out' } },
 
346
      },
 
347
   },
 
348
 
 
349
   {  'SurfacePattern', parent = cairo.Pattern,
 
350
      cprefix = 'pattern_',
 
351
      methods = {
 
352
         create = {
 
353
            cname = 'cairo_pattern_create_for_surface', static = true,
 
354
            ret = { cairo.Pattern, xfer = true },
 
355
            cairo.Surface },
 
356
         get_surface = { ret = cairo.Status, { cairo.Surface, dir = 'out' } },
 
357
      },
 
358
   },
 
359
 
 
360
   {  'GradientPattern', parent = cairo.Pattern,
 
361
      cprefix = 'pattern_',
 
362
      methods = {
281
363
         add_color_stop_rgb = { ti.double, ti.double, ti.double, ti.double },
282
364
         add_color_stop_rgba = { ti.double, ti.double, ti.double,
283
365
                                 ti.double, ti.double },
288
370
                                 { ti.double, dir = 'out' },
289
371
                                 { ti.double, dir = 'out' },
290
372
                                 { ti.double, dir = 'out' } },
291
 
         create_rgb = { static = true, ret = { cairo.Pattern, xfer = true },
292
 
                        ti.double, ti.double, ti.double },
293
 
         create_rgba = { static = true, ret = { cairo.Pattern, xfer = true },
294
 
                         ti.double, ti.double, ti.double, ti.double },
295
 
         get_rgba = { ret = cairo.Status, { ti.double, dir = 'out' },
296
 
                      { ti.double, dir = 'out' }, { ti.double, dir = 'out' } },
297
 
         create_for_surface = { static = true,
298
 
                                ret = { cairo.Pattern, xfer = true },
299
 
                                cairo.Surface },
300
 
         get_surface = { ret = cairo.Status, { cairo.Surface, dir = 'out' } },
301
 
         create_linear = { static = true, ret = { cairo.Pattern, xfer = true },
302
 
                           ti.double, ti.double, ti.double, ti.double },
303
 
         get_linear_points = { ret = cairo.Status, ti.int,
 
373
      },
 
374
   },
 
375
 
 
376
   {  'LinearPattern', parent = cairo.GradientPattern,
 
377
      cprefix = 'pattern_',
 
378
      methods = {
 
379
         create = { cname = 'cairo_pattern_create_linear', static = true,
 
380
                    ret = { cairo.Pattern, xfer = true },
 
381
                    ti.double, ti.double, ti.double, ti.double },
 
382
         get_linear_points = { ret = cairo.Status,
304
383
                               { ti.double, dir = 'out' },
305
384
                               { ti.double, dir = 'out' },
306
385
                               { ti.double, dir = 'out' },
307
386
                               { ti.double, dir = 'out' } },
308
 
         create_radial = { static = true, ret = { cairo.Pattern, xfer = true },
309
 
                           ti.double, ti.double, ti.double, ti.double,
310
 
                           ti.double, ti.double },
311
 
         get_radial_circles = { ret = cairo.Status, ti.int,
 
387
      }
 
388
   },
 
389
 
 
390
   {  'RadialPattern', parent = cairo.GradientPattern,
 
391
      cprefix = 'pattern_',
 
392
      methods = {
 
393
         create = { cname = 'cairo_pattern_create_radial', static = true,
 
394
                    ret = { cairo.Pattern, xfer = true },
 
395
                    ti.double, ti.double, ti.double, ti.double,
 
396
                    ti.double, ti.double },
 
397
         get_radial_circles = { ret = cairo.Status,
312
398
                                { ti.double, dir = 'out' },
313
399
                                { ti.double, dir = 'out' },
314
400
                                { ti.double, dir = 'out' },
315
401
                                { ti.double, dir = 'out' },
316
402
                                { ti.double, dir = 'out' },
317
403
                                { ti.double, dir = 'out' } },
318
 
         status = { ret = cairo.Status },
319
 
         set_extend = { cairo.Extend },
320
 
         get_extend = { ret = cairo.Extend },
321
 
         set_filter = { cairo.Filter },
322
 
         get_filter = { ret = cairo.Filter },
323
 
         set_matrix = { cairo.Matrix },
324
 
         get_matrix = { cairo.Matrix },
325
 
         get_type = { ret = cairo.PatternType },
326
 
      },
327
 
      properties = { 'status', 'extend', 'filter', 'type' },
 
404
      },
 
405
   },
 
406
 
 
407
   {  'MeshPattern', parent = cairo.Pattern,
 
408
      since = cairo.version_encode(1, 12, 0),
 
409
      methods = {
 
410
         create = { cname = 'cairo_pattern_create_mesh', static = true,
 
411
                    ret = { cairo.Pattern, xfer = true } },
 
412
         begin_patch = {},
 
413
         end_patch = {},
 
414
         move_to = { ti.double, ti.double },
 
415
         line_to = { ti.double, ti.double },
 
416
         curve_to = { ti.double, ti.double, ti.double, ti.double,
 
417
                      ti.double, ti.double },
 
418
         set_control_point = { ti.int, ti.double, ti.double },
 
419
         set_corner_color_rgb = { ti.int, ti.double, ti.double, ti.double },
 
420
         set_corner_color_rgba = { ti.int, ti.double, ti.double, ti.double,
 
421
                                   ti.double },
 
422
         get_patch_count = { ret = cairo.Status, { ti.int, dir = 'out' } },
 
423
         get_path = { ret = { cairo.Path, xfer = true }, ti.int },
 
424
         get_control_point = { ret = cairo.Status, ti.int, ti.int,
 
425
                               { ti.double, dir = 'out' },
 
426
                               { ti.double, dir = 'out' },
 
427
                               { ti.double, dir = 'out' } },
 
428
         get_corner_color_rgba = { ret = cairo.Status, ti.int, ti.int,
 
429
                                   { ti.double, dir = 'out' },
 
430
                                   { ti.double, dir = 'out' },
 
431
                                   { ti.double, dir = 'out' },
 
432
                                   { ti.double, dir = 'out' } },
 
433
      },
328
434
   },
329
435
 
330
436
   {  'Device',
341
447
 
342
448
   {  'Format',
343
449
      methods = {
344
 
         stride_for_width = { ret = ti.int, cairo.Format },
 
450
         stride_for_width = { ret = ti.int, ti.int },
345
451
      },
346
452
   },
347
453
 
436
542
   {  'RecordingSurface', parent = cairo.Surface,
437
543
      methods = {
438
544
         create = { static = true, ret = { cairo.Surface, xfer = true },
439
 
                    cairo.Content },
 
545
                    cairo.Content, cairo.Rectangle },
440
546
         ink_extents = {
441
547
            { ti.double, dir = 'out' }, { ti.double, dir = 'out' },
442
548
            { ti.double, dir = 'out' }, { ti.double, dir = 'out' } },
 
549
         get_extents = { since = cairo.version_encode(1, 12, 0),
 
550
                         ret = ti.boolean, cairo.Rectangle },
443
551
      },
444
552
   },
445
553
 
469
577
   {  'ToyFontFace', parent = cairo.FontFace,
470
578
      methods = {
471
579
         create = { static = true, ret = { cairo.ToyFontFace, xfer = true },
472
 
                    cairo.FontSlant, cairo.FontWeight },
 
580
                    ti.utf8, cairo.FontSlant, cairo.FontWeight },
473
581
         get_family = { ret = ti.utf8 },
474
582
         get_slant = { ret = cairo.Slant },
475
583
         get_weight = { ret = cairo.Weight },
545
653
      properties = { 'status', 'extents', },
546
654
   },
547
655
} do
548
 
   local name = info[1]
549
 
   local obj = assert(cairo[name])
550
 
   obj._parent = info.parent
551
 
   if info.methods then
552
 
      -- Go through description of the methods and create functions
553
 
      -- from them.
554
 
      obj._method = {}
555
 
      local prefix = 'cairo_'
556
 
      if name ~= 'Context' then
557
 
         prefix = prefix .. name:gsub('([%l%d])([%u])', '%1_%2'):lower() .. '_'
558
 
      end
559
 
      local self_arg = { obj }
560
 
      for method_name, method_info in pairs(info.methods) do
561
 
         method_info.name = 'cairo.' .. name .. '.' .. method_name
562
 
         method_info.addr = cairo._module[
563
 
            prefix .. (method_info.cname or method_name)]
564
 
         if not method_info.static then
565
 
            table.insert(method_info, 1, self_arg)
566
 
         end
567
 
         method_info.ret = method_info.ret or ti.void
568
 
         obj._method[method_name] = core.callable.new(method_info)
569
 
      end
570
 
   end
571
 
   if info.values then
572
 
      -- Fill in addition enum/bitflag values.
573
 
      for n, v in pairs(info.values) do
574
 
         obj[n] = v
575
 
      end
576
 
   end
577
 
   if info.properties then
578
 
      -- Aggregate getters/setters into pseudoproperties implemented
579
 
      -- as attributes.
580
 
      obj._attribute = {}
581
 
      for _, attr in pairs(info.properties) do
582
 
         obj._attribute[attr] = {
583
 
            get = obj._method['get_' .. attr] or obj._method[attr],
584
 
            set = obj._method['set_' .. attr],
585
 
         }
586
 
      end
587
 
   end
588
 
   if info.fields then
589
 
      -- Load record fields definition
590
 
      ffi.load_fields(obj, info.fields)
591
 
   end
592
 
end
593
 
 
594
 
for _, struct in pairs(cairo._struct) do
595
 
   local create = struct._method and struct._method.create
596
 
   if create then
597
 
      function struct._new(typetable, ...)
598
 
         return create(...)
 
656
   if cairo.version >= (info.since or 0) then
 
657
      local name = info[1]
 
658
      local obj = assert(cairo[name], name)
 
659
      obj._parent = info.parent
 
660
      if info.methods then
 
661
         -- Go through description of the methods and create functions
 
662
         -- from them.
 
663
         obj._method = {}
 
664
         local cprefix = 'cairo_' ..
 
665
            (info.cprefix or
 
666
             name:gsub('([%l%d])([%u])', '%1_%2'):lower() .. '_')
 
667
         local self_arg = { obj }
 
668
         for method_name, method_info in pairs(info.methods) do
 
669
            if cairo.version >= (method_info.since or 0) then
 
670
               method_info.name = 'cairo.' .. name .. '.' .. method_name
 
671
               method_info.addr = assert(
 
672
                  cairo._module[
 
673
                     method_info.cname or (cprefix .. method_name)])
 
674
               if not method_info.static then
 
675
                  table.insert(method_info, 1, self_arg)
 
676
               end
 
677
               method_info.ret = method_info.ret or ti.void
 
678
               obj._method[method_name] = core.callable.new(method_info)
 
679
            end
 
680
         end
 
681
      end
 
682
      if info.values then
 
683
         -- Fill in addition enum/bitflag values.
 
684
         for n, v in pairs(info.values) do
 
685
            obj[n] = v
 
686
         end
 
687
      end
 
688
      if info.properties then
 
689
         -- Aggregate getters/setters into pseudoproperties
 
690
         -- implemented as attributes.
 
691
         obj._attribute = {}
 
692
         for _, attr in pairs(info.properties) do
 
693
            obj._attribute[attr] = {
 
694
               get = obj._method['get_' .. attr] or obj._method[attr],
 
695
               set = obj._method['set_' .. attr],
 
696
            }
 
697
         end
 
698
      end
 
699
      if info.fields then
 
700
         -- Load record fields definition
 
701
         ffi.load_fields(obj, info.fields)
599
702
      end
600
703
   end
601
704
end
625
727
   return font_options
626
728
end
627
729
 
 
730
-- Fix all methods using caller-alloc attribute, which is not
 
731
-- supported by ffi.  Emulate it 'by-hand', creating Lua wrapper for
 
732
-- them.
628
733
for _, info in pairs {
629
734
   { cairo.Context, 'matrix', cairo.Matrix },
630
735
   { cairo.Context, 'font_matrix', cairo.Matrix },
631
736
   { cairo.Context, 'font_options', cairo.FontOptions },
 
737
   { cairo.Context, 'font_extents', cairo.FontExtents },
 
738
   { cairo.Context, 'text_extents', cairo.TextExtents, args = 1 },
632
739
   { cairo.Pattern, 'matrix', cairo.Matrix },
633
740
   { cairo.Surface, 'font_options', cairo.FontOptions },
634
741
   { cairo.ScaledFont, 'font_matrix', cairo.Matrix },
635
742
   { cairo.ScaledFont, 'ctm', cairo.Matrix },
636
743
   { cairo.ScaledFont, 'scale_matrix', cairo.Matrix },
637
744
   { cairo.ScaledFont, 'font_options', cairo.FontOptions },
 
745
   { cairo.ScaledFont, 'extents', cairo.FontExtents },
 
746
   { cairo.ScaledFont, 'text_extents', cairo.TextExtents, args = 1 },
 
747
   { cairo.RecordingSurface, 'extents', cairo.Rectangle },
 
748
   { cairo.Region, 'extents', cairo.RectangleInt },
 
749
   { cairo.Region, 'get_rectangle', cairo.RectangleInt, args = 1 },
638
750
} do
639
751
   local getter_name = 'get_' ..info[2]
640
 
   local raw_getter = assert(info[1]._method[getter_name])
641
 
   info[1]._method[getter_name] = function(self)
642
 
      local ret = info[3]()
643
 
      raw_getter(self, ret)
644
 
      return ret
645
 
   end
646
 
   info[1]._attribute[info[2]] = {
647
 
      get = info[1][getter_name],
648
 
      set = info[1]['set_' .. info[2]],
649
 
   }
 
752
   local raw_getter = info[1]._method[getter_name]
 
753
   if not raw_getter then
 
754
      getter_name = info[2]
 
755
      raw_getter = info[1]._method[getter_name]
 
756
   end
 
757
   if raw_getter then
 
758
      if info.args == 1 then
 
759
         info[1]._method[getter_name] = function(self, arg1)
 
760
            local ret = info[3]()
 
761
            local res = raw_getter(self, arg1, ret)
 
762
            return (res == nil or res) and ret or nil
 
763
         end
 
764
      else
 
765
         info[1]._method[getter_name] = function(self)
 
766
            local ret = info[3]()
 
767
            local res = raw_getter(self, ret)
 
768
            return (res == nil or res) and ret or nil
 
769
         end
 
770
         info[1]._attribute[info[2]] = {
 
771
            get = info[1][getter_name],
 
772
            set = info[1]['set_' .. info[2]],
 
773
         }
 
774
      end
 
775
   end
650
776
end
651
777
 
652
778
-- Choose correct 'subclass' of surface on attaching to surface instances.
667
791
   end
668
792
end
669
793
 
 
794
-- Also choose correct 'subclass' for patterns.
 
795
local pattern_type_map = {
 
796
   SOLID = cairo.SolidPattern,
 
797
   SURFACE = cairo.SurfacePattern,
 
798
   LINEAR = cairo.LinearPattern,
 
799
   RADIAL = cairo.RadialPattern,
 
800
   MESH = cairo.MeshPattern
 
801
}
 
802
function cairo.Pattern:_attach(pattern)
 
803
   local type = cairo.Pattern._method.get_type(pattern)
 
804
   local repotype = pattern_type_map[type]
 
805
   if repotype then
 
806
      core.record.set(pattern, repotype)
 
807
   end
 
808
end
 
809
 
 
810
-- Solid pattern constructor, calling either rgb or rgba variant
 
811
-- according to the number of arguments.
 
812
function cairo.SolidPattern._method.create(red, green, blue, alpha)
 
813
   if alpha then
 
814
      return cairo.SolidPattern._method.create_rgba(red, green, blue, alpha)
 
815
   else
 
816
      return cairo.SolidPattern._method.create_rgb(red, green, blue)
 
817
   end
 
818
end
 
819
 
 
820
-- For backward compatibility, propagate pattern creation methods from
 
821
-- specific subpattern types into base cairo.Pattern class.
 
822
cairo.Pattern._method.create_rgb = cairo.SolidPattern.create_rgb
 
823
cairo.Pattern._method.create_rgba = cairo.SolidPattern.create_rgba
 
824
cairo.Pattern._method.create_for_surface = cairo.SurfacePattern.create
 
825
cairo.Pattern._method.create_linear = cairo.LinearPattern.create
 
826
cairo.Pattern._method.create_radial = cairo.RadialPattern.create
 
827
if cairo.MeshPattern then
 
828
   cairo.Pattern._method.create_mesh = cairo.MeshPattern.create
 
829
end
 
830
 
 
831
-- Map all 'create' methods to constructors.
 
832
for _, struct in pairs(cairo._struct) do
 
833
   local create = struct._method and struct._method.create
 
834
   if create then
 
835
      function struct._new(typetable, ...)
 
836
         return create(...)
 
837
      end
 
838
   end
 
839
end
 
840
 
670
841
-- Implementation of Context.dash operations.  Since ffi does not
671
842
-- support arrays of doubles, we cheat here and use array of structs
672
843
-- containing only single 'double' field.