ector: add software backend using FreeType rasterizer.

This commit is contained in:
Subhransu Sekhar Mohanty 2015-04-03 16:31:45 +02:00 committed by Cedric BAIL
parent e99774946c
commit 891ec14585
21 changed files with 7963 additions and 0 deletions

View File

@ -0,0 +1,15 @@
#ifndef ECTOR_SOFTWARE_H_
#define ECTOR_SOFTWARE_H_
#include <Ector.h>
typedef Eo Ector_Software_Surface;
typedef struct _Software_Rasterizer Software_Rasterizer;
#include "software/ector_software_surface.eo.h"
#include "software/ector_renderer_software_base.eo.h"
#include "software/ector_renderer_software_shape.eo.h"
#include "software/ector_renderer_software_gradient_linear.eo.h"
#include "software/ector_renderer_software_gradient_radial.eo.h"
#endif

View File

@ -0,0 +1,117 @@
#ifndef ECTOR_BLEND_PRIVATE_H
#define ECTOR_BLEND_PRIVATE_H
#ifndef MIN
#define MIN( a, b ) ( (a) < (b) ? (a) : (b) )
#endif
#ifndef MAX
#define MAX( a, b ) ( (a) > (b) ? (a) : (b) )
#endif
#define ECTOR_ARGB_JOIN(a,r,g,b) \
(((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
#define ECTOR_MUL4_SYM(x, y) \
( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \
((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \
((((((x) & 0xff00) * ((y) & 0xff00)) + 0xff0000) >> 16) & 0xff00) + \
(((((x) & 0xff) * ((y) & 0xff)) + 0xff) >> 8) )
#define ECTOR_MUL_256(c, a) \
( (((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \
(((((c) & 0x00ff00ff) * (a)) >> 8) & 0x00ff00ff) )
static inline void
_ector_memfill(DATA32 *dest, uint value, int count)
{
if (!count)
return;
int n = (count + 7) / 8;
switch (count & 0x07)
{
case 0: do { *dest++ = value;
case 7: *dest++ = value;
case 6: *dest++ = value;
case 5: *dest++ = value;
case 4: *dest++ = value;
case 3: *dest++ = value;
case 2: *dest++ = value;
case 1: *dest++ = value;
} while (--n > 0);
}
}
static inline void
_ector_comp_func_source_over_mul_c(uint *dest, uint *src, DATA32 c, int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
uint s = src[i];
DATA32 sc = ECTOR_MUL4_SYM(c, s);
uint a = (~sc) >> 24;
dest[i] = sc + ECTOR_MUL_256(dest[i], a);
}
} else {
for (int i = 0; i < length; ++i) {
uint s = src[i];
DATA32 sc = ECTOR_MUL4_SYM(c, s);
sc = ECTOR_MUL_256(sc, const_alpha);
uint a = (~sc) >> 24;
dest[i] = sc + ECTOR_MUL_256(dest[i], a);
}
}
}
static inline void
_ector_comp_func_source_over(uint *dest, uint *src, int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
uint s = src[i];
if (s >= 0xff000000)
dest[i] = s;
else if (s != 0) {
uint a = (~s) >> 24;
dest[i] = s + ECTOR_MUL_256(dest[i], a);
}
}
} else {
for (int i = 0; i < length; ++i) {
uint s = ECTOR_MUL_256(src[i], const_alpha);
uint a = (~s) >> 24;
dest[i] = s + ECTOR_MUL_256(dest[i], a);
}
}
}
static inline uint
_ector_premultiply(uint data)
{
DATA32 a = 1 + (data >> 24);
data = ( data & 0xff000000) +
(((((data) >> 8) & 0xff) * a) & 0xff00) +
(((((data) & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
return data;
}
static inline uint
INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
t >>= 8;
t &= 0xff00ff;
x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
x &= 0xff00ff00;
x |= t;
return x;
}
#endif

View File

@ -0,0 +1,12 @@
class Ector.Renderer.Software.Base (Ector.Renderer.Generic.Base)
{
legacy_prefix: null;
methods {
fill {
return: bool;
}
}
implements {
@virtual .fill;
}
}

View File

@ -0,0 +1,109 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <Ector.h>
#include <software/Ector_Software.h>
#include "ector_private.h"
#include "ector_software_private.h"
static void
_update_linear_data(Ector_Renderer_Software_Gradient_Data *gdata)
{
update_color_table(gdata);
gdata->linear.x1 = gdata->gld->start.x;
gdata->linear.y1 = gdata->gld->start.y;
gdata->linear.x2 = gdata->gld->end.x;
gdata->linear.y2 = gdata->gld->end.y;
gdata->linear.dx = gdata->linear.x2 - gdata->linear.x1;
gdata->linear.dy = gdata->linear.y2 - gdata->linear.y1;
gdata->linear.l = gdata->linear.dx * gdata->linear.dx + gdata->linear.dy * gdata->linear.dy;
gdata->linear.off = 0;
if (gdata->linear.l != 0)
{
gdata->linear.dx /= gdata->linear.l;
gdata->linear.dy /= gdata->linear.l;
gdata->linear.off = -gdata->linear.dx * gdata->linear.x1 - gdata->linear.dy * gdata->linear.y1;
}
}
static Eina_Bool
_ector_renderer_software_gradient_linear_ector_renderer_generic_base_prepare(Eo *obj,
Ector_Renderer_Software_Gradient_Data *pd)
{
if (!pd->surface)
{
Eo *parent;
eo_do(obj, parent = eo_parent_get());
if (!parent) return EINA_FALSE;
pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
}
_update_linear_data(pd);
return EINA_FALSE;
}
static Eina_Bool
_ector_renderer_software_gradient_linear_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED,
Ector_Renderer_Software_Gradient_Data *pd EINA_UNUSED,
Ector_Rop op EINA_UNUSED, Eina_Array *clips EINA_UNUSED,
int x EINA_UNUSED, int y EINA_UNUSED, unsigned int mul_col EINA_UNUSED)
{
return EINA_TRUE;
}
static Eina_Bool
_ector_renderer_software_gradient_linear_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED,
Ector_Renderer_Software_Gradient_Data *pd)
{
ector_software_rasterizer_linear_gradient_set(pd->surface->software, pd);
return EINA_TRUE;
}
void
_ector_renderer_software_gradient_linear_eo_base_constructor(Eo *obj,
Ector_Renderer_Software_Gradient_Data *pd)
{
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, eo_constructor());
pd->gd = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN, obj);
pd->gld = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN, obj);
}
void
_ector_renderer_software_gradient_linear_eo_base_destructor(Eo *obj,
Ector_Renderer_Software_Gradient_Data *pd)
{
Eo *parent;
destroy_color_table(pd);
eo_do(obj, parent = eo_parent_get());
eo_data_xunref(parent, pd->surface, obj);
eo_data_xunref(obj, pd->gd, obj);
eo_data_xunref(obj, pd->gld, obj);
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, eo_destructor());
}
void
_ector_renderer_software_gradient_linear_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
{
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS,
efl_gfx_gradient_stop_set(colors, length));
destroy_color_table(pd);
}
#include "ector_renderer_software_gradient_linear.eo.c"

View File

@ -0,0 +1,14 @@
class Ector.Renderer.Software.Gradient_Linear (Ector.Renderer.Software.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Linear)
{
eo_prefix: ector_renderer_software_gradient_linear;
legacy_prefix: null;
data: Ector_Renderer_Software_Gradient_Data;
implements {
Ector.Renderer.Generic.Base.prepare;
Ector.Renderer.Generic.Base.draw;
Ector.Renderer.Software.Base.fill;
Eo.Base.constructor;
Eo.Base.destructor;
Efl.Gfx.Gradient.Base.stop.set;
}
}

View File

@ -0,0 +1,117 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <Ector.h>
#include <software/Ector_Software.h>
#include "ector_private.h"
#include "ector_software_private.h"
static void
_update_radial_data(Ector_Renderer_Software_Gradient_Data *gdata)
{
update_color_table(gdata);
gdata->radial.cx = gdata->grd->radial.x;
gdata->radial.cy = gdata->grd->radial.y;
gdata->radial.cradius = gdata->grd->radius;
if (!gdata->grd->focal.x)
gdata->radial.fx = gdata->grd->radial.x;
else
gdata->radial.fx = gdata->grd->focal.x;
if (!gdata->grd->focal.y)
gdata->radial.fy = gdata->grd->radial.y;
else
gdata->radial.fy = gdata->grd->focal.y;
gdata->radial.fradius = 0;
gdata->radial.dx = gdata->radial.cx - gdata->radial.fx;
gdata->radial.dy = gdata->radial.cy - gdata->radial.fy;
gdata->radial.dr = gdata->radial.cradius - gdata->radial.fradius;
gdata->radial.sqrfr = gdata->radial.fradius * gdata->radial.fradius;
gdata->radial.a = gdata->radial.dr * gdata->radial.dr -
gdata->radial.dx * gdata->radial.dx -
gdata->radial.dy * gdata->radial.dy;
gdata->radial.inv2a = 1 / (2 * gdata->radial.a);
gdata->radial.extended = (gdata->radial.fradius >= 0.00001f) || gdata->radial.a >= 0.00001f;
}
static Eina_Bool
_ector_renderer_software_gradient_radial_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd)
{
if (!pd->surface)
{
Eo *parent;
eo_do(obj, parent = eo_parent_get());
if (!parent) return EINA_FALSE;
pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
}
_update_radial_data(pd);
return EINA_FALSE;
}
// Clearly duplicated and should be in a common place...
static Eina_Bool
_ector_renderer_software_gradient_radial_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED,
Ector_Renderer_Software_Gradient_Data *pd EINA_UNUSED,
Ector_Rop op EINA_UNUSED, Eina_Array *clips EINA_UNUSED,
int x EINA_UNUSED, int y EINA_UNUSED, unsigned int mul_col EINA_UNUSED)
{
return EINA_TRUE;
}
// Clearly duplicated and should be in a common place...
static Eina_Bool
_ector_renderer_software_gradient_radial_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Gradient_Data *pd)
{
ector_software_rasterizer_radial_gradient_set(pd->surface->software, pd);
return EINA_TRUE;
}
void
_ector_renderer_software_gradient_radial_eo_base_constructor(Eo *obj,
Ector_Renderer_Software_Gradient_Data *pd)
{
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, eo_constructor());
pd->gd = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN, obj);
pd->gld = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN, obj);
}
void
_ector_renderer_software_gradient_radial_eo_base_destructor(Eo *obj,
Ector_Renderer_Software_Gradient_Data *pd)
{
Eo *parent;
destroy_color_table(pd);
eo_do(obj, parent = eo_parent_get());
eo_data_xunref(parent, pd->surface, obj);
eo_data_xunref(obj, pd->gd, obj);
eo_data_xunref(obj, pd->gld, obj);
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, eo_destructor());
}
void
_ector_renderer_software_gradient_radial_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
{
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS,
efl_gfx_gradient_stop_set(colors, length));
destroy_color_table(pd);
}
#include "ector_renderer_software_gradient_radial.eo.c"

View File

@ -0,0 +1,14 @@
class Ector.Renderer.Software.Gradient_Radial (Ector.Renderer.Software.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Radial)
{
eo_prefix: ector_renderer_software_gradient_radial;
legacy_prefix: null;
data: Ector_Renderer_Software_Gradient_Data;
implements {
Ector.Renderer.Generic.Base.prepare;
Ector.Renderer.Generic.Base.draw;
Ector.Renderer.Software.Base.fill;
Eo.Base.constructor;
Eo.Base.destructor;
Efl.Gfx.Gradient.Base.stop.set;
}
}

View File

@ -0,0 +1,373 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <math.h>
#include <float.h>
#include <Eina.h>
#include <Ector.h>
#include <software/Ector_Software.h>
#include "ector_private.h"
#include "ector_software_private.h"
typedef struct _Ector_Renderer_Software_Shape_Data Ector_Renderer_Software_Shape_Data;
struct _Ector_Renderer_Software_Shape_Data
{
Ector_Software_Surface_Data *surface;
Ector_Renderer_Generic_Shape_Data *shape;
Ector_Renderer_Generic_Base_Data *base;
Shape_Rle_Data *shape_data;
Shape_Rle_Data *outline_data;
};
typedef struct _Outline
{
SW_FT_Outline ft_outline;
int points_alloc;
int contours_alloc;
}Outline;
static Outline *
_outline_create()
{
Outline *outline = (Outline *) calloc(1, sizeof(Outline));
outline->ft_outline.points = (SW_FT_Vector *) calloc(50, sizeof(SW_FT_Vector));
outline->ft_outline.tags = (char *) calloc(50, sizeof(char));
outline->ft_outline.contours = (short *) calloc(5, sizeof(short));
outline->points_alloc = 50;
outline->contours_alloc = 5;
return outline;
}
static
void _outline_destroy(Outline *outline)
{
if (outline)
{
free(outline->ft_outline.points);
free(outline->ft_outline.tags);
free(outline->ft_outline.contours);
free(outline);
outline = NULL;
}
}
static void
_outline_move_to(Outline *outline, double x, double y)
{
SW_FT_Outline *ft_outline = &outline->ft_outline;
if (ft_outline->n_contours == outline->contours_alloc)
{
outline->contours_alloc += 5;
ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
}
ft_outline->points[ft_outline->n_points].x = x;
ft_outline->points[ft_outline->n_points].y = y;
ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
if (ft_outline->n_points)
{
ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1;
ft_outline->n_contours++;
}
ft_outline->n_points++;
}
static void
_outline_end(Outline *outline)
{
SW_FT_Outline *ft_outline = &outline->ft_outline;
if (ft_outline->n_contours == outline->contours_alloc)
{
outline->contours_alloc += 1;
ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
}
if (ft_outline->n_points)
{
ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1;
ft_outline->n_contours++;
}
}
static void _outline_line_to(Outline *outline, double x, double y)
{
SW_FT_Outline *ft_outline = &outline->ft_outline;
if (ft_outline->n_points == outline->points_alloc)
{
outline->points_alloc += 50;
ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
}
ft_outline->points[ft_outline->n_points].x = x;
ft_outline->points[ft_outline->n_points].y = y;
ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
ft_outline->n_points++;
}
static Eina_Bool
_outline_close_path(Outline *outline)
{
SW_FT_Outline *ft_outline = &outline->ft_outline;
int index ;
if (ft_outline->n_contours)
{
index = ft_outline->contours[ft_outline->n_contours - 1] + 1;
}
else
{
// first path
index = 0;
}
// make sure there is atleast one point in the current path
if (ft_outline->n_points == index) return EINA_FALSE;
_outline_line_to(outline, ft_outline->points[index].x, ft_outline->points[index].y);
return EINA_TRUE;
}
static void _outline_cubic_to(Outline *outline, double cx1, double cy1, double cx2, double cy2, double x, double y)
{
SW_FT_Outline *ft_outline = &outline->ft_outline;
if (ft_outline->n_points == outline->points_alloc)
{
outline->points_alloc += 50;
ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
}
ft_outline->points[ft_outline->n_points].x = cx1;
ft_outline->points[ft_outline->n_points].y = cy1;
ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_CUBIC;
ft_outline->n_points++;
ft_outline->points[ft_outline->n_points].x = cx2;
ft_outline->points[ft_outline->n_points].y = cy2;
ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_CUBIC;
ft_outline->n_points++;
ft_outline->points[ft_outline->n_points].x = x;
ft_outline->points[ft_outline->n_points].y = y;
ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
ft_outline->n_points++;
}
static void _outline_transform(Outline *outline, Eina_Matrix3 *m)
{
int i;
SW_FT_Outline *ft_outline = &outline->ft_outline;
if (m)
{
double x, y;
for (i = 0; i < ft_outline->n_points ; i++)
{
eina_matrix3_point_transform(m, ft_outline->points[i].x, ft_outline->points[i].y, &x, &y);
ft_outline->points[i].x = (int)(x * 64);// to freetype 26.6 coordinate.
ft_outline->points[i].y = (int)(y * 64);
}
}
else
{
for (i = 0; i < ft_outline->n_points ; i++)
{
ft_outline->points[i].x = ft_outline->points[i].x <<6;// to freetype 26.6 coordinate.
ft_outline->points[i].y = ft_outline->points[i].y <<6;
}
}
}
static Eina_Bool
_ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
{
const Efl_Gfx_Path_Command *cmds = NULL;
const double *pts = NULL;
// FIXME: shouldn't that be part of the shape generic implementation ?
if (pd->shape->fill)
eo_do(pd->shape->fill, ector_renderer_prepare());
if (pd->shape->stroke.fill)
eo_do(pd->shape->stroke.fill, ector_renderer_prepare());
if (pd->shape->stroke.marker)
eo_do(pd->shape->stroke.marker, ector_renderer_prepare());
// shouldn't that be moved to the software base object
if (!pd->surface)
{
Eo *parent;
eo_do(obj, parent = eo_parent_get());
if (!parent) return EINA_FALSE;
pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
if (!pd->surface) return EINA_FALSE;
}
eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts));
if (!pd->shape_data && cmds)
{
Eina_Bool close_path = EINA_FALSE;
Outline * outline = _outline_create();
for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
{
switch (*cmds)
{
case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
_outline_move_to(outline, pts[0], pts[1]);
pts += 2;
break;
case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
_outline_line_to(outline, pts[0], pts[1]);
pts += 2;
break;
case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
// Be careful, we do have a different order than
// cairo, first is destination point, followed by
// the control point. The opposite of cairo.
_outline_cubic_to(outline,
pts[2], pts[3], pts[4], pts[5], // control points
pts[0], pts[1]); // destination point
pts += 6;
break;
case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:
close_path = _outline_close_path(outline);
break;
case EFL_GFX_PATH_COMMAND_TYPE_LAST:
case EFL_GFX_PATH_COMMAND_TYPE_END:
break;
}
}
_outline_end(outline);
_outline_transform(outline, pd->base->m);
// generate the shape data.
pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->software, &outline->ft_outline);
if (!pd->outline_data)
{
ector_software_rasterizer_stroke_set(pd->surface->software, (pd->shape->stroke.width * pd->shape->stroke.scale), pd->shape->stroke.cap,
pd->shape->stroke.join);
pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->software, &outline->ft_outline, close_path);
}
_outline_destroy(outline);
}
return EINA_TRUE;
}
static Eina_Bool
_ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd, Ector_Rop op, Eina_Array *clips, int x, int y, unsigned int mul_col)
{
// adjust the offset
x = x + (int)pd->base->origin.x;
y = y + (int)pd->base->origin.y;
// fill the span_data structure
ector_software_rasterizer_clip_rect_set(pd->surface->software, clips);
ector_software_rasterizer_transform_set(pd->surface->software, pd->base->m);
if (pd->shape->fill)
{
eo_do(pd->shape->fill, ector_renderer_software_base_fill());
ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data);
}
else
{
if (pd->base->color.a > 0)
{
ector_software_rasterizer_color_set(pd->surface->software, pd->base->color.r, pd->base->color.g, pd->base->color.b, pd->base->color.a);
ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data);
}
}
if (pd->shape->stroke.fill)
{
eo_do(pd->shape->stroke.fill, ector_renderer_software_base_fill());
ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data);
}
else
{
if (pd->shape->stroke.color.a > 0)
{
ector_software_rasterizer_color_set(pd->surface->software,
pd->shape->stroke.color.r, pd->shape->stroke.color.g,
pd->shape->stroke.color.b, pd->shape->stroke.color.a);
ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data);
}
}
return EINA_TRUE;
}
static Eina_Bool
_ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd EINA_UNUSED)
{
// FIXME: let's find out how to fill a shape with a shape later.
// I need to read SVG specification and see how to map that with software.
return EINA_FALSE;
}
static void
_ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_Software_Shape_Data *pd,
const Efl_Gfx_Path_Command *op, const double *points)
{
if(pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
if(pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
pd->shape_data = NULL;
pd->outline_data = NULL;
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, efl_gfx_shape_path_set(op, points));
}
void
_ector_renderer_software_shape_eo_base_constructor(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
{
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, eo_constructor());
pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_MIXIN, obj);
pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj);
}
void
_ector_renderer_software_shape_eo_base_destructor(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
{
Eo *parent;
if(pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
if(pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
eo_do(obj, parent = eo_parent_get());
eo_data_xunref(parent, pd->surface, obj);
eo_data_xunref(obj, pd->shape, obj);
eo_data_xunref(obj, pd->base, obj);
eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, eo_destructor());
}
#include "ector_renderer_software_shape.eo.c"

View File

@ -0,0 +1,13 @@
class Ector.Renderer.Software.Shape (Ector.Renderer.Software.Base, Ector.Renderer.Generic.Shape)
{
eo_prefix: ector_renderer_software_shape;
legacy_prefix: null;
implements {
Ector.Renderer.Generic.Base.prepare;
Ector.Renderer.Generic.Base.draw;
Ector.Renderer.Software.Base.fill;
Efl.Gfx.Shape.path.set;
Eo.Base.constructor;
Eo.Base.destructor;
}
}

View File

@ -0,0 +1,269 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
//Remove
#include <assert.h>
#include <math.h>
#include <float.h>
#include <Eina.h>
#include <Ector.h>
#include <software/Ector_Software.h>
#include "ector_private.h"
#include "ector_software_private.h"
#include "ector_blend_private.h"
#define GRADIENT_STOPTABLE_SIZE 1024
#define FIXPT_BITS 8
#define FIXPT_SIZE (1<<FIXPT_BITS)
static inline int
_gradient_clamp(const Ector_Renderer_Software_Gradient_Data *data, int ipos)
{
if (data->gd->s == EFL_GFX_GRADIENT_SPREAD_REPEAT)
{
ipos = ipos % GRADIENT_STOPTABLE_SIZE;
ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
}
else if (data->gd->s == EFL_GFX_GRADIENT_SPREAD_REFLECT)
{
const int limit = GRADIENT_STOPTABLE_SIZE * 2;
ipos = ipos % limit;
ipos = ipos < 0 ? limit + ipos : ipos;
ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - 1 - ipos : ipos;
}
else
{
if (ipos < 0)
ipos = 0;
else if (ipos >= GRADIENT_STOPTABLE_SIZE)
ipos = GRADIENT_STOPTABLE_SIZE-1;
}
return ipos;
}
static uint
_gradient_pixel_fixed(const Ector_Renderer_Software_Gradient_Data *data, int fixed_pos)
{
int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
return data->colorTable[_gradient_clamp(data, ipos)];
}
static inline uint
_gradient_pixel(const Ector_Renderer_Software_Gradient_Data *data, float pos)
{
int ipos = (int)(pos * (GRADIENT_STOPTABLE_SIZE - 1) + (float)(0.5));
return data->colorTable[_gradient_clamp(data, ipos)];
}
typedef double (*BLEND_FUNC)(double progress);
static double
_ease_linear(double t)
{
return t;
}
static void
_generate_gradient_color_table(Efl_Gfx_Gradient_Stop *gradient_stops, int stop_count, uint *colorTable, int size)
{
int pos = 0;
Efl_Gfx_Gradient_Stop *curr, *next;
assert(stop_count > 0);
curr = gradient_stops;
uint current_color = ECTOR_ARGB_JOIN(curr->a, curr->r, curr->g, curr->b);
double incr = 1.0 / (double)size;
double fpos = 1.5 * incr;
current_color = _ector_premultiply(current_color);
colorTable[pos++] = current_color;
while (fpos <= curr->offset)
{
colorTable[pos] = colorTable[pos - 1];
pos++;
fpos += incr;
}
for (int i = 0; i < stop_count - 1; ++i)
{
curr = (gradient_stops + i);
next = (gradient_stops + i + 1);
double delta = 1/(next->offset - curr->offset);
uint next_color = ECTOR_ARGB_JOIN(next->a, next->r, next->g, next->b);
next_color = _ector_premultiply(next_color);
BLEND_FUNC func = &_ease_linear;
while (fpos < next->offset && pos < size)
{
double t = func((fpos - curr->offset) * delta);
int dist = (int)(256 * t);
int idist = 256 - dist;
colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
++pos;
fpos += incr;
}
current_color = next_color;
}
uint last_color = _ector_premultiply(current_color);
for (;pos < size; ++pos)
colorTable[pos] = last_color;
// Make sure the last color stop is represented at the end of the table
colorTable[size-1] = last_color;
}
void
update_color_table(Ector_Renderer_Software_Gradient_Data *gdata)
{
if(gdata->colorTable) return;
gdata->colorTable = malloc(GRADIENT_STOPTABLE_SIZE * 4);
_generate_gradient_color_table(gdata->gd->colors, gdata->gd->colors_count, gdata->colorTable, GRADIENT_STOPTABLE_SIZE);
}
void
destroy_color_table(Ector_Renderer_Software_Gradient_Data *gdata)
{
if (gdata->colorTable)
{
free(gdata->colorTable);
gdata->colorTable = NULL;
}
}
void
fetch_linear_gradient(uint *buffer, Span_Data *data, int y, int x, int length)
{
Ector_Renderer_Software_Gradient_Data *g_data = data->gradient;
float t, inc;
float rx=0, ry=0;
if (g_data->linear.l == 0)
{
t = inc = 0;
}
else
{
rx = data->inv.xy * (y + (float)0.5) + data->inv.xz + data->inv.xx * (x + (float)0.5);
ry = data->inv.yy * (y + (float)0.5) + data->inv.yz + data->inv.yx * (x + (float)0.5);
t = g_data->linear.dx*rx + g_data->linear.dy*ry + g_data->linear.off;
inc = g_data->linear.dx * data->inv.xx + g_data->linear.dx * data->inv.yx;
t *= (GRADIENT_STOPTABLE_SIZE - 1);
inc *= (GRADIENT_STOPTABLE_SIZE - 1);
}
uint *end = buffer + length;
if (inc > (float)(-1e-5) && inc < (float)(1e-5))
{
_ector_memfill(buffer, _gradient_pixel_fixed(g_data, (int)(t * FIXPT_SIZE)), length);
}
else
{
if (t + inc*length < (float)(INT_MAX >> (FIXPT_BITS + 1)) &&
t+inc*length > (float)(INT_MIN >> (FIXPT_BITS + 1)))
{
// we can use fixed point math
int t_fixed = (int)(t * FIXPT_SIZE);
int inc_fixed = (int)(inc * FIXPT_SIZE);
// #ifdef BUILD_SSE3
// if (evas_common_cpu_has_feature(CPU_FEATURE_SSE3)) {
// _fetch_linear_sse3(buffer, length, g_data, t_fixed, inc_fixed);
// } else
// #endif
{
while (buffer < end)
{
*buffer++ = _gradient_pixel_fixed(g_data, t_fixed);
t_fixed += inc_fixed;
}
}
}
else
{
// we have to fall back to float math
while (buffer < end) {
*buffer++ = _gradient_pixel(g_data, t/GRADIENT_STOPTABLE_SIZE);
t += inc;
}
}
}
}
static void
_radial_helper_generic(uint *buffer, int length, Ector_Renderer_Software_Gradient_Data *g_data, float det,
float delta_det, float delta_delta_det, float b, float delta_b)
{
for (int i = 0 ; i < length ; i++)
{
*buffer++ = _gradient_pixel(g_data, sqrt(det) - b);
det += delta_det;
delta_det += delta_delta_det;
b += delta_b;
}
}
void
fetch_radial_gradient(uint *buffer, Span_Data *data, int y, int x, int length)
{
Ector_Renderer_Software_Gradient_Data *g_data = data->gradient;
// avoid division by zero
if (abs(g_data->radial.a) <= 0.00001f)
{
_ector_memfill(buffer, 0, length);
return;
}
float rx = data->inv.xy * (y + (float)0.5) + data->inv.xz + data->inv.xx * (x + (float)0.5);
float ry = data->inv.yy * (y + (float)0.5) + data->inv.yz + data->inv.yx * (x + (float)0.5);
rx -= g_data->radial.fx;
ry -= g_data->radial.fy;
float inv_a = 1 / (float)(2 * g_data->radial.a);
const float delta_rx = data->inv.xx;
const float delta_ry = data->inv.yx;
float b = 2*(g_data->radial.dr*g_data->radial.fradius + rx * g_data->radial.dx + ry * g_data->radial.dy);
float delta_b = 2*(delta_rx * g_data->radial.dx + delta_ry * g_data->radial.dy);
const float b_delta_b = 2 * b * delta_b;
const float delta_b_delta_b = 2 * delta_b * delta_b;
const float bb = b * b;
const float delta_bb = delta_b * delta_b;
b *= inv_a;
delta_b *= inv_a;
const float rxrxryry = rx * rx + ry * ry;
const float delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
const float rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
const float delta_rx_plus_ry = 2 * delta_rxrxryry;
inv_a *= inv_a;
float det = (bb - 4 * g_data->radial.a * (g_data->radial.sqrfr - rxrxryry)) * inv_a;
float delta_det = (b_delta_b + delta_bb + 4 * g_data->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
const float delta_delta_det = (delta_b_delta_b + 4 * g_data->radial.a * delta_rx_plus_ry) * inv_a;
// #ifdef BUILD_SSE3
// if (evas_common_cpu_has_feature(CPU_FEATURE_SSE3)) {
// _radial_helper_sse3(buffer, length, g_data, det, delta_det, delta_delta_det, b, delta_b);
// } else
// #endif
{ // generic fallback
_radial_helper_generic(buffer, length, g_data, det, delta_det, delta_delta_det, b, delta_b);
}
}

View File

@ -0,0 +1,150 @@
#ifndef ECTOR_SOFTWARE_PRIVATE_H_
# define ECTOR_SOFTWARE_PRIVATE_H_
#include "sw_ft_raster.h"
#include "sw_ft_stroker.h"
#ifndef DATA32
typedef unsigned int DATA32;
#endif
#ifndef uint
typedef unsigned int uint;
#endif
typedef struct _Ector_Software_Surface_Data Ector_Software_Surface_Data;
#define CHECK_SOFTWARE(Parent) (!(Parent && Parent->software))
// Gradient related structure
typedef struct _Software_Gradient_Linear_Data
{
float x1, y1, x2, y2;
float dx, dy, l, off;
} Software_Gradient_Linear_Data;
typedef struct _Software_Gradient_Radial_Data
{
float cx, cy, fx, fy, cradius, fradius;
float dx, dy, dr, sqrfr, a, inv2a;
Eina_Bool extended;
} Software_Gradient_Radial_Data;
typedef struct _Ector_Renderer_Software_Gradient_Data
{
Ector_Software_Surface_Data *surface;
Ector_Renderer_Generic_Gradient_Data *gd;
union {
Ector_Renderer_Generic_Gradient_Linear_Data *gld;
Ector_Renderer_Generic_Gradient_Radial_Data *grd;
};
union {
Software_Gradient_Linear_Data linear;
Software_Gradient_Radial_Data radial;
};
uint* colorTable;
} Ector_Renderer_Software_Gradient_Data;
// Rasterizer related structure
typedef struct _Raster_Buffer
{
int width;
int height;
DATA32 *buffer;
} Raster_Buffer;
typedef struct _Shape_Rle_Data
{
unsigned short alloc;
unsigned short size;
SW_FT_Span *spans;// array of Scanlines.
} Shape_Rle_Data;
typedef struct _Clip_Data
{
Eina_Array *clips; //Eina_Rectangle
Shape_Rle_Data *path;
unsigned int enabled : 1;
unsigned int hasRectClip : 1;
unsigned int hasPathClip : 1;
} Clip_Data;
typedef enum _Span_Data_Type {
None,
Solid,
LinearGradient,
RadialGradient,
Image
} Span_Data_Type;
typedef struct _Span_Data
{
Raster_Buffer raster_buffer;
SW_FT_SpanFunc blend;
SW_FT_SpanFunc unclipped_blend;
int offx, offy;
Clip_Data clip;
Eina_Matrix3 inv;
Span_Data_Type type;
Eina_Bool fast_matrix ;
DATA32 mul_col;
Ector_Rop op;
union {
DATA32 color;
Ector_Renderer_Software_Gradient_Data *gradient;
//ImageData texture;
};
} Span_Data;
typedef struct _Software_Rasterizer
{
SW_FT_Raster raster;
SW_FT_Stroker stroker;
Span_Data fillData;
Eina_Matrix3 *transform;
Eina_Rectangle systemClip;
} Software_Rasterizer;
struct _Ector_Software_Surface_Data
{
Software_Rasterizer *software;
};
void ector_software_rasterizer_init(Software_Rasterizer *rasterizer);
void ector_software_rasterizer_done(Software_Rasterizer *rasterizer);
void ector_software_rasterizer_stroke_set(Software_Rasterizer *rasterizer, double width,
Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style);
void ector_software_rasterizer_transform_set(Software_Rasterizer *rasterizer, Eina_Matrix3 *t);
void ector_software_rasterizer_color_set(Software_Rasterizer *rasterizer, int r, int g, int b, int a);
void ector_software_rasterizer_linear_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *linear);
void ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *radial);
void ector_software_rasterizer_clip_rect_set(Software_Rasterizer *rasterizer, Eina_Array *clips);
void ector_software_rasterizer_clip_shape_set(Software_Rasterizer *rasterizer, Shape_Rle_Data *clip);
Shape_Rle_Data * ector_software_rasterizer_generate_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline);
Shape_Rle_Data * ector_software_rasterizer_generate_stroke_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath);
void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, int x, int y, uint mul_col, Ector_Rop op, Shape_Rle_Data* rle);
void ector_software_rasterizer_destroy_rle_data(Shape_Rle_Data *rle);
// Gradient Api
void update_color_table(Ector_Renderer_Software_Gradient_Data *gdata);
void destroy_color_table(Ector_Renderer_Software_Gradient_Data *gdata);
void fetch_linear_gradient(uint *buffer, Span_Data *data, int y, int x, int length);
void fetch_radial_gradient(uint *buffer, Span_Data *data, int y, int x, int length);
#endif

View File

@ -0,0 +1,437 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <Ector.h>
#include <software/Ector_Software.h>
#include "ector_private.h"
#include "ector_software_private.h"
#include "ector_blend_private.h"
static void
_blend_color_argb(int count, const SW_FT_Span *spans, void *userData)
{
Span_Data *data = (Span_Data *)(userData);
// multiply the color with mul_col if any
uint color = ECTOR_MUL4_SYM(data->color, data->mul_col);
Eina_Bool solidSource = ((color >> 24) == 255);
// move to the offset location
uint *buffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
if (solidSource)
{
while (count--)
{
uint *target = buffer + (data->raster_buffer.width * spans->y + spans->x);
if (spans->coverage == 255)
{
_ector_memfill(target, color, spans->len);
}
else
{
uint c = ECTOR_MUL_256(color, spans->coverage);
int ialpha = 255 - spans->coverage;
for (int i = 0; i < spans->len; ++i)
target[i] = c + ECTOR_MUL_256(target[i], ialpha);
}
++spans;
}
return;
}
while (count--)
{
uint *target = buffer + (data->raster_buffer.width * spans->y + spans->x);
uint c = ECTOR_MUL_256(color, spans->coverage);
int ialpha = (~c) >> 24;
for (int i = 0; i < spans->len; ++i)
target[i] = c + ECTOR_MUL_256(target[i], ialpha);
++spans;
}
}
int buffer_size = 2048;
typedef void (*src_fetch) (unsigned int *buffer, Span_Data *data, int y, int x, int length);
static void
_blend_gradient(int count, const SW_FT_Span *spans, void *userData)
{
Span_Data *data = (Span_Data *)(userData);
src_fetch fetchfunc = NULL;
if(data->type == LinearGradient) fetchfunc = &fetch_linear_gradient;
if(data->type == RadialGradient) fetchfunc = &fetch_radial_gradient;
unsigned int buffer[buffer_size];
// move to the offset location
unsigned int *destbuffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
while (count--)
{
unsigned int *target = destbuffer + (data->raster_buffer.width * spans->y + spans->x);
int length = spans->len;
while (length)
{
int l = MIN(length, buffer_size);
fetchfunc(buffer, data, spans->y, spans->x, l);
if (data->mul_col == 0xffffffff)
_ector_comp_func_source_over(target, buffer, l, spans->coverage); // TODO use proper composition func
else
_ector_comp_func_source_over_mul_c(target, buffer, data->mul_col, l, spans->coverage);
target += l;
length -= l;
}
++spans;
}
}
/*!
\internal
spans must be sorted on y
*/
static const
SW_FT_Span *_intersect_spans_rect(const Eina_Rectangle *clip, const SW_FT_Span *spans, const SW_FT_Span *end,
SW_FT_Span **outSpans, int available)
{
SW_FT_Span *out = *outSpans;
const short minx = clip->x;
const short miny = clip->y;
const short maxx = minx + clip->w - 1;
const short maxy = miny + clip->h - 1;
while (available && spans < end )
{
if (spans->y > maxy)
{
spans = end;// update spans so that we can breakout
break;
}
if (spans->y < miny
|| spans->x > maxx
|| spans->x + spans->len <= minx)
{
++spans;
continue;
}
if (spans->x < minx)
{
out->len = MIN(spans->len - (minx - spans->x), maxx - minx + 1);
out->x = minx;
}
else
{
out->x = spans->x;
out->len = MIN(spans->len, (maxx - spans->x + 1));
}
if (out->len != 0)
{
out->y = spans->y;
out->coverage = spans->coverage;
++out;
}
++spans;
--available;
}
*outSpans = out;
return spans;
}
static void
_span_fill_clipRect(int spanCount, const SW_FT_Span *spans, void *userData)
{
const int NSPANS = 256;
int clip_count, i;
SW_FT_Span cspans[NSPANS];
Span_Data *fillData = (Span_Data *) userData;
Clip_Data clip = fillData->clip;
clip_count = eina_array_count(clip.clips);
for (i = 0; i < clip_count ; i ++)
{
Eina_Rectangle *rect = (Eina_Rectangle *)eina_array_data_get(clip.clips, i);
Eina_Rectangle tmpRect;
// invert transform the offset
tmpRect.x = rect->x - fillData->offx;
tmpRect.y = rect->y - fillData->offy;
tmpRect.w = rect->w;
tmpRect.h = rect->h;
//printf("Clip after Offset : %d , %d ,%d , %d\n",tmpRect.x, tmpRect.y, tmpRect.w, tmpRect.h);
//printf("Offset = %d , %d \n", fillData->offx, fillData->offy);
const SW_FT_Span *end = spans + spanCount;
while (spans < end)
{
SW_FT_Span *clipped = cspans;
spans = _intersect_spans_rect(&tmpRect,spans, end, &clipped, NSPANS);
if (clipped - cspans)
fillData->unclipped_blend(clipped - cspans, cspans, fillData);
}
}
}
static void
_adjust_span_fill_methods(Span_Data *spdata)
{
switch(spdata->type)
{
case None:
spdata->unclipped_blend = 0;
break;
case Solid:
spdata->unclipped_blend = &_blend_color_argb;
break;
case LinearGradient:
case RadialGradient:
spdata->unclipped_blend = &_blend_gradient;
break;
case Image:
spdata->unclipped_blend = 0;//&_blend_image;
break;
}
// setup clipping
if (!spdata->unclipped_blend)
{
spdata->blend = 0;
}
else if (!spdata->clip.enabled)
{
spdata->blend = spdata->unclipped_blend;
}
else if (spdata->clip.hasRectClip)
{
spdata->blend = &_span_fill_clipRect;
}
else
{
spdata->blend = &_span_fill_clipRect; //TODO change when do path clipping
}
}
void ector_software_rasterizer_init(Software_Rasterizer *rasterizer)
{
// initialize the rasterizer and stroker
unsigned char* renderPool = (unsigned char*) malloc(1024 * 100);
sw_ft_grays_raster.raster_new(&rasterizer->raster);
sw_ft_grays_raster.raster_reset(rasterizer->raster, renderPool, 1024*100);
SW_FT_Stroker_New(&rasterizer->stroker);
SW_FT_Stroker_Set(rasterizer->stroker, 1<<6,SW_FT_STROKER_LINECAP_BUTT,SW_FT_STROKER_LINEJOIN_MITER,0);
//initialize the span data.
rasterizer->fillData.raster_buffer.buffer = NULL;
rasterizer->fillData.clip.enabled = EINA_FALSE;
rasterizer->fillData.unclipped_blend = 0;
rasterizer->fillData.blend = 0;
}
void ector_software_rasterizer_done(Software_Rasterizer *rasterizer)
{
sw_ft_grays_raster.raster_done(rasterizer->raster);
SW_FT_Stroker_Done(rasterizer->stroker);
//TODO free the pool memory
}
void ector_software_rasterizer_stroke_set(Software_Rasterizer *rasterizer, double width,
Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style)
{
SW_FT_Stroker_LineCap cap;
SW_FT_Stroker_LineJoin join;
switch (cap_style)
{
case EFL_GFX_CAP_SQUARE:
cap = SW_FT_STROKER_LINECAP_SQUARE;
break;
case EFL_GFX_CAP_ROUND:
cap = SW_FT_STROKER_LINECAP_ROUND;
break;
default:
cap = SW_FT_STROKER_LINECAP_BUTT;
break;
}
switch (join_style)
{
case EFL_GFX_JOIN_BEVEL:
join = SW_FT_STROKER_LINEJOIN_BEVEL;
break;
case EFL_GFX_JOIN_ROUND:
join = SW_FT_STROKER_LINEJOIN_ROUND;
break;
default:
join = SW_FT_STROKER_LINEJOIN_MITER;
break;
}
int stroke_width = (int)(width * 64);
SW_FT_Stroker_Set(rasterizer->stroker, stroke_width, cap, join, 0);
}
static void
_rle_generation_cb( int count, const SW_FT_Span* spans,void *user)
{
Shape_Rle_Data *rle = (Shape_Rle_Data *) user;
int newsize = rle->size + count;
// allocate enough memory for new spans
// alloc is required to prevent free and reallocation
// when the rle needs to be regenerated because of attribute change.
if(rle->alloc < newsize)
{
rle->spans = (SW_FT_Span *) realloc(rle->spans, newsize * sizeof(SW_FT_Span));
rle->alloc = newsize;
}
// copy the new spans to the allocated memory
SW_FT_Span *lastspan = (rle->spans + rle->size);
memcpy(lastspan,spans, count * sizeof(SW_FT_Span));
// update the size
rle->size = newsize;
}
Shape_Rle_Data *
ector_software_rasterizer_generate_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline)
{
Shape_Rle_Data *rle_data = (Shape_Rle_Data *) calloc(1, sizeof(Shape_Rle_Data));
SW_FT_Raster_Params params;
params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ;
params.gray_spans = &_rle_generation_cb;
params.user = rle_data;
params.source = outline;
sw_ft_grays_raster.raster_render(rasterizer->raster, &params);
return rle_data;
}
Shape_Rle_Data *
ector_software_rasterizer_generate_stroke_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath)
{
uint points,contors;
SW_FT_Stroker_ParseOutline(rasterizer->stroker, outline, !closePath);
SW_FT_Stroker_GetCounts(rasterizer->stroker,&points, &contors);
SW_FT_Outline strokeOutline = {0};
strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
strokeOutline.tags = (char *) calloc(points, sizeof(char));
strokeOutline.contours = (short *) calloc(contors, sizeof(short));
SW_FT_Stroker_Export(rasterizer->stroker, &strokeOutline);
Shape_Rle_Data *rle_data = ector_software_rasterizer_generate_rle_data(rasterizer, &strokeOutline);
// cleanup the outline data.
free(strokeOutline.points);
free(strokeOutline.tags);
free(strokeOutline.contours);
return rle_data;
}
void ector_software_rasterizer_destroy_rle_data(Shape_Rle_Data *rle)
{
if (rle)
{
if (rle->spans)
free(rle->spans);
free(rle);
}
}
static
void _setup_span_fill_matrix(Software_Rasterizer *rasterizer)
{
if (rasterizer->transform)
{
eina_matrix3_inverse(rasterizer->transform, &rasterizer->fillData.inv);
}
else
{
eina_matrix3_identity(&rasterizer->fillData.inv);
eina_matrix3_identity(&rasterizer->fillData.inv);
}
}
void ector_software_rasterizer_transform_set(Software_Rasterizer *rasterizer, Eina_Matrix3 *t)
{
rasterizer->transform = t;
}
void ector_software_rasterizer_clip_rect_set(Software_Rasterizer *rasterizer, Eina_Array *clips)
{
if (clips)
{
rasterizer->fillData.clip.clips = clips;
rasterizer->fillData.clip.hasRectClip = EINA_TRUE;
rasterizer->fillData.clip.enabled = EINA_TRUE;
}
else
{
rasterizer->fillData.clip.clips = NULL;
rasterizer->fillData.clip.hasRectClip = EINA_FALSE;
rasterizer->fillData.clip.enabled = EINA_FALSE;
}
}
void ector_software_rasterizer_clip_shape_set(Software_Rasterizer *rasterizer, Shape_Rle_Data *clip)
{
rasterizer->fillData.clip.path = clip;
rasterizer->fillData.clip.hasPathClip = EINA_TRUE;
rasterizer->fillData.clip.enabled = EINA_TRUE;
}
void ector_software_rasterizer_color_set(Software_Rasterizer *rasterizer, int r, int g, int b, int a)
{
uint color = ECTOR_ARGB_JOIN(a, r, g, b);
rasterizer->fillData.color = _ector_premultiply(color);
rasterizer->fillData.type = Solid;
}
void ector_software_rasterizer_linear_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *linear)
{
rasterizer->fillData.gradient = linear;
rasterizer->fillData.type = LinearGradient;
}
void ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *radial)
{
rasterizer->fillData.gradient = radial;
rasterizer->fillData.type = RadialGradient;
}
void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer,
int x, int y, uint mul_col, Ector_Rop op, Shape_Rle_Data* rle)
{
// check for NULL rle data
if (!rle) return;
rasterizer->fillData.offx = x;
rasterizer->fillData.offy = y;
rasterizer->fillData.mul_col = mul_col;
rasterizer->fillData.op = op;
_setup_span_fill_matrix(rasterizer);
_adjust_span_fill_methods(&rasterizer->fillData);
if(rasterizer->fillData.blend)
rasterizer->fillData.blend(rle->size, rle->spans, &rasterizer->fillData);
}

View File

@ -0,0 +1,94 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Ector.h>
#include <software/Ector_Software.h>
#include "ector_private.h"
#include "ector_software_private.h"
static unsigned int _software_count = 0;
typedef struct _Ector_Renderer_Software_Base_Data Ector_Renderer_Software_Base_Data;
struct _Ector_Renderer_Software_Base_Data
{
};
static Ector_Renderer *
_ector_software_surface_ector_generic_surface_renderer_factory_new(Eo *obj,
Ector_Software_Surface_Data *pd EINA_UNUSED,
const Eo_Class *type)
{
if (type == ECTOR_RENDERER_GENERIC_SHAPE_MIXIN)
return eo_add(ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, obj);
else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN)
return eo_add(ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, obj);
else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN)
return eo_add(ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, obj);
ERR("Couldn't find class for type: %s\n", eo_class_name_get(type));
return NULL;
}
static void
_ector_software_surface_context_set(Eo *obj EINA_UNUSED,
Ector_Software_Surface_Data *pd,
Software_Rasterizer *ctx)
{
pd->software = ctx;
}
static Software_Rasterizer *
_ector_software_surface_context_get(Eo *obj EINA_UNUSED,
Ector_Software_Surface_Data *pd)
{
return pd->software;
}
void
_ector_software_surface_surface_set(Eo *obj EINA_UNUSED,
Ector_Software_Surface_Data *pd,
void *pixels, unsigned int width, unsigned int height)
{
pd->software->fillData.raster_buffer.buffer = pixels;
pd->software->fillData.raster_buffer.width = width;
pd->software->fillData.raster_buffer.height = height;
}
void
_ector_software_surface_surface_get(Eo *obj EINA_UNUSED,
Ector_Software_Surface_Data *pd,
void **pixels, unsigned int *width, unsigned int *height)
{
*pixels = pd->software->fillData.raster_buffer.buffer;
*width = pd->software->fillData.raster_buffer.width;
*height = pd->software->fillData.raster_buffer.height;
}
static void
_ector_software_surface_eo_base_constructor(Eo *obj,
Ector_Software_Surface_Data *pd EINA_UNUSED)
{
eo_do_super(obj, ECTOR_SOFTWARE_SURFACE_CLASS, eo_constructor());
if(_software_count == 0)
{
pd->software = (Software_Rasterizer *) calloc(1, sizeof(Software_Rasterizer));
ector_software_rasterizer_init(pd->software);
}
_software_count++;
}
static void
_ector_software_surface_eo_base_destructor(Eo *obj EINA_UNUSED,
Ector_Software_Surface_Data *pd EINA_UNUSED)
{
--_software_count;
if (_software_count > 0) return;
ector_software_rasterizer_done(pd->software);
free(pd->software);
pd->software = NULL;
eo_do_super(obj, ECTOR_SOFTWARE_SURFACE_CLASS, eo_destructor());
}
#include "ector_software_surface.eo.c"
#include "ector_renderer_software_base.eo.c"

View File

@ -0,0 +1,33 @@
class Ector.Software.Surface (Ector.Generic.Surface)
{
eo_prefix: ector_software_surface;
legacy_prefix: null;
properties {
context {
set {
}
get {
}
values {
Software_Rasterizer *ctx;
}
}
surface {
set {
}
get {
}
values {
void *pixels;
uint width;
uint height;
}
}
}
implements {
Ector.Generic.Surface.renderer_factory_new;
Eo.Base.destructor;
Eo.Base.constructor;
}
}

View File

@ -0,0 +1,528 @@
/***************************************************************************/
/* */
/* fttrigon.c */
/* */
/* FreeType trigonometric functions (body). */
/* */
/* Copyright 2001-2005, 2012-2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <math.h>
#include "sw_ft_math.h"
#define SW_FT_MSB( x ) ( 31 - __builtin_clz( x ) )
#define SW_FT_PAD_FLOOR( x, n ) ( (x) & ~((n)-1) )
#define SW_FT_PAD_ROUND( x, n ) SW_FT_PAD_FLOOR( (x) + ((n)/2), n )
#define SW_FT_PAD_CEIL( x, n ) SW_FT_PAD_FLOOR( (x) + ((n)-1), n )
#define SW_FT_BEGIN_STMNT do {
#define SW_FT_END_STMNT } while ( 0 )
/* transfer sign leaving a positive number */
#define SW_FT_MOVE_SIGN( x, s ) \
SW_FT_BEGIN_STMNT \
if ( x < 0 ) \
{ \
x = -x; \
s = -s; \
} \
SW_FT_END_STMNT
SW_FT_Long
SW_FT_MulFix( SW_FT_Long a,
SW_FT_Long b )
{
SW_FT_Int s = 1;
SW_FT_Long c;
SW_FT_MOVE_SIGN( a, s );
SW_FT_MOVE_SIGN( b, s );
c = (SW_FT_Long)( ( (SW_FT_Int64)a * b + 0x8000L ) >> 16 );
return ( s > 0 ) ? c : -c;
}
SW_FT_Long
SW_FT_MulDiv( SW_FT_Long a,
SW_FT_Long b,
SW_FT_Long c )
{
SW_FT_Int s = 1;
SW_FT_Long d;
SW_FT_MOVE_SIGN( a, s );
SW_FT_MOVE_SIGN( b, s );
SW_FT_MOVE_SIGN( c, s );
d = (SW_FT_Long)( c > 0 ? ( (SW_FT_Int64)a * b + ( c >> 1 ) ) / c
: 0x7FFFFFFFL );
return ( s > 0 ) ? d : -d;
}
SW_FT_Long
SW_FT_DivFix( SW_FT_Long a,
SW_FT_Long b )
{
SW_FT_Int s = 1;
SW_FT_Long q;
SW_FT_MOVE_SIGN( a, s );
SW_FT_MOVE_SIGN( b, s );
q = (SW_FT_Long)( b > 0 ? ( ( (SW_FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b
: 0x7FFFFFFFL );
return ( s < 0 ? -q : q );
}
/*************************************************************************/
/* */
/* This is a fixed-point CORDIC implementation of trigonometric */
/* functions as well as transformations between Cartesian and polar */
/* coordinates. The angles are represented as 16.16 fixed-point values */
/* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that */
/* only vectors longer than 2^16*180/pi (or at least 22 bits) on a */
/* discrete Cartesian grid can have the same or better angular */
/* resolution. Therefore, to maintain this precision, some functions */
/* require an interim upscaling of the vectors, whereas others operate */
/* with 24-bit long vectors directly. */
/* */
/*************************************************************************/
/* the Cordic shrink factor 0.858785336480436 * 2^32 */
#define SW_FT_TRIG_SCALE 0xDBD95B16UL
/* the highest bit in overflow-safe vector components, */
/* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */
#define SW_FT_TRIG_SAFE_MSB 29
/* this table was generated for SW_FT_PI = 180L << 16, i.e. degrees */
#define SW_FT_TRIG_MAX_ITERS 23
static const SW_FT_Fixed
ft_trig_arctan_table[] =
{
1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
57L, 29L, 14L, 7L, 4L, 2L, 1L
};
/* multiply a given value by the CORDIC shrink factor */
static SW_FT_Fixed
ft_trig_downscale( SW_FT_Fixed val )
{
SW_FT_Fixed s;
SW_FT_Int64 v;
s = val;
val = SW_FT_ABS( val );
v = ( val * (SW_FT_Int64)SW_FT_TRIG_SCALE ) + 0x100000000UL;
val = (SW_FT_Fixed)( v >> 32 );
return ( s >= 0 ) ? val : -val;
}
/* undefined and never called for zero vector */
static SW_FT_Int
ft_trig_prenorm( SW_FT_Vector* vec )
{
SW_FT_Pos x, y;
SW_FT_Int shift;
x = vec->x;
y = vec->y;
shift = SW_FT_MSB( SW_FT_ABS( x ) | SW_FT_ABS( y ) );
if ( shift <= SW_FT_TRIG_SAFE_MSB )
{
shift = SW_FT_TRIG_SAFE_MSB - shift;
vec->x = (SW_FT_Pos)( (SW_FT_ULong)x << shift );
vec->y = (SW_FT_Pos)( (SW_FT_ULong)y << shift );
}
else
{
shift -= SW_FT_TRIG_SAFE_MSB;
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
return shift;
}
static void
ft_trig_pseudo_rotate( SW_FT_Vector* vec,
SW_FT_Angle theta )
{
SW_FT_Int i;
SW_FT_Fixed x, y, xtemp, b;
const SW_FT_Fixed *arctanptr;
x = vec->x;
y = vec->y;
/* Rotate inside [-PI/4,PI/4] sector */
while ( theta < -SW_FT_ANGLE_PI4 )
{
xtemp = y;
y = -x;
x = xtemp;
theta += SW_FT_ANGLE_PI2;
}
while ( theta > SW_FT_ANGLE_PI4 )
{
xtemp = -y;
y = x;
x = xtemp;
theta -= SW_FT_ANGLE_PI2;
}
arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */
for ( i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++ )
{
if ( theta < 0 )
{
xtemp = x + ( ( y + b ) >> i );
y = y - ( ( x + b ) >> i );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( ( y + b ) >> i );
y = y + ( ( x + b ) >> i );
x = xtemp;
theta -= *arctanptr++;
}
}
vec->x = x;
vec->y = y;
}
static void
ft_trig_pseudo_polarize( SW_FT_Vector* vec )
{
SW_FT_Angle theta;
SW_FT_Int i;
SW_FT_Fixed x, y, xtemp, b;
const SW_FT_Fixed *arctanptr;
x = vec->x;
y = vec->y;
/* Get the vector into [-PI/4,PI/4] sector */
if ( y > x )
{
if ( y > -x )
{
theta = SW_FT_ANGLE_PI2;
xtemp = y;
y = -x;
x = xtemp;
}
else
{
theta = y > 0 ? SW_FT_ANGLE_PI : -SW_FT_ANGLE_PI;
x = -x;
y = -y;
}
}
else
{
if ( y < -x )
{
theta = -SW_FT_ANGLE_PI2;
xtemp = -y;
y = x;
x = xtemp;
}
else
{
theta = 0;
}
}
arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */
for ( i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++ )
{
if ( y > 0 )
{
xtemp = x + ( ( y + b ) >> i );
y = y - ( ( x + b ) >> i );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( ( y + b ) >> i );
y = y + ( ( x + b ) >> i );
x = xtemp;
theta -= *arctanptr++;
}
}
/* round theta */
if ( theta >= 0 )
theta = SW_FT_PAD_ROUND( theta, 32 );
else
theta = -SW_FT_PAD_ROUND( -theta, 32 );
vec->x = x;
vec->y = theta;
}
/* documentation is in fttrigon.h */
SW_FT_Fixed
SW_FT_Cos( SW_FT_Angle angle )
{
SW_FT_Vector v;
v.x = SW_FT_TRIG_SCALE >> 8;
v.y = 0;
ft_trig_pseudo_rotate( &v, angle );
return ( v.x + 0x80L ) >> 8;
}
/* documentation is in fttrigon.h */
SW_FT_Fixed
SW_FT_Sin( SW_FT_Angle angle )
{
return SW_FT_Cos( SW_FT_ANGLE_PI2 - angle );
}
/* documentation is in fttrigon.h */
SW_FT_Fixed
SW_FT_Tan( SW_FT_Angle angle )
{
SW_FT_Vector v;
v.x = SW_FT_TRIG_SCALE >> 8;
v.y = 0;
ft_trig_pseudo_rotate( &v, angle );
return SW_FT_DivFix( v.y, v.x );
}
/* documentation is in fttrigon.h */
SW_FT_Angle
SW_FT_Atan2( SW_FT_Fixed dx,
SW_FT_Fixed dy )
{
SW_FT_Vector v;
if ( dx == 0 && dy == 0 )
return 0;
v.x = dx;
v.y = dy;
ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
return v.y;
}
/* documentation is in fttrigon.h */
void
SW_FT_Vector_Unit( SW_FT_Vector* vec,
SW_FT_Angle angle )
{
vec->x = SW_FT_TRIG_SCALE >> 8;
vec->y = 0;
ft_trig_pseudo_rotate( vec, angle );
vec->x = ( vec->x + 0x80L ) >> 8;
vec->y = ( vec->y + 0x80L ) >> 8;
}
/* these macros return 0 for positive numbers,
and -1 for negative ones */
#define SW_FT_SIGN_LONG( x ) ( (x) >> ( SW_FT_SIZEOF_LONG * 8 - 1 ) )
#define SW_FT_SIGN_INT( x ) ( (x) >> ( SW_FT_SIZEOF_INT * 8 - 1 ) )
#define SW_FT_SIGN_INT32( x ) ( (x) >> 31 )
#define SW_FT_SIGN_INT16( x ) ( (x) >> 15 )
/* documentation is in fttrigon.h */
void
SW_FT_Vector_Rotate( SW_FT_Vector* vec,
SW_FT_Angle angle )
{
SW_FT_Int shift;
SW_FT_Vector v;
v.x = vec->x;
v.y = vec->y;
if ( angle && ( v.x != 0 || v.y != 0 ) )
{
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_rotate( &v, angle );
v.x = ft_trig_downscale( v.x );
v.y = ft_trig_downscale( v.y );
if ( shift > 0 )
{
SW_FT_Int32 half = (SW_FT_Int32)1L << ( shift - 1 );
vec->x = ( v.x + half + SW_FT_SIGN_LONG( v.x ) ) >> shift;
vec->y = ( v.y + half + SW_FT_SIGN_LONG( v.y ) ) >> shift;
}
else
{
shift = -shift;
vec->x = (SW_FT_Pos)( (SW_FT_ULong)v.x << shift );
vec->y = (SW_FT_Pos)( (SW_FT_ULong)v.y << shift );
}
}
}
/* documentation is in fttrigon.h */
SW_FT_Fixed
SW_FT_Vector_Length( SW_FT_Vector* vec )
{
SW_FT_Int shift;
SW_FT_Vector v;
v = *vec;
/* handle trivial cases */
if ( v.x == 0 )
{
return SW_FT_ABS( v.y );
}
else if ( v.y == 0 )
{
return SW_FT_ABS( v.x );
}
/* general case */
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
v.x = ft_trig_downscale( v.x );
if ( shift > 0 )
return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
return (SW_FT_Fixed)( (SW_FT_UInt32)v.x << -shift );
}
/* documentation is in fttrigon.h */
void
SW_FT_Vector_Polarize( SW_FT_Vector* vec,
SW_FT_Fixed *length,
SW_FT_Angle *angle )
{
SW_FT_Int shift;
SW_FT_Vector v;
v = *vec;
if ( v.x == 0 && v.y == 0 )
return;
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
v.x = ft_trig_downscale( v.x );
*length = ( shift >= 0 ) ? ( v.x >> shift )
: (SW_FT_Fixed)( (SW_FT_UInt32)v.x << -shift );
*angle = v.y;
}
/* documentation is in fttrigon.h */
void
SW_FT_Vector_From_Polar( SW_FT_Vector* vec,
SW_FT_Fixed length,
SW_FT_Angle angle )
{
vec->x = length;
vec->y = 0;
SW_FT_Vector_Rotate( vec, angle );
}
/* documentation is in fttrigon.h */
SW_FT_Angle
SW_FT_Angle_Diff( SW_FT_Angle angle1,
SW_FT_Angle angle2 )
{
SW_FT_Angle delta = angle2 - angle1;
delta %= SW_FT_ANGLE_2PI;
if ( delta < 0 )
delta += SW_FT_ANGLE_2PI;
if ( delta > SW_FT_ANGLE_PI )
delta -= SW_FT_ANGLE_2PI;
return delta;
}
/* END */

View File

@ -0,0 +1,438 @@
#ifndef SW_FT_MATH_H
#define SW_FT_MATH_H
/***************************************************************************/
/* */
/* fttrigon.h */
/* */
/* FreeType trigonometric functions (specification). */
/* */
/* Copyright 2001, 2003, 2005, 2007, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include "sw_ft_types.h"
/*************************************************************************/
/* */
/* The min and max functions missing in C. As usual, be careful not to */
/* write things like SW_FT_MIN( a++, b++ ) to avoid side effects. */
/* */
#define SW_FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
#define SW_FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
#define SW_FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
/*
* Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
* algorithm. We use alpha = 1, beta = 3/8, giving us results with a
* largest error less than 7% compared to the exact value.
*/
#define SW_FT_HYPOT( x, y ) \
( x = SW_FT_ABS( x ), \
y = SW_FT_ABS( y ), \
x > y ? x + ( 3 * y >> 3 ) \
: y + ( 3 * x >> 3 ) )
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_MulFix */
/* */
/* <Description> */
/* A very simple function used to perform the computation */
/* `(a*b)/0x10000' with maximum accuracy. Most of the time this is */
/* used to multiply a given value by a 16.16 fixed-point factor. */
/* */
/* <Input> */
/* a :: The first multiplier. */
/* b :: The second multiplier. Use a 16.16 factor here whenever */
/* possible (see note below). */
/* */
/* <Return> */
/* The result of `(a*b)/0x10000'. */
/* */
/* <Note> */
/* This function has been optimized for the case where the absolute */
/* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
/* As this happens mainly when scaling from notional units to */
/* fractional pixels in FreeType, it resulted in noticeable speed */
/* improvements between versions 2.x and 1.x. */
/* */
/* As a conclusion, always try to place a 16.16 factor as the */
/* _second_ argument of this function; this can make a great */
/* difference. */
/* */
SW_FT_Long
SW_FT_MulFix( SW_FT_Long a,
SW_FT_Long b );
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_MulDiv */
/* */
/* <Description> */
/* A very simple function used to perform the computation `(a*b)/c' */
/* with maximum accuracy (it uses a 64-bit intermediate integer */
/* whenever necessary). */
/* */
/* This function isn't necessarily as fast as some processor specific */
/* operations, but is at least completely portable. */
/* */
/* <Input> */
/* a :: The first multiplier. */
/* b :: The second multiplier. */
/* c :: The divisor. */
/* */
/* <Return> */
/* The result of `(a*b)/c'. This function never traps when trying to */
/* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
/* on the signs of `a' and `b'. */
/* */
SW_FT_Long
SW_FT_MulDiv( SW_FT_Long a,
SW_FT_Long b,
SW_FT_Long c );
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_DivFix */
/* */
/* <Description> */
/* A very simple function used to perform the computation */
/* `(a*0x10000)/b' with maximum accuracy. Most of the time, this is */
/* used to divide a given value by a 16.16 fixed-point factor. */
/* */
/* <Input> */
/* a :: The numerator. */
/* b :: The denominator. Use a 16.16 factor here. */
/* */
/* <Return> */
/* The result of `(a*0x10000)/b'. */
/* */
SW_FT_Long
SW_FT_DivFix( SW_FT_Long a,
SW_FT_Long b );
/*************************************************************************/
/* */
/* <Section> */
/* computations */
/* */
/*************************************************************************/
/*************************************************************************
*
* @type:
* SW_FT_Angle
*
* @description:
* This type is used to model angle values in FreeType. Note that the
* angle is a 16.16 fixed-point value expressed in degrees.
*
*/
typedef SW_FT_Fixed SW_FT_Angle;
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_PI
*
* @description:
* The angle pi expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_PI ( 180L << 16 )
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_2PI
*
* @description:
* The angle 2*pi expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_2PI ( SW_FT_ANGLE_PI * 2 )
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_PI2
*
* @description:
* The angle pi/2 expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_PI2 ( SW_FT_ANGLE_PI / 2 )
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_PI4
*
* @description:
* The angle pi/4 expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_PI4 ( SW_FT_ANGLE_PI / 4 )
/*************************************************************************
*
* @function:
* SW_FT_Sin
*
* @description:
* Return the sinus of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The sinus value.
*
* @note:
* If you need both the sinus and cosinus for a given angle, use the
* function @SW_FT_Vector_Unit.
*
*/
SW_FT_Fixed
SW_FT_Sin( SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Cos
*
* @description:
* Return the cosinus of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The cosinus value.
*
* @note:
* If you need both the sinus and cosinus for a given angle, use the
* function @SW_FT_Vector_Unit.
*
*/
SW_FT_Fixed
SW_FT_Cos( SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Tan
*
* @description:
* Return the tangent of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The tangent value.
*
*/
SW_FT_Fixed
SW_FT_Tan( SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Atan2
*
* @description:
* Return the arc-tangent corresponding to a given vector (x,y) in
* the 2d plane.
*
* @input:
* x ::
* The horizontal vector coordinate.
*
* y ::
* The vertical vector coordinate.
*
* @return:
* The arc-tangent value (i.e. angle).
*
*/
SW_FT_Angle
SW_FT_Atan2( SW_FT_Fixed x,
SW_FT_Fixed y );
/*************************************************************************
*
* @function:
* SW_FT_Angle_Diff
*
* @description:
* Return the difference between two angles. The result is always
* constrained to the ]-PI..PI] interval.
*
* @input:
* angle1 ::
* First angle.
*
* angle2 ::
* Second angle.
*
* @return:
* Constrained value of `value2-value1'.
*
*/
SW_FT_Angle
SW_FT_Angle_Diff( SW_FT_Angle angle1,
SW_FT_Angle angle2 );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Unit
*
* @description:
* Return the unit vector corresponding to a given angle. After the
* call, the value of `vec.x' will be `sin(angle)', and the value of
* `vec.y' will be `cos(angle)'.
*
* This function is useful to retrieve both the sinus and cosinus of a
* given angle quickly.
*
* @output:
* vec ::
* The address of target vector.
*
* @input:
* angle ::
* The input angle.
*
*/
void
SW_FT_Vector_Unit( SW_FT_Vector* vec,
SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Rotate
*
* @description:
* Rotate a vector by a given angle.
*
* @inout:
* vec ::
* The address of target vector.
*
* @input:
* angle ::
* The input angle.
*
*/
void
SW_FT_Vector_Rotate( SW_FT_Vector* vec,
SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Length
*
* @description:
* Return the length of a given vector.
*
* @input:
* vec ::
* The address of target vector.
*
* @return:
* The vector length, expressed in the same units that the original
* vector coordinates.
*
*/
SW_FT_Fixed
SW_FT_Vector_Length( SW_FT_Vector* vec );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Polarize
*
* @description:
* Compute both the length and angle of a given vector.
*
* @input:
* vec ::
* The address of source vector.
*
* @output:
* length ::
* The vector length.
*
* angle ::
* The vector angle.
*
*/
void
SW_FT_Vector_Polarize( SW_FT_Vector* vec,
SW_FT_Fixed *length,
SW_FT_Angle *angle );
/*************************************************************************
*
* @function:
* SW_FT_Vector_From_Polar
*
* @description:
* Compute vector coordinates from a length and angle.
*
* @output:
* vec ::
* The address of source vector.
*
* @input:
* length ::
* The vector length.
*
* angle ::
* The vector angle.
*
*/
void
SW_FT_Vector_From_Polar( SW_FT_Vector* vec,
SW_FT_Fixed length,
SW_FT_Angle angle );
#endif // SW_FT_MATH_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,607 @@
#ifndef SW_FT_IMG_H
#define SW_FT_IMG_H
/***************************************************************************/
/* */
/* ftimage.h */
/* */
/* FreeType glyph image formats and default raster interface */
/* (specification). */
/* */
/* Copyright 1996-2010, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* Note: A `raster' is simply a scan-line converter, used to render */
/* SW_FT_Outlines into SW_FT_Bitmaps. */
/* */
/*************************************************************************/
#include "sw_ft_types.h"
/*************************************************************************/
/* */
/* <Struct> */
/* FT_BBox */
/* */
/* <Description> */
/* A structure used to hold an outline's bounding box, i.e., the */
/* coordinates of its extrema in the horizontal and vertical */
/* directions. */
/* */
/* <Fields> */
/* xMin :: The horizontal minimum (left-most). */
/* */
/* yMin :: The vertical minimum (bottom-most). */
/* */
/* xMax :: The horizontal maximum (right-most). */
/* */
/* yMax :: The vertical maximum (top-most). */
/* */
/* <Note> */
/* The bounding box is specified with the coordinates of the lower */
/* left and the upper right corner. In PostScript, those values are */
/* often called (llx,lly) and (urx,ury), respectively. */
/* */
/* If `yMin' is negative, this value gives the glyph's descender. */
/* Otherwise, the glyph doesn't descend below the baseline. */
/* Similarly, if `ymax' is positive, this value gives the glyph's */
/* ascender. */
/* */
/* `xMin' gives the horizontal distance from the glyph's origin to */
/* the left edge of the glyph's bounding box. If `xMin' is negative, */
/* the glyph extends to the left of the origin. */
/* */
typedef struct SW_FT_BBox_
{
SW_FT_Pos xMin, yMin;
SW_FT_Pos xMax, yMax;
} SW_FT_BBox;
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Outline */
/* */
/* <Description> */
/* This structure is used to describe an outline to the scan-line */
/* converter. */
/* */
/* <Fields> */
/* n_contours :: The number of contours in the outline. */
/* */
/* n_points :: The number of points in the outline. */
/* */
/* points :: A pointer to an array of `n_points' @SW_FT_Vector */
/* elements, giving the outline's point coordinates. */
/* */
/* tags :: A pointer to an array of `n_points' chars, giving */
/* each outline point's type. */
/* */
/* If bit~0 is unset, the point is `off' the curve, */
/* i.e., a Bézier control point, while it is `on' if */
/* set. */
/* */
/* Bit~1 is meaningful for `off' points only. If set, */
/* it indicates a third-order Bézier arc control point; */
/* and a second-order control point if unset. */
/* */
/* If bit~2 is set, bits 5-7 contain the drop-out mode */
/* (as defined in the OpenType specification; the value */
/* is the same as the argument to the SCANMODE */
/* instruction). */
/* */
/* Bits 3 and~4 are reserved for internal purposes. */
/* */
/* contours :: An array of `n_contours' shorts, giving the end */
/* point of each contour within the outline. For */
/* example, the first contour is defined by the points */
/* `0' to `contours[0]', the second one is defined by */
/* the points `contours[0]+1' to `contours[1]', etc. */
/* */
/* flags :: A set of bit flags used to characterize the outline */
/* and give hints to the scan-converter and hinter on */
/* how to convert/grid-fit it. See @SW_FT_OUTLINE_FLAGS.*/
/* */
typedef struct SW_FT_Outline_
{
short n_contours; /* number of contours in glyph */
short n_points; /* number of points in the glyph */
SW_FT_Vector* points; /* the outline's points */
char* tags; /* the points flags */
short* contours; /* the contour end points */
int flags; /* outline masks */
} SW_FT_Outline;
/*************************************************************************/
/* */
/* <Enum> */
/* SW_FT_OUTLINE_FLAGS */
/* */
/* <Description> */
/* A list of bit-field constants use for the flags in an outline's */
/* `flags' field. */
/* */
/* <Values> */
/* SW_FT_OUTLINE_NONE :: */
/* Value~0 is reserved. */
/* */
/* SW_FT_OUTLINE_OWNER :: */
/* If set, this flag indicates that the outline's field arrays */
/* (i.e., `points', `flags', and `contours') are `owned' by the */
/* outline object, and should thus be freed when it is destroyed. */
/* */
/* SW_FT_OUTLINE_EVEN_ODD_FILL :: */
/* By default, outlines are filled using the non-zero winding rule. */
/* If set to 1, the outline will be filled using the even-odd fill */
/* rule (only works with the smooth rasterizer). */
/* */
/* SW_FT_OUTLINE_REVERSE_FILL :: */
/* By default, outside contours of an outline are oriented in */
/* clock-wise direction, as defined in the TrueType specification. */
/* This flag is set if the outline uses the opposite direction */
/* (typically for Type~1 fonts). This flag is ignored by the scan */
/* converter. */
/* */
/* */
/* */
/* There exists a second mechanism to pass the drop-out mode to the */
/* B/W rasterizer; see the `tags' field in @SW_FT_Outline. */
/* */
/* Please refer to the description of the `SCANTYPE' instruction in */
/* the OpenType specification (in file `ttinst1.doc') how simple */
/* drop-outs, smart drop-outs, and stubs are defined. */
/* */
#define SW_FT_OUTLINE_NONE 0x0
#define SW_FT_OUTLINE_OWNER 0x1
#define SW_FT_OUTLINE_EVEN_ODD_FILL 0x2
#define SW_FT_OUTLINE_REVERSE_FILL 0x4
/* */
#define SW_FT_CURVE_TAG( flag ) ( flag & 3 )
#define SW_FT_CURVE_TAG_ON 1
#define SW_FT_CURVE_TAG_CONIC 0
#define SW_FT_CURVE_TAG_CUBIC 2
#define SW_FT_Curve_Tag_On SW_FT_CURVE_TAG_ON
#define SW_FT_Curve_Tag_Conic SW_FT_CURVE_TAG_CONIC
#define SW_FT_Curve_Tag_Cubic SW_FT_CURVE_TAG_CUBIC
/*************************************************************************/
/* */
/* A raster is a scan converter, in charge of rendering an outline into */
/* a a bitmap. This section contains the public API for rasters. */
/* */
/* Note that in FreeType 2, all rasters are now encapsulated within */
/* specific modules called `renderers'. See `ftrender.h' for more */
/* details on renderers. */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Raster */
/* */
/* <Description> */
/* A handle (pointer) to a raster object. Each object can be used */
/* independently to convert an outline into a bitmap or pixmap. */
/* */
typedef struct SW_FT_RasterRec_* SW_FT_Raster;
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Span */
/* */
/* <Description> */
/* A structure used to model a single span of gray (or black) pixels */
/* when rendering a monochrome or anti-aliased bitmap. */
/* */
/* <Fields> */
/* x :: The span's horizontal start position. */
/* */
/* len :: The span's length in pixels. */
/* */
/* coverage :: The span color/coverage, ranging from 0 (background) */
/* to 255 (foreground). Only used for anti-aliased */
/* rendering. */
/* */
/* <Note> */
/* This structure is used by the span drawing callback type named */
/* @SW_FT_SpanFunc that takes the y~coordinate of the span as a */
/* parameter. */
/* */
/* The coverage value is always between 0 and 255. If you want less */
/* gray values, the callback function has to reduce them. */
/* */
typedef struct SW_FT_Span_
{
short x;
short y;
unsigned short len;
unsigned char coverage;
} SW_FT_Span;
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_SpanFunc */
/* */
/* <Description> */
/* A function used as a call-back by the anti-aliased renderer in */
/* order to let client applications draw themselves the gray pixel */
/* spans on each scan line. */
/* */
/* <Input> */
/* y :: The scanline's y~coordinate. */
/* */
/* count :: The number of spans to draw on this scanline. */
/* */
/* spans :: A table of `count' spans to draw on the scanline. */
/* */
/* user :: User-supplied data that is passed to the callback. */
/* */
/* <Note> */
/* This callback allows client applications to directly render the */
/* gray spans of the anti-aliased bitmap to any kind of surfaces. */
/* */
/* This can be used to write anti-aliased outlines directly to a */
/* given background bitmap, and even perform translucency. */
/* */
/* Note that the `count' field cannot be greater than a fixed value */
/* defined by the `SW_FT_MAX_GRAY_SPANS' configuration macro in */
/* `ftoption.h'. By default, this value is set to~32, which means */
/* that if there are more than 32~spans on a given scanline, the */
/* callback is called several times with the same `y' parameter in */
/* order to draw all callbacks. */
/* */
/* Otherwise, the callback is only called once per scan-line, and */
/* only for those scanlines that do have `gray' pixels on them. */
/* */
typedef void
(*SW_FT_SpanFunc)( int count,
const SW_FT_Span* spans,
void* user );
#define SW_FT_Raster_Span_Func SW_FT_SpanFunc
/*************************************************************************/
/* */
/* <Enum> */
/* SW_FT_RASTER_FLAG_XXX */
/* */
/* <Description> */
/* A list of bit flag constants as used in the `flags' field of a */
/* @SW_FT_Raster_Params structure. */
/* */
/* <Values> */
/* SW_FT_RASTER_FLAG_DEFAULT :: This value is 0. */
/* */
/* SW_FT_RASTER_FLAG_AA :: This flag is set to indicate that an */
/* anti-aliased glyph image should be */
/* generated. Otherwise, it will be */
/* monochrome (1-bit). */
/* */
/* SW_FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */
/* rendering. In this mode, client */
/* applications must provide their own span */
/* callback. This lets them directly */
/* draw or compose over an existing bitmap. */
/* If this bit is not set, the target */
/* pixmap's buffer _must_ be zeroed before */
/* rendering. */
/* */
/* Note that for now, direct rendering is */
/* only possible with anti-aliased glyphs. */
/* */
/* SW_FT_RASTER_FLAG_CLIP :: This flag is only used in direct */
/* rendering mode. If set, the output will */
/* be clipped to a box specified in the */
/* `clip_box' field of the */
/* @SW_FT_Raster_Params structure. */
/* */
/* Note that by default, the glyph bitmap */
/* is clipped to the target pixmap, except */
/* in direct rendering mode where all spans */
/* are generated if no clipping box is set. */
/* */
#define SW_FT_RASTER_FLAG_DEFAULT 0x0
#define SW_FT_RASTER_FLAG_AA 0x1
#define SW_FT_RASTER_FLAG_DIRECT 0x2
#define SW_FT_RASTER_FLAG_CLIP 0x4
/* deprecated */
#define ft_raster_flag_default SW_FT_RASTER_FLAG_DEFAULT
#define ft_raster_flag_aa SW_FT_RASTER_FLAG_AA
#define ft_raster_flag_direct SW_FT_RASTER_FLAG_DIRECT
#define ft_raster_flag_clip SW_FT_RASTER_FLAG_CLIP
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Raster_Params */
/* */
/* <Description> */
/* A structure to hold the arguments used by a raster's render */
/* function. */
/* */
/* <Fields> */
/* target :: The target bitmap. */
/* */
/* source :: A pointer to the source glyph image (e.g., an */
/* @SW_FT_Outline). */
/* */
/* flags :: The rendering flags. */
/* */
/* gray_spans :: The gray span drawing callback. */
/* */
/* black_spans :: The black span drawing callback. UNIMPLEMENTED! */
/* */
/* bit_test :: The bit test callback. UNIMPLEMENTED! */
/* */
/* bit_set :: The bit set callback. UNIMPLEMENTED! */
/* */
/* user :: User-supplied data that is passed to each drawing */
/* callback. */
/* */
/* clip_box :: An optional clipping box. It is only used in */
/* direct rendering mode. Note that coordinates here */
/* should be expressed in _integer_ pixels (and not in */
/* 26.6 fixed-point units). */
/* */
/* <Note> */
/* An anti-aliased glyph bitmap is drawn if the @SW_FT_RASTER_FLAG_AA */
/* bit flag is set in the `flags' field, otherwise a monochrome */
/* bitmap is generated. */
/* */
/* If the @SW_FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */
/* raster will call the `gray_spans' callback to draw gray pixel */
/* spans, in the case of an aa glyph bitmap, it will call */
/* `black_spans', and `bit_test' and `bit_set' in the case of a */
/* monochrome bitmap. This allows direct composition over a */
/* pre-existing bitmap through user-provided callbacks to perform the */
/* span drawing/composition. */
/* */
/* Note that the `bit_test' and `bit_set' callbacks are required when */
/* rendering a monochrome bitmap, as they are crucial to implement */
/* correct drop-out control as defined in the TrueType specification. */
/* */
typedef struct SW_FT_Raster_Params_
{
const void* source;
int flags;
SW_FT_SpanFunc gray_spans;
void* user;
SW_FT_BBox clip_box;
} SW_FT_Raster_Params;
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_Outline_Check */
/* */
/* <Description> */
/* Check the contents of an outline descriptor. */
/* */
/* <Input> */
/* outline :: A handle to a source outline. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
SW_FT_Error
SW_FT_Outline_Check( SW_FT_Outline* outline );
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_Outline_Get_CBox */
/* */
/* <Description> */
/* Return an outline's `control box'. The control box encloses all */
/* the outline's points, including Bézier control points. Though it */
/* coincides with the exact bounding box for most glyphs, it can be */
/* slightly larger in some situations (like when rotating an outline */
/* that contains Bézier outside arcs). */
/* */
/* Computing the control box is very fast, while getting the bounding */
/* box can take much more time as it needs to walk over all segments */
/* and arcs in the outline. To get the latter, you can use the */
/* `ftbbox' component, which is dedicated to this single task. */
/* */
/* <Input> */
/* outline :: A pointer to the source outline descriptor. */
/* */
/* <Output> */
/* acbox :: The outline's control box. */
/* */
/* <Note> */
/* See @SW_FT_Glyph_Get_CBox for a discussion of tricky fonts. */
/* */
void
SW_FT_Outline_Get_CBox( const SW_FT_Outline* outline,
SW_FT_BBox *acbox );
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_NewFunc */
/* */
/* <Description> */
/* A function used to create a new raster object. */
/* */
/* <Input> */
/* memory :: A handle to the memory allocator. */
/* */
/* <Output> */
/* raster :: A handle to the new raster object. */
/* */
/* <Return> */
/* Error code. 0~means success. */
/* */
/* <Note> */
/* The `memory' parameter is a typeless pointer in order to avoid */
/* un-wanted dependencies on the rest of the FreeType code. In */
/* practice, it is an @SW_FT_Memory object, i.e., a handle to the */
/* standard FreeType memory allocator. However, this field can be */
/* completely ignored by a given raster implementation. */
/* */
typedef int
(*SW_FT_Raster_NewFunc)( SW_FT_Raster* raster );
#define SW_FT_Raster_New_Func SW_FT_Raster_NewFunc
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_DoneFunc */
/* */
/* <Description> */
/* A function used to destroy a given raster object. */
/* */
/* <Input> */
/* raster :: A handle to the raster object. */
/* */
typedef void
(*SW_FT_Raster_DoneFunc)( SW_FT_Raster raster );
#define SW_FT_Raster_Done_Func SW_FT_Raster_DoneFunc
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_ResetFunc */
/* */
/* <Description> */
/* FreeType provides an area of memory called the `render pool', */
/* available to all registered rasters. This pool can be freely used */
/* during a given scan-conversion but is shared by all rasters. Its */
/* content is thus transient. */
/* */
/* This function is called each time the render pool changes, or just */
/* after a new raster object is created. */
/* */
/* <Input> */
/* raster :: A handle to the new raster object. */
/* */
/* pool_base :: The address in memory of the render pool. */
/* */
/* pool_size :: The size in bytes of the render pool. */
/* */
/* <Note> */
/* Rasters can ignore the render pool and rely on dynamic memory */
/* allocation if they want to (a handle to the memory allocator is */
/* passed to the raster constructor). However, this is not */
/* recommended for efficiency purposes. */
/* */
typedef void
(*SW_FT_Raster_ResetFunc)( SW_FT_Raster raster,
unsigned char* pool_base,
unsigned long pool_size );
#define SW_FT_Raster_Reset_Func SW_FT_Raster_ResetFunc
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_RenderFunc */
/* */
/* <Description> */
/* Invoke a given raster to scan-convert a given glyph image into a */
/* target bitmap. */
/* */
/* <Input> */
/* raster :: A handle to the raster object. */
/* */
/* params :: A pointer to an @SW_FT_Raster_Params structure used to */
/* store the rendering parameters. */
/* */
/* <Return> */
/* Error code. 0~means success. */
/* */
/* <Note> */
/* The exact format of the source image depends on the raster's glyph */
/* format defined in its @SW_FT_Raster_Funcs structure. It can be an */
/* @SW_FT_Outline or anything else in order to support a large array of */
/* glyph formats. */
/* */
/* Note also that the render function can fail and return a */
/* `SW_FT_Err_Unimplemented_Feature' error code if the raster used does */
/* not support direct composition. */
/* */
/* XXX: For now, the standard raster doesn't support direct */
/* composition but this should change for the final release (see */
/* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */
/* for examples of distinct implementations that support direct */
/* composition). */
/* */
typedef int
(*SW_FT_Raster_RenderFunc)( SW_FT_Raster raster,
const SW_FT_Raster_Params* params );
#define SW_FT_Raster_Render_Func SW_FT_Raster_RenderFunc
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Raster_Funcs */
/* */
/* <Description> */
/* A structure used to describe a given raster class to the library. */
/* */
/* <Fields> */
/* glyph_format :: The supported glyph format for this raster. */
/* */
/* raster_new :: The raster constructor. */
/* */
/* raster_reset :: Used to reset the render pool within the raster. */
/* */
/* raster_render :: A function to render a glyph into a given bitmap. */
/* */
/* raster_done :: The raster destructor. */
/* */
typedef struct SW_FT_Raster_Funcs_
{
SW_FT_Raster_NewFunc raster_new;
SW_FT_Raster_ResetFunc raster_reset;
SW_FT_Raster_RenderFunc raster_render;
SW_FT_Raster_DoneFunc raster_done;
} SW_FT_Raster_Funcs;
extern const SW_FT_Raster_Funcs sw_ft_grays_raster;
#endif // SW_FT_IMG_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,325 @@
#ifndef SW_FT_STROKER_H
#define SW_FT_STROKER_H
/***************************************************************************/
/* */
/* ftstroke.h */
/* */
/* FreeType path stroker (specification). */
/* */
/* Copyright 2002-2006, 2008, 2009, 2011-2012 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include "sw_ft_raster.h"
/**************************************************************
*
* @type:
* SW_FT_Stroker
*
* @description:
* Opaque handler to a path stroker object.
*/
typedef struct SW_FT_StrokerRec_* SW_FT_Stroker;
/**************************************************************
*
* @enum:
* SW_FT_Stroker_LineJoin
*
* @description:
* These values determine how two joining lines are rendered
* in a stroker.
*
* @values:
* SW_FT_STROKER_LINEJOIN_ROUND ::
* Used to render rounded line joins. Circular arcs are used
* to join two lines smoothly.
*
* SW_FT_STROKER_LINEJOIN_BEVEL ::
* Used to render beveled line joins. The outer corner of
* the joined lines is filled by enclosing the triangular
* region of the corner with a straight line between the
* outer corners of each stroke.
*
* SW_FT_STROKER_LINEJOIN_MITER_FIXED ::
* Used to render mitered line joins, with fixed bevels if the
* miter limit is exceeded. The outer edges of the strokes
* for the two segments are extended until they meet at an
* angle. If the segments meet at too sharp an angle (such
* that the miter would extend from the intersection of the
* segments a distance greater than the product of the miter
* limit value and the border radius), then a bevel join (see
* above) is used instead. This prevents long spikes being
* created. SW_FT_STROKER_LINEJOIN_MITER_FIXED generates a miter
* line join as used in PostScript and PDF.
*
* SW_FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* SW_FT_STROKER_LINEJOIN_MITER ::
* Used to render mitered line joins, with variable bevels if
* the miter limit is exceeded. The intersection of the
* strokes is clipped at a line perpendicular to the bisector
* of the angle between the strokes, at the distance from the
* intersection of the segments equal to the product of the
* miter limit value and the border radius. This prevents
* long spikes being created.
* SW_FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line
* join as used in XPS. SW_FT_STROKER_LINEJOIN_MITER is an alias
* for SW_FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for
* backwards compatibility.
*/
typedef enum SW_FT_Stroker_LineJoin_
{
SW_FT_STROKER_LINEJOIN_ROUND = 0,
SW_FT_STROKER_LINEJOIN_BEVEL = 1,
SW_FT_STROKER_LINEJOIN_MITER_VARIABLE = 2,
SW_FT_STROKER_LINEJOIN_MITER = SW_FT_STROKER_LINEJOIN_MITER_VARIABLE,
SW_FT_STROKER_LINEJOIN_MITER_FIXED = 3
} SW_FT_Stroker_LineJoin;
/**************************************************************
*
* @enum:
* SW_FT_Stroker_LineCap
*
* @description:
* These values determine how the end of opened sub-paths are
* rendered in a stroke.
*
* @values:
* SW_FT_STROKER_LINECAP_BUTT ::
* The end of lines is rendered as a full stop on the last
* point itself.
*
* SW_FT_STROKER_LINECAP_ROUND ::
* The end of lines is rendered as a half-circle around the
* last point.
*
* SW_FT_STROKER_LINECAP_SQUARE ::
* The end of lines is rendered as a square around the
* last point.
*/
typedef enum SW_FT_Stroker_LineCap_
{
SW_FT_STROKER_LINECAP_BUTT = 0,
SW_FT_STROKER_LINECAP_ROUND,
SW_FT_STROKER_LINECAP_SQUARE
} SW_FT_Stroker_LineCap;
/**************************************************************
*
* @enum:
* SW_FT_StrokerBorder
*
* @description:
* These values are used to select a given stroke border
* in @SW_FT_Stroker_GetBorderCounts and @SW_FT_Stroker_ExportBorder.
*
* @values:
* SW_FT_STROKER_BORDER_LEFT ::
* Select the left border, relative to the drawing direction.
*
* SW_FT_STROKER_BORDER_RIGHT ::
* Select the right border, relative to the drawing direction.
*
* @note:
* Applications are generally interested in the `inside' and `outside'
* borders. However, there is no direct mapping between these and the
* `left' and `right' ones, since this really depends on the glyph's
* drawing orientation, which varies between font formats.
*
* You can however use @SW_FT_Outline_GetInsideBorder and
* @SW_FT_Outline_GetOutsideBorder to get these.
*/
typedef enum SW_FT_StrokerBorder_
{
SW_FT_STROKER_BORDER_LEFT = 0,
SW_FT_STROKER_BORDER_RIGHT
} SW_FT_StrokerBorder;
/**************************************************************
*
* @function:
* SW_FT_Stroker_New
*
* @description:
* Create a new stroker object.
*
* @input:
* library ::
* FreeType library handle.
*
* @output:
* astroker ::
* A new stroker object handle. NULL in case of error.
*
* @return:
* FreeType error code. 0~means success.
*/
SW_FT_Error
SW_FT_Stroker_New( SW_FT_Stroker *astroker );
/**************************************************************
*
* @function:
* SW_FT_Stroker_Set
*
* @description:
* Reset a stroker object's attributes.
*
* @input:
* stroker ::
* The target stroker handle.
*
* radius ::
* The border radius.
*
* line_cap ::
* The line cap style.
*
* line_join ::
* The line join style.
*
* miter_limit ::
* The miter limit for the SW_FT_STROKER_LINEJOIN_MITER_FIXED and
* SW_FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles,
* expressed as 16.16 fixed-point value.
*
* @note:
* The radius is expressed in the same units as the outline
* coordinates.
*/
void
SW_FT_Stroker_Set( SW_FT_Stroker stroker,
SW_FT_Fixed radius,
SW_FT_Stroker_LineCap line_cap,
SW_FT_Stroker_LineJoin line_join,
SW_FT_Fixed miter_limit );
/**************************************************************
*
* @function:
* SW_FT_Stroker_ParseOutline
*
* @description:
* A convenience function used to parse a whole outline with
* the stroker. The resulting outline(s) can be retrieved
* later by functions like @SW_FT_Stroker_GetCounts and @SW_FT_Stroker_Export.
*
* @input:
* stroker ::
* The target stroker handle.
*
* outline ::
* The source outline.
*
* opened ::
* A boolean. If~1, the outline is treated as an open path instead
* of a closed one.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
* If `opened' is~0 (the default), the outline is treated as a closed
* path, and the stroker generates two distinct `border' outlines.
*
* If `opened' is~1, the outline is processed as an open path, and the
* stroker generates a single `stroke' outline.
*
* This function calls @SW_FT_Stroker_Rewind automatically.
*/
SW_FT_Error
SW_FT_Stroker_ParseOutline( SW_FT_Stroker stroker,
SW_FT_Outline* outline,
SW_FT_Bool opened );
/**************************************************************
*
* @function:
* SW_FT_Stroker_GetCounts
*
* @description:
* Call this function once you have finished parsing your paths
* with the stroker. It returns the number of points and
* contours necessary to export all points/borders from the stroked
* outline/path.
*
* @input:
* stroker ::
* The target stroker handle.
*
* @output:
* anum_points ::
* The number of points.
*
* anum_contours ::
* The number of contours.
*
* @return:
* FreeType error code. 0~means success.
*/
SW_FT_Error
SW_FT_Stroker_GetCounts( SW_FT_Stroker stroker,
SW_FT_UInt *anum_points,
SW_FT_UInt *anum_contours );
/**************************************************************
*
* @function:
* SW_FT_Stroker_Export
*
* @description:
* Call this function after @SW_FT_Stroker_GetBorderCounts to
* export all borders to your own @SW_FT_Outline structure.
*
* Note that this function appends the border points and
* contours to your outline, but does not try to resize its
* arrays.
*
* @input:
* stroker ::
* The target stroker handle.
*
* outline ::
* The target outline handle.
*/
void
SW_FT_Stroker_Export( SW_FT_Stroker stroker,
SW_FT_Outline* outline );
/**************************************************************
*
* @function:
* SW_FT_Stroker_Done
*
* @description:
* Destroy a stroker object.
*
* @input:
* stroker ::
* A stroker handle. Can be NULL.
*/
void
SW_FT_Stroker_Done( SW_FT_Stroker stroker );
#endif // SW_FT_STROKER_H

View File

@ -0,0 +1,160 @@
#ifndef SW_FT_TYPES_H
#define SW_FT_TYPES_H
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Fixed */
/* */
/* <Description> */
/* This type is used to store 16.16 fixed-point values, like scaling */
/* values or matrix coefficients. */
/* */
typedef signed long SW_FT_Fixed;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Int */
/* */
/* <Description> */
/* A typedef for the int type. */
/* */
typedef signed int SW_FT_Int;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_UInt */
/* */
/* <Description> */
/* A typedef for the unsigned int type. */
/* */
typedef unsigned int SW_FT_UInt;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Long */
/* */
/* <Description> */
/* A typedef for signed long. */
/* */
typedef signed long SW_FT_Long;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_ULong */
/* */
/* <Description> */
/* A typedef for unsigned long. */
/* */
typedef unsigned long SW_FT_ULong;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Short */
/* */
/* <Description> */
/* A typedef for signed short. */
/* */
typedef signed short SW_FT_Short;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Byte */
/* */
/* <Description> */
/* A simple typedef for the _unsigned_ char type. */
/* */
typedef unsigned char SW_FT_Byte;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Bool */
/* */
/* <Description> */
/* A typedef of unsigned char, used for simple booleans. As usual, */
/* values 1 and~0 represent true and false, respectively. */
/* */
typedef unsigned char SW_FT_Bool;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Error */
/* */
/* <Description> */
/* The FreeType error code type. A value of~0 is always interpreted */
/* as a successful operation. */
/* */
typedef int SW_FT_Error;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Pos */
/* */
/* <Description> */
/* The type SW_FT_Pos is used to store vectorial coordinates. Depending */
/* on the context, these can represent distances in integer font */
/* units, or 16.16, or 26.6 fixed-point pixel coordinates. */
/* */
typedef signed long SW_FT_Pos;
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Vector */
/* */
/* <Description> */
/* A simple structure used to store a 2D vector; coordinates are of */
/* the SW_FT_Pos type. */
/* */
/* <Fields> */
/* x :: The horizontal coordinate. */
/* y :: The vertical coordinate. */
/* */
typedef struct SW_FT_Vector_
{
SW_FT_Pos x;
SW_FT_Pos y;
} SW_FT_Vector;
typedef long long int SW_FT_Int64;
typedef unsigned long long int SW_FT_UInt64;
typedef signed int SW_FT_Int32;
typedef unsigned int SW_FT_UInt32;
#define SW_FT_BOOL( x ) ( (SW_FT_Bool)( x ) )
#define SW_FT_SIZEOF_LONG 4
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#endif // SW_FT_TYPES_H