summaryrefslogtreecommitdiff
path: root/src/lib/ector/cairo/ector_cairo_surface.c
blob: 93336db508884158c45eb4c61552d6b937403c6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <Eina.h>
#include <Ector.h>
#include <cairo/Ector_Cairo.h>

#include "ector_private.h"
#include "ector_cairo_private.h"

static unsigned int _cairo_count = 0;
static Eina_Module *_cairo_so = NULL;

static void *
_ector_cairo_surface_symbol_get(Eo *obj EINA_UNUSED,
                                Ector_Cairo_Surface_Data *pd EINA_UNUSED,
                                const char *name)
{
   if (!_cairo_so)
     {
#define LOAD(x)                                 \
        if (!_cairo_so)                         \
          {                                     \
             _cairo_so = eina_module_new(x);    \
             if (_cairo_so &&                   \
                 !eina_module_load(_cairo_so))  \
               {                                \
                  eina_module_free(_cairo_so);  \
                  _cairo_so = NULL;             \
               }                                \
          }
#if defined(_WIN32) || defined(__CYGWIN__)
        LOAD("libcairo.dll");
#elif defined(__APPLE__) && defined(__MACH__)
        LOAD("libcairo.dylib");
        LOAD("libcairo.so");
#else
        LOAD("libcairo.so");
#endif

#undef LOAD
     }

   if (!_cairo_so)
     {
        ERR("Couldn't find cairo library. Please make sure that your system can locate it.");
        return NULL;
     }

   return eina_module_symbol_get(_cairo_so, name);
}

#undef USE
#define USE(Obj, Sym, Error)                                            \
  if (!Sym) Sym = _ector_cairo_surface_symbol_get(Obj, NULL, #Sym);     \
  if (!Sym) return Error;

static Ector_Renderer *
_ector_cairo_surface_ector_generic_surface_renderer_factory_new(Eo *obj,
                                                                Ector_Cairo_Surface_Data *pd EINA_UNUSED,
                                                                const Eo_Class *type)
{
   Eo *ret = NULL;
   if (type == ECTOR_RENDERER_GENERIC_SHAPE_MIXIN)
     return eo_add(&ret, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, NULL, ector_renderer_surface_set(ret, obj));
   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN)
     return eo_add(&ret, ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS, NULL, ector_renderer_surface_set(ret, obj));
   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN)
     return eo_add(&ret, ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS, NULL, ector_renderer_surface_set(ret, obj));

   ERR("Couldn't find class for type: %s\n", eo_class_name_get(type));
   return NULL;
}

typedef struct _cairo_surface_t cairo_surface_t;

static void (*cairo_destroy)(cairo_t *cr) = NULL;
static cairo_surface_t *(*cairo_image_surface_create)(int format,
                                                      int width,
                                                      int height) = NULL;
static cairo_t *(*cairo_create)(cairo_surface_t *target) = NULL;

static cairo_surface_t *internal = NULL;

static void
_ector_cairo_surface_context_set(Eo *obj EINA_UNUSED,
                                 Ector_Cairo_Surface_Data *pd,
                                 cairo_t *ctx)
{
   if (pd->cairo) cairo_destroy(pd->cairo);
   if (!ctx)
     {
        if (!internal) internal = cairo_image_surface_create(0, 1, 1);
        ctx = cairo_create(internal);
     }
   pd->current.x = pd->current.y = 0;
   pd->cairo = ctx;
}

static cairo_t *
_ector_cairo_surface_context_get(Eo *obj EINA_UNUSED,
                                 Ector_Cairo_Surface_Data *pd)
{
   return pd->cairo;
}

static void
_ector_cairo_surface_ector_generic_surface_reference_point_set(Eo *obj EINA_UNUSED,
                                                               Ector_Cairo_Surface_Data *pd,
                                                               int x, int y)
{
   pd->current.x = x;
   pd->current.y = y;
}

static Eo *
_ector_cairo_surface_eo_base_constructor(Eo *obj,
                                         Ector_Cairo_Surface_Data *pd)
{
   USE(obj, cairo_destroy, NULL);
   USE(obj, cairo_image_surface_create, NULL);
   USE(obj, cairo_create, NULL);

   obj = eo_constructor(eo_super(obj, ECTOR_CAIRO_SURFACE_CLASS));
   if (!obj) return NULL;

   _cairo_count++;

   _ector_cairo_surface_context_set(obj, pd, NULL);

   return obj;
}

static void
_ector_cairo_surface_eo_base_destructor(Eo *obj EINA_UNUSED,
                                        Ector_Cairo_Surface_Data *pd EINA_UNUSED)
{
   eo_destructor(eo_super(obj, ECTOR_CAIRO_SURFACE_CLASS));

   if (--_cairo_count) return ;
   if (_cairo_so) eina_module_free(_cairo_so);
   _cairo_so = NULL;
}

#include "ector_cairo_surface.eo.c"