Commit 780fb572 authored by Barak Itkin's avatar Barak Itkin
Browse files

Rename the exported seamless cloning api (Begin with GeglSc, not just Sc)

parent 44c58ff8
......@@ -29,39 +29,39 @@
* ALPHA CHANNEL IS ALWAYS LAST. DO NOT CHANGE THIS WITHOUT UPDATING
* THE REST OF THE CODE!
*/
#define SC_COLOR_BABL_NAME "R'G'B'A float"
#define GEGL_SC_COLOR_BABL_NAME "R'G'B'A float"
/**
* The type used for individual color channels. Note that this should
* never be used directly - you must get a pointer to this type using
* the allocation macros below!
*/
typedef gfloat ScColor;
typedef gfloat GeglScColor;
/**
* The amount of channels per color
*/
#define SC_COLORA_CHANNEL_COUNT 4
#define SC_COLOR_CHANNEL_COUNT ((SC_COLORA_CHANNEL_COUNT) - 1)
#define GEGL_SC_COLORA_CHANNEL_COUNT 4
#define GEGL_SC_COLOR_CHANNEL_COUNT ((GEGL_SC_COLORA_CHANNEL_COUNT) - 1)
#define sc_color_new() (g_new (ScColor, SC_COLORA_CHANNEL_COUNT))
#define sc_color_free(mem) (g_free (mem))
#define gegl_sc_color_new() (g_new (GeglScColor, GEGL_SC_COLORA_CHANNEL_COUNT))
#define gegl_sc_color_free(mem) (g_free (mem))
/**
* The index of the alpha channel in the color
*/
#define SC_COLOR_ALPHA_INDEX SC_COLOR_CHANNEL_COUNT
#define GEGL_SC_COLOR_ALPHA_INDEX GEGL_SC_COLOR_CHANNEL_COUNT
/**
* Apply a macro once for each non-alpha color channel, with the
* channel index as an input
*/
#define sc_color_process() \
G_STMT_START \
{ \
sc_color_expr(0); \
sc_color_expr(1); \
sc_color_expr(2); \
} \
#define gegl_sc_color_process() \
G_STMT_START \
{ \
gegl_sc_color_expr(0); \
gegl_sc_color_expr(1); \
gegl_sc_color_expr(2); \
} \
G_STMT_END
typedef struct {
......@@ -75,9 +75,9 @@ typedef struct {
gint yoff;
gboolean render_bg;
} ScRenderInfo;
} GeglScRenderInfo;
#define sc_point_in_rectangle(px, py, rect) \
#define gegl_sc_point_in_rectangle(px, py, rect) \
( ((px) >= (rect)->x) \
&& ((py) >= (rect)->y) \
&& ((px) < (rect)->x + (rect)->width) \
......
......@@ -29,25 +29,25 @@
typedef struct
{
GHashTable *pt2col;
gboolean is_valid;
} ScRenderCache;
GHashTable *pt2col;
gboolean is_valid;
} GeglScRenderCache;
struct _ScContext
struct _GeglScContext
{
ScOutline *outline;
GeglRectangle mesh_bounds;
P2trMesh *mesh;
GeglScOutline *outline;
GeglRectangle mesh_bounds;
P2trMesh *mesh;
ScMeshSampling *sampling;
GeglScMeshSampling *sampling;
gboolean cache_uvt;
GeglBuffer *uvt;
gboolean cache_uvt;
GeglBuffer *uvt;
ScRenderCache *render_cache;
GeglScRenderCache *render_cache;
};
#define SC_BABL_UVT_TYPE (babl_type_new ("uvt", "bits", sizeof (P2trUVT) * 8, NULL))
#define SC_BABL_UVT_FORMAT (babl_format_n (SC_BABL_UVT_TYPE, 1))
#define GEGL_SC_BABL_UVT_TYPE (babl_type_new ("uvt", "bits", sizeof (P2trUVT) * 8, NULL))
#define GEGL_SC_BABL_UVT_FORMAT (babl_format_n (GEGL_SC_BABL_UVT_TYPE, 1))
#endif
......@@ -30,7 +30,7 @@
* An opaque type representing the context for a seamless cloning
* operation
*/
typedef struct _ScContext ScContext;
typedef struct _GeglScContext GeglScContext;
/**
* Errors generated during the creation of a seamless cloning context
......@@ -39,36 +39,36 @@ typedef enum {
/**
* No error
*/
SC_CREATION_ERROR_NONE = 0,
GEGL_SC_CREATION_ERROR_NONE = 0,
/**
* The input doesn't contain an opaque area
*/
SC_CREATION_ERROR_EMPTY,
GEGL_SC_CREATION_ERROR_EMPTY,
/**
*The opaque area of the input is too small
*/
SC_CREATION_ERROR_TOO_SMALL,
GEGL_SC_CREATION_ERROR_TOO_SMALL,
/**
* The opaque area of the input either contains holes or is split
* to several disconnected areas
*/
SC_CREATION_ERROR_HOLED_OR_SPLIT
} ScCreationError;
GEGL_SC_CREATION_ERROR_HOLED_OR_SPLIT
} GeglScCreationError;
/**
* Create a new seamless cloning context where the alpha of the
* given input buffer will be used to determine its outline.
*/
ScContext* sc_context_new (GeglBuffer *input,
const GeglRectangle *roi,
gdouble threshold,
ScCreationError *error);
GeglScContext* gegl_sc_context_new (GeglBuffer *input,
const GeglRectangle *roi,
gdouble threshold,
GeglScCreationError *error);
gboolean sc_context_update (ScContext *self,
GeglBuffer *input,
const GeglRectangle *roi,
gdouble threshold,
ScCreationError *error);
gboolean gegl_sc_context_update (GeglScContext *self,
GeglBuffer *input,
const GeglRectangle *roi,
gdouble threshold,
GeglScCreationError *error);
/**
* Do the necessary caching so that rendering can happen. This function
......@@ -79,8 +79,8 @@ gboolean sc_context_update (ScContext *self,
* BEHAVIOUR IS THAT THE FOREGROUND DOES NOT OVERLAP ENOUGH THE
* BACKGROUND!
*/
gboolean sc_context_prepare_render (ScContext *context,
ScRenderInfo *info);
gboolean gegl_sc_context_prepare_render (GeglScContext *context,
GeglScRenderInfo *info);
/**
* Specifies whether the triangle containing each pixel, along with the
......@@ -89,19 +89,19 @@ gboolean sc_context_prepare_render (ScContext *context,
* render the result faster.
* This function takes effect from the next call to prepare_render.
*/
void sc_context_set_uvt_cache (ScContext *context,
gboolean enabled);
void gegl_sc_context_set_uvt_cache (GeglScContext *context,
gboolean enabled);
/**
* Call this function to render the specified area of the seamless
* cloning composition. This call must be preceeded by a call to
* the prepare function.
*/
gboolean sc_context_render (ScContext *context,
ScRenderInfo *info,
const GeglRectangle *part_rect,
GeglBuffer *part);
gboolean gegl_sc_context_render (GeglScContext *context,
GeglScRenderInfo *info,
const GeglRectangle *part_rect,
GeglBuffer *part);
void sc_context_free (ScContext *context);
void gegl_sc_context_free (GeglScContext *context);
#endif
......@@ -44,35 +44,35 @@
#include "sc-common.h"
static inline void
sc_point_copy_to (const ScPoint *src,
ScPoint *dst)
gegl_sc_point_copy_to (const GeglScPoint *src,
GeglScPoint *dst)
{
dst->x = src->x;
dst->y = src->y;
dst->outside_normal = src->outside_normal;
}
static inline ScPoint*
sc_point_copy (const ScPoint *src)
static inline GeglScPoint*
gegl_sc_point_copy (const GeglScPoint *src)
{
ScPoint *self = g_slice_new (ScPoint);
sc_point_copy_to (src, self);
GeglScPoint *self = g_slice_new (GeglScPoint);
gegl_sc_point_copy_to (src, self);
return self;
}
static inline ScPoint*
sc_point_move (const ScPoint *src,
ScDirection t,
ScPoint *dst)
static inline GeglScPoint*
gegl_sc_point_move (const GeglScPoint *src,
GeglScDirection t,
GeglScPoint *dst)
{
dst->x = src->x + SC_DIRECTION_XOFFSET (t, 1);
dst->y = src->y + SC_DIRECTION_YOFFSET (t, 1);
dst->x = src->x + GEGL_SC_DIRECTION_XOFFSET (t, 1);
dst->y = src->y + GEGL_SC_DIRECTION_YOFFSET (t, 1);
return dst;
}
static inline gboolean
sc_point_eq (const ScPoint *pt1,
const ScPoint *pt2)
gegl_sc_point_eq (const GeglScPoint *pt1,
const GeglScPoint *pt2)
{
return pt1->x == pt2->x && pt1->y == pt2->y;
}
......@@ -82,17 +82,17 @@ is_opaque (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *pt)
const GeglScPoint *pt)
{
ScColor col[SC_COLORA_CHANNEL_COUNT];
GeglScColor col[GEGL_SC_COLORA_CHANNEL_COUNT];
if (! sc_point_in_rectangle (pt->x, pt->y, search_area))
if (! gegl_sc_point_in_rectangle (pt->x, pt->y, search_area))
return FALSE;
gegl_buffer_sample (buffer, pt->x, pt->y, NULL, col, format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
return col[SC_COLOR_ALPHA_INDEX] >= threshold;
return col[GEGL_SC_COLOR_ALPHA_INDEX] >= threshold;
}
/* This function assumes the pixel is opaque! */
......@@ -101,13 +101,13 @@ is_opaque_island (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *pt)
const GeglScPoint *pt)
{
gint i;
ScPoint temp;
GeglScPoint temp;
for (i = 0; i < 8; ++i)
if (is_opaque (search_area, buffer, format, threshold, sc_point_move (pt, i, &temp)))
if (is_opaque (search_area, buffer, format, threshold, gegl_sc_point_move (pt, i, &temp)))
return FALSE;
return TRUE;
......@@ -120,16 +120,16 @@ is_valid_edge (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *pt)
const GeglScPoint *pt)
{
gint i;
ScPoint temp;
GeglScPoint temp;
if (! is_opaque (search_area, buffer, format, threshold, pt))
return FALSE;
for (i = 0; i < SC_DIRECTION_COUNT; ++i)
if (is_opaque (search_area, buffer, format, threshold, sc_point_move (pt, i, &temp)))
for (i = 0; i < GEGL_SC_DIRECTION_COUNT; ++i)
if (is_opaque (search_area, buffer, format, threshold, gegl_sc_point_move (pt, i, &temp)))
return FALSE;
return TRUE;
......@@ -150,24 +150,24 @@ is_valid_edge (const GeglRectangle *search_area,
* untill you find an opaque pixel. That pixel must then be the next
* edge pixel (when going in clock-wise direction)!
*/
static inline ScDirection
static inline GeglScDirection
walk_cw (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *cur_pt,
ScDirection dir_from_prev,
ScPoint *next_pt)
const GeglScPoint *cur_pt,
GeglScDirection dir_from_prev,
GeglScPoint *next_pt)
{
ScDirection dir_to_prev = SC_DIRECTION_OPPOSITE (dir_from_prev);
ScDirection dir_to_next = SC_DIRECTION_CW (dir_to_prev);
GeglScDirection dir_to_prev = GEGL_SC_DIRECTION_OPPOSITE (dir_from_prev);
GeglScDirection dir_to_next = GEGL_SC_DIRECTION_CW (dir_to_prev);
sc_point_move (cur_pt, dir_to_next, next_pt);
gegl_sc_point_move (cur_pt, dir_to_next, next_pt);
while (! is_opaque (search_area, buffer, format, threshold, next_pt))
{
dir_to_next = SC_DIRECTION_CW (dir_to_next);
sc_point_move (cur_pt, dir_to_next, next_pt);
dir_to_next = GEGL_SC_DIRECTION_CW (dir_to_next);
gegl_sc_point_move (cur_pt, dir_to_next, next_pt);
}
return dir_to_next;
......@@ -180,18 +180,18 @@ walk_cw (const GeglRectangle *search_area,
* the finds and returns the outline in which this edge pixel takes
* a part.
*/
ScOutline*
sc_outline_find (const GeglRectangle *search_area,
GeglBuffer *buffer,
gdouble threshold,
gboolean *ignored_islands)
GeglScOutline*
gegl_sc_outline_find (const GeglRectangle *search_area,
GeglBuffer *buffer,
gdouble threshold,
gboolean *ignored_islands)
{
const Babl *format = babl_format("RGBA float");
ScOutline *result = g_ptr_array_new ();
GeglScOutline *result = g_ptr_array_new ();
gboolean found = FALSE;
ScPoint current, next, *first;
ScDirection to_next;
GeglScPoint current, next, *first;
GeglScDirection to_next;
gint row_max = search_area->x + search_area->width;
gint col_max = search_area->y + search_area->height;
......@@ -219,17 +219,17 @@ sc_outline_find (const GeglRectangle *search_area,
if (found)
{
current.outside_normal = SC_DIRECTION_N;
g_ptr_array_add (result, first = sc_point_copy (&current));
current.outside_normal = GEGL_SC_DIRECTION_N;
g_ptr_array_add (result, first = gegl_sc_point_copy (&current));
to_next = walk_cw (search_area, buffer, format, threshold,
&current, SC_DIRECTION_E, &next);
&current, GEGL_SC_DIRECTION_E, &next);
while (! sc_point_eq (&next, first))
while (! gegl_sc_point_eq (&next, first))
{
next.outside_normal = SC_DIRECTION_CW(SC_DIRECTION_CW(to_next));
g_ptr_array_add (result, sc_point_copy (&next));
sc_point_copy_to (&next, &current);
next.outside_normal = GEGL_SC_DIRECTION_CW (GEGL_SC_DIRECTION_CW (to_next));
g_ptr_array_add (result, gegl_sc_point_copy (&next));
gegl_sc_point_copy_to (&next, &current);
to_next = walk_cw (search_area, buffer, format, threshold,
&current, to_next, &next);
}
......@@ -243,8 +243,8 @@ sc_outline_find (const GeglRectangle *search_area,
* increasing X values
*/
static gint
sc_point_cmp (const ScPoint **pt1,
const ScPoint **pt2)
gegl_sc_point_cmp (const GeglScPoint **pt1,
const GeglScPoint **pt2)
{
if ((*pt1)->y < (*pt2)->y)
return -1;
......@@ -280,16 +280,16 @@ sc_point_cmp (const ScPoint **pt1,
* (amortized) time!
*/
gboolean
sc_outline_check_if_single (const GeglRectangle *search_area,
GeglBuffer *buffer,
gdouble threshold,
ScOutline *existing)
gegl_sc_outline_check_if_single (const GeglRectangle *search_area,
GeglBuffer *buffer,
gdouble threshold,
GeglScOutline *existing)
{
const Babl *format = babl_format("RGBA float");
GPtrArray *sorted_points = g_ptr_array_sized_new (existing->len);
gboolean not_single = FALSE;
ScPoint current, *sorted_p;
GeglScPoint current, *sorted_p;
guint s_index;
gint row_max = search_area->x + search_area->width;
......@@ -297,10 +297,10 @@ sc_outline_check_if_single (const GeglRectangle *search_area,
for (s_index = 0; s_index < existing->len; ++s_index)
g_ptr_array_add (sorted_points, g_ptr_array_index (existing, s_index));
g_ptr_array_sort (sorted_points, (GCompareFunc) sc_point_cmp);
g_ptr_array_sort (sorted_points, (GCompareFunc) gegl_sc_point_cmp);
s_index = 0;
sorted_p = (ScPoint*) g_ptr_array_index (sorted_points, s_index);
sorted_p = (GeglScPoint*) g_ptr_array_index (sorted_points, s_index);
for (current.y = search_area->y; current.y < row_max; ++current.y)
{
......@@ -311,12 +311,12 @@ sc_outline_check_if_single (const GeglRectangle *search_area,
gboolean hit, opaque;
opaque = is_opaque (search_area, buffer, format, threshold, &current);
hit = sc_point_eq (&current, sorted_p);
hit = gegl_sc_point_eq (&current, sorted_p);
if (hit && ! inside)
{
inside = TRUE;
sorted_p = (ScPoint*) g_ptr_array_index (sorted_points, ++s_index);
sorted_p = (GeglScPoint*) g_ptr_array_index (sorted_points, ++s_index);
/* Prevent "leaving" the area in the next if statement */
hit = FALSE;
}
......@@ -331,7 +331,7 @@ sc_outline_check_if_single (const GeglRectangle *search_area,
if (hit && inside)
{
inside = FALSE;
sorted_p = (ScPoint*) g_ptr_array_index (sorted_points, ++s_index);
sorted_p = (GeglScPoint*) g_ptr_array_index (sorted_points, ++s_index);
}
}
......@@ -344,30 +344,30 @@ sc_outline_check_if_single (const GeglRectangle *search_area,
}
guint
sc_outline_length (ScOutline *self)
gegl_sc_outline_length (GeglScOutline *self)
{
return ((GPtrArray*) self)->len;
}
gboolean
sc_outline_equals (ScOutline *a,
ScOutline *b)
gegl_sc_outline_equals (GeglScOutline *a,
GeglScOutline *b)
{
if (a == b) /* Includes the case were both are NULL */
return TRUE;
else if ((a == NULL) != (b == NULL))
return FALSE;
else if (sc_outline_length (a) != sc_outline_length (b))
else if (gegl_sc_outline_length (a) != gegl_sc_outline_length (b))
return FALSE;
else
{
guint n = sc_outline_length (a);
guint n = gegl_sc_outline_length (a);
guint i;
for (i = 0; i < n; i++)
{
const ScPoint *pA = (ScPoint*) g_ptr_array_index (a, i);
const ScPoint *pB = (ScPoint*) g_ptr_array_index (b, i);
if (sc_point_cmp (&pA, &pB) != 0)
const GeglScPoint *pA = (GeglScPoint*) g_ptr_array_index (a, i);
const GeglScPoint *pB = (GeglScPoint*) g_ptr_array_index (b, i);
if (gegl_sc_point_cmp (&pA, &pB) != 0)
return FALSE;
}
return TRUE;
......@@ -375,11 +375,11 @@ sc_outline_equals (ScOutline *a,
}
void
sc_outline_free (ScOutline *self)
gegl_sc_outline_free (GeglScOutline *self)
{
GPtrArray *real = (GPtrArray*) self;
gint i;
for (i = 0; i < real->len; i++)
g_slice_free (ScPoint, g_ptr_array_index (self, i));
g_slice_free (GeglScPoint, g_ptr_array_index (self, i));
g_ptr_array_free (real, TRUE);
}
......@@ -39,55 +39,55 @@
* </pre>
*/
typedef enum {
SC_DIRECTION_N = 0,
SC_DIRECTION_NE = 1,
SC_DIRECTION_E = 2,
SC_DIRECTION_SE = 3,
SC_DIRECTION_S = 4,
SC_DIRECTION_SW = 5,
SC_DIRECTION_W = 6,
SC_DIRECTION_NW = 7,
SC_DIRECTION_COUNT = 8
} ScDirection;
#define SC_DIRECTION_CW(d) (((d) + 1) % 8)
#define SC_DIRECTION_CCW(d) (((d) + 7) % 8)
#define SC_DIRECTION_OPPOSITE(d) (((d) + 4) % 8)
#define SC_DIRECTION_IS_NORTH(d) ( \
((d) == SC_DIRECTION_N) || \
((d) == SC_DIRECTION_NE) || \
((d) == SC_DIRECTION_NW) \
GEGL_SC_DIRECTION_N = 0,
GEGL_SC_DIRECTION_NE = 1,
GEGL_SC_DIRECTION_E = 2,
GEGL_SC_DIRECTION_SE = 3,
GEGL_SC_DIRECTION_S = 4,
GEGL_SC_DIRECTION_SW = 5,
GEGL_SC_DIRECTION_W = 6,
GEGL_SC_DIRECTION_NW = 7,
GEGL_SC_DIRECTION_COUNT = 8
} GeglScDirection;
#define GEGL_SC_DIRECTION_CW(d) (((d) + 1) % 8)
#define GEGL_SC_DIRECTION_CCW(d) (((d) + 7) % 8)
#define GEGL_SC_DIRECTION_OPPOSITE(d) (((d) + 4) % 8)
#define GEGL_SC_DIRECTION_IS_NORTH(d) ( \
((d) == GEGL_SC_DIRECTION_N) || \
((d) == GEGL_SC_DIRECTION_NE) || \
((d) == GEGL_SC_DIRECTION_NW) \
)
#define SC_DIRECTION_IS_SOUTH(d) ( \
((d) == SC_DIRECTION_S) || \
((d) == SC_DIRECTION_SE) || \
((d) == SC_DIRECTION_SW) \
#define GEGL_SC_DIRECTION_IS_SOUTH(d) ( \
((d) == GEGL_SC_DIRECTION_S) || \
((d) == GEGL_SC_DIRECTION_SE) || \
((d) == GEGL_SC_DIRECTION_SW) \
)
#define SC_DIRECTION_IS_EAST(d) ( \
((d) == SC_DIRECTION_E) || \
((d) == SC_DIRECTION_NE) || \
((d) == SC_DIRECTION_SE) \
#define GEGL_SC_DIRECTION_IS_EAST(d) ( \
((d) == GEGL_SC_DIRECTION_E) || \
((d) == GEGL_SC_DIRECTION_NE) || \
((d) == GEGL_SC_DIRECTION_SE) \
)
#define SC_DIRECTION_IS_WEST(d) ( \
((d) == SC_DIRECTION_W) || \
((d) == SC_DIRECTION_NW) || \
((d) == SC_DIRECTION_SW) \
#define GEGL_SC_DIRECTION_IS_WEST(d) ( \
((d) == GEGL_SC_DIRECTION_W) || \
((d) == GEGL_SC_DIRECTION_NW) || \
((d) == GEGL_SC_DIRECTION_SW) \
)
#define SC_DIRECTION_XOFFSET(d,s) ( \
(SC_DIRECTION_IS_EAST(d)) ? (s) : \
((SC_DIRECTION_IS_WEST(d)) ? -(s) : \
0) \
#define GEGL_SC_DIRECTION_XOFFSET(d,s) ( \
(GEGL_SC_DIRECTION_IS_EAST(d)) ? (s) : \
((GEGL_SC_DIRECTION_IS_WEST(d)) ? -(s) : \
0) \
)
#define SC_DIRECTION_YOFFSET(d,s) ( \
(SC_DIRECTION_IS_SOUTH(d)) ? (s) : \
((SC_DIRECTION_IS_NORTH(d)) ? -(s) : \
0) \
#define GEGL_SC_DIRECTION_YOFFSET(d,s) ( \
(GEGL_SC_DIRECTION_IS_SOUTH(d)) ? (s) : \