forked from enlightenment/efl
ector: add software backend using FreeType rasterizer.
This commit is contained in:
parent
e99774946c
commit
891ec14585
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,12 @@
|
|||
class Ector.Renderer.Software.Base (Ector.Renderer.Generic.Base)
|
||||
{
|
||||
legacy_prefix: null;
|
||||
methods {
|
||||
fill {
|
||||
return: bool;
|
||||
}
|
||||
}
|
||||
implements {
|
||||
@virtual .fill;
|
||||
}
|
||||
}
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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, ¶ms);
|
||||
|
||||
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);
|
||||
}
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 */
|
||||
|
|
@ -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
|
@ -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
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue