2009-10-22 08:47:30 -07:00
|
|
|
#include "evas_common.h"
|
|
|
|
#include "evas_private.h"
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
static void
|
2009-10-28 01:59:01 -07:00
|
|
|
_evas_map_calc_geom_change(Evas_Object *obj)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
|
|
|
int is, was = 0, pass = 0;
|
2009-10-22 13:11:33 -07:00
|
|
|
|
2009-10-22 08:47:30 -07:00
|
|
|
evas_object_change(obj);
|
|
|
|
evas_object_clip_dirty(obj);
|
|
|
|
if (obj->layer->evas->events_frozen <= 0)
|
|
|
|
{
|
|
|
|
evas_object_recalc_clippees(obj);
|
|
|
|
if (!pass)
|
|
|
|
{
|
|
|
|
if (!obj->smart.smart)
|
|
|
|
{
|
|
|
|
is = evas_object_is_in_output_rect(obj,
|
|
|
|
obj->layer->evas->pointer.x,
|
|
|
|
obj->layer->evas->pointer.y, 1, 1);
|
|
|
|
if ((is ^ was) && obj->cur.visible)
|
|
|
|
evas_event_feed_mouse_move(obj->layer->evas,
|
|
|
|
obj->layer->evas->pointer.x,
|
|
|
|
obj->layer->evas->pointer.y,
|
|
|
|
obj->layer->evas->last_timestamp,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
evas_object_inform_call_move(obj);
|
|
|
|
evas_object_inform_call_resize(obj);
|
|
|
|
}
|
|
|
|
|
2009-10-28 01:59:01 -07:00
|
|
|
static void
|
|
|
|
_evas_map_calc_map_geometry(Evas_Object *obj)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-28 01:59:01 -07:00
|
|
|
Evas_Coord x1, x2, y1, y2;
|
|
|
|
const Evas_Map_Point *p, *p_end;
|
2010-01-25 03:04:32 -08:00
|
|
|
int ch;
|
2009-10-22 08:47:30 -07:00
|
|
|
|
2009-10-28 01:59:01 -07:00
|
|
|
if (!obj->cur.map) return;
|
|
|
|
p = obj->cur.map->points;
|
2009-11-03 07:41:36 -08:00
|
|
|
p_end = p + obj->cur.map->count;
|
2009-10-28 01:59:01 -07:00
|
|
|
x1 = p->x;
|
|
|
|
x2 = p->x;
|
|
|
|
y1 = p->y;
|
|
|
|
y2 = p->y;
|
|
|
|
p++;
|
|
|
|
for (; p < p_end; p++)
|
|
|
|
{
|
|
|
|
if (p->x < x1) x1 = p->x;
|
|
|
|
if (p->x > x2) x2 = p->x;
|
|
|
|
if (p->y < y1) y1 = p->y;
|
|
|
|
if (p->y > y2) y2 = p->y;
|
|
|
|
}
|
2010-01-25 03:04:32 -08:00
|
|
|
ch = 0;
|
|
|
|
if (obj->cur.map->normal_geometry.x != x1) ch = 1;
|
|
|
|
if (obj->cur.map->normal_geometry.y != y1) ch = 1;
|
|
|
|
if (obj->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
|
|
|
|
if (obj->cur.map->normal_geometry.h != (y2 - y1)) ch = 1;
|
2009-11-03 07:41:36 -08:00
|
|
|
obj->cur.map->normal_geometry.x = x1;
|
|
|
|
obj->cur.map->normal_geometry.y = y1;
|
|
|
|
obj->cur.map->normal_geometry.w = (x2 - x1);
|
|
|
|
obj->cur.map->normal_geometry.h = (y2 - y1);
|
2010-01-25 03:04:32 -08:00
|
|
|
if (ch) _evas_map_calc_geom_change(obj);
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
static inline Evas_Map *
|
2009-10-28 01:59:01 -07:00
|
|
|
_evas_map_new(int count)
|
2009-10-22 13:11:33 -07:00
|
|
|
{
|
2009-10-31 18:32:23 -07:00
|
|
|
int i;
|
2009-10-28 01:59:01 -07:00
|
|
|
Evas_Map *m = calloc(1, sizeof(Evas_Map) + count * sizeof(Evas_Map_Point));
|
|
|
|
if (!m) return NULL;
|
2009-10-22 13:11:33 -07:00
|
|
|
m->count = count;
|
2009-10-31 02:08:01 -07:00
|
|
|
m->alpha = 1;
|
|
|
|
m->smooth = 1;
|
2009-10-31 18:32:23 -07:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
m->points[i].r = 255;
|
|
|
|
m->points[i].g = 255;
|
|
|
|
m->points[i].b = 255;
|
|
|
|
m->points[i].a = 255;
|
|
|
|
}
|
2009-10-22 13:11:33 -07:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
_evas_map_copy(Evas_Map *dst, const Evas_Map *src)
|
|
|
|
{
|
|
|
|
if (dst->count != src->count)
|
|
|
|
{
|
2009-10-31 02:08:01 -07:00
|
|
|
ERR("cannot copy map of different sizes: dst=%i, src=%i", dst->count, src->count);
|
2009-10-22 13:11:33 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
|
2009-10-31 02:08:01 -07:00
|
|
|
dst->smooth = src->smooth;
|
|
|
|
dst->alpha = src->alpha;
|
2009-10-22 13:11:33 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-10-31 18:32:23 -07:00
|
|
|
static inline Evas_Map *
|
|
|
|
_evas_map_dup(const Evas_Map *orig)
|
|
|
|
{
|
|
|
|
Evas_Map *copy = _evas_map_new(orig->count);
|
|
|
|
if (!copy) return NULL;
|
|
|
|
memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
|
|
|
|
copy->smooth = orig->smooth;
|
|
|
|
copy->alpha = orig->alpha;
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
static inline void
|
2010-04-12 01:23:53 -07:00
|
|
|
_evas_map_free(Evas_Object *obj, Evas_Map *m)
|
2009-10-22 13:11:33 -07:00
|
|
|
{
|
2010-04-12 01:23:53 -07:00
|
|
|
if (obj)
|
|
|
|
{
|
|
|
|
if (m->surface)
|
|
|
|
obj->layer->evas->engine.func->image_map_surface_free
|
|
|
|
(obj->layer->evas->engine.data.output, m->surface);
|
|
|
|
}
|
2009-10-22 13:11:33 -07:00
|
|
|
free(m);
|
|
|
|
}
|
|
|
|
|
2009-11-05 07:24:48 -08:00
|
|
|
Eina_Bool
|
|
|
|
evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
|
|
|
|
Evas_Coord *mx, Evas_Coord *my, int grab)
|
|
|
|
{
|
2010-01-21 22:51:27 -08:00
|
|
|
int i, j, edges, edge[4][2], douv;
|
2009-11-05 07:24:48 -08:00
|
|
|
Evas_Coord xe[2];
|
2009-12-21 07:52:12 -08:00
|
|
|
double u[2] = { 0.0, 0.0 };
|
|
|
|
double v[2] = { 0.0, 0.0 };
|
2009-11-05 07:24:48 -08:00
|
|
|
|
|
|
|
if (m->count != 4) return 0;
|
|
|
|
// FIXME need to handle grab mode and extrapolte coords outside
|
|
|
|
// map
|
|
|
|
if (grab)
|
|
|
|
{
|
|
|
|
Evas_Coord ymin, ymax;
|
|
|
|
|
|
|
|
ymin = m->points[0].y;
|
|
|
|
ymax = m->points[0].y;
|
|
|
|
for (i = 1; i < m->count; i++)
|
|
|
|
{
|
|
|
|
if (m->points[i].y < ymin) ymin = m->points[i].y;
|
|
|
|
else if (m->points[i].y > ymax) ymax = m->points[i].y;
|
|
|
|
}
|
|
|
|
if (y <= ymin) y = ymin + 1;
|
|
|
|
if (y >= ymax) y = ymax - 1;
|
|
|
|
}
|
|
|
|
edges = 0;
|
|
|
|
for (i = 0; i < m->count; i++)
|
|
|
|
{
|
|
|
|
j = (i + 1) % m->count;
|
|
|
|
if ((m->points[i].y <= y) && (m->points[j].y > y))
|
|
|
|
{
|
|
|
|
edge[edges][0] = i;
|
|
|
|
edge[edges][1] = j;
|
|
|
|
edges++;
|
|
|
|
}
|
|
|
|
else if ((m->points[j].y <= y) && (m->points[i].y > y))
|
|
|
|
{
|
|
|
|
edge[edges][0] = j;
|
|
|
|
edge[edges][1] = i;
|
|
|
|
edges++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
douv = 0;
|
|
|
|
if ((mx) || (my)) douv = 1;
|
|
|
|
for (i = 0; i < (edges - 1); i+= 2)
|
|
|
|
{
|
2010-01-21 22:51:27 -08:00
|
|
|
Evas_Coord yp, yd;
|
|
|
|
|
2009-11-05 07:24:48 -08:00
|
|
|
j = i + 1;
|
|
|
|
yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
|
|
|
|
if (yd > 0)
|
|
|
|
{
|
|
|
|
yp = y - m->points[edge[i][0]].y;
|
|
|
|
xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
|
|
|
|
xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
|
|
|
|
if (douv)
|
|
|
|
{
|
|
|
|
u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
|
|
|
|
u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
|
|
|
|
v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
|
|
|
|
v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xe[0] = m->points[edge[i][0]].x;
|
|
|
|
if (douv)
|
|
|
|
{
|
|
|
|
u[0] = m->points[edge[i][0]].u;
|
|
|
|
v[0] = m->points[edge[i][0]].v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
|
|
|
|
if (yd > 0)
|
|
|
|
{
|
|
|
|
yp = y - m->points[edge[j][0]].y;
|
|
|
|
xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
|
|
|
|
xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
|
|
|
|
if (douv)
|
|
|
|
{
|
|
|
|
u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
|
|
|
|
u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
|
|
|
|
v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
|
|
|
|
v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xe[1] = m->points[edge[j][0]].x;
|
|
|
|
if (douv)
|
|
|
|
{
|
|
|
|
u[1] = m->points[edge[j][0]].u;
|
|
|
|
v[1] = m->points[edge[j][0]].v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (xe[0] > xe[1])
|
|
|
|
{
|
|
|
|
int ti;
|
|
|
|
|
|
|
|
ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
|
|
|
|
if (douv)
|
|
|
|
{
|
|
|
|
double td;
|
|
|
|
|
|
|
|
td = u[0]; u[0] = u[1]; u[1] = td;
|
|
|
|
td = v[0]; v[0] = v[1]; v[1] = td;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((x >= xe[0]) && (x < xe[1]))
|
|
|
|
{
|
|
|
|
if (douv)
|
|
|
|
{
|
|
|
|
if (mx)
|
|
|
|
*mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
|
|
|
|
(xe[1] - xe[0]));
|
|
|
|
if (my)
|
|
|
|
*my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
|
|
|
|
(xe[1] - xe[0]));
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (grab)
|
|
|
|
{
|
|
|
|
if (douv)
|
|
|
|
{
|
|
|
|
if (mx)
|
|
|
|
*mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
|
|
|
|
(xe[1] - xe[0]));
|
|
|
|
if (my)
|
|
|
|
*my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
|
|
|
|
(xe[1] - xe[0]));
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
|
|
|
|
{
|
|
|
|
return evas_map_coords_get(m, x, y, NULL, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-17 21:57:40 -07:00
|
|
|
/**
|
2010-03-27 22:40:42 -07:00
|
|
|
* Enable or disable the map that is set.
|
2009-10-28 01:59:01 -07:00
|
|
|
*
|
|
|
|
* This enables the map that is set or disables it. On enable, the object
|
|
|
|
* geometry will be saved, and the new geometry will change (position and
|
|
|
|
* size) to reflect the map geometry set. If none is set yet, this may be
|
|
|
|
* an undefined geometry, unless you have already set the map with
|
|
|
|
* evas_object_map_set(). It is suggested you first set a map with
|
2010-03-27 22:40:42 -07:00
|
|
|
* evas_object_map_set() with valid useful coordinates then enable and
|
2009-10-28 01:59:01 -07:00
|
|
|
* disable the map with evas_object_map_enable_set() as needed.
|
|
|
|
*
|
|
|
|
* @param obj object to enable the map on
|
2010-03-17 21:57:40 -07:00
|
|
|
* @param enabled enabled state
|
2009-10-28 01:59:01 -07:00
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
|
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
|
|
return;
|
|
|
|
MAGIC_CHECK_END();
|
2010-08-23 23:58:07 -07:00
|
|
|
enabled = !!enabled;
|
|
|
|
if (obj->cur.usemap == enabled) return;
|
|
|
|
obj->cur.usemap = enabled;
|
2009-10-28 01:59:01 -07:00
|
|
|
if (enabled)
|
|
|
|
{
|
|
|
|
if (!obj->cur.map)
|
|
|
|
obj->cur.map = _evas_map_new(4);
|
2010-08-31 15:16:08 -07:00
|
|
|
evas_object_mapped_clip_across_mark(obj);
|
2009-11-03 07:41:36 -08:00
|
|
|
// obj->cur.map->normal_geometry = obj->cur.geometry;
|
2009-10-28 01:59:01 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (obj->cur.map)
|
|
|
|
{
|
|
|
|
_evas_map_calc_geom_change(obj);
|
2010-08-31 15:16:08 -07:00
|
|
|
evas_object_mapped_clip_across_mark(obj);
|
2009-10-28 01:59:01 -07:00
|
|
|
}
|
|
|
|
}
|
2009-11-02 07:58:48 -08:00
|
|
|
_evas_map_calc_map_geometry(obj);
|
2010-03-27 22:40:42 -07:00
|
|
|
/* This is a bit heavy handed, but it fixes the case of same geometry, but
|
|
|
|
* changed colour or UV settings. */
|
|
|
|
evas_object_change(obj);
|
2009-10-28 01:59:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the map enabled state
|
|
|
|
*
|
|
|
|
* This returns the currently enabled state of the map on the object indicated.
|
|
|
|
* The default map enable state is off. You can enable and disable it with
|
|
|
|
* evas_object_map_enable_set().
|
|
|
|
*
|
|
|
|
* @param obj object to get the map enabled state from
|
|
|
|
* @return the map enabled state
|
|
|
|
*/
|
|
|
|
EAPI Eina_Bool
|
|
|
|
evas_object_map_enable_get(const Evas_Object *obj)
|
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
|
|
return 0;
|
|
|
|
MAGIC_CHECK_END();
|
|
|
|
return obj->cur.usemap;
|
|
|
|
}
|
|
|
|
|
2010-01-18 01:46:45 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the map sourc eobject
|
|
|
|
*
|
|
|
|
* This sets the object from which the map is taken - can be any object that
|
|
|
|
* has map enabled on it.
|
|
|
|
*
|
|
|
|
* Currently not implemented. for future use.
|
|
|
|
*
|
|
|
|
* @param obj object to set the map source of
|
|
|
|
* @param src the source object from which the map is taken
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_object_map_source_set(Evas_Object *obj, Evas_Object *src)
|
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
|
|
return;
|
|
|
|
MAGIC_CHECK_END();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the map source object
|
|
|
|
*
|
|
|
|
* See evas_object_map_source_set()
|
|
|
|
*
|
|
|
|
* @param obj object to set the map source of
|
|
|
|
* @return the object set as the source
|
|
|
|
*/
|
|
|
|
EAPI Evas_Object *
|
|
|
|
evas_object_map_source_get(const Evas_Object *obj)
|
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
|
|
return NULL;
|
|
|
|
MAGIC_CHECK_END();
|
2010-05-13 13:24:06 -07:00
|
|
|
return NULL;
|
2010-01-18 01:46:45 -08:00
|
|
|
}
|
|
|
|
|
2009-10-28 01:59:01 -07:00
|
|
|
/**
|
|
|
|
* Set current object transformation map.
|
|
|
|
*
|
|
|
|
* This sets the map on a given object. It is copied from the @p map pointer,
|
|
|
|
* so there is no need to keep the @p map object if you don't need it anymore.
|
|
|
|
*
|
|
|
|
* A map is a set of 4 points which have canvas x, y coordinates per point,
|
|
|
|
* with an optional z point value as a hint for perspective correction, if it
|
|
|
|
* is available. As well each point has u and v coordinates. These are like
|
|
|
|
* "texture coordinates" in OpenGL in that they define a point in the source
|
|
|
|
* image that is mapped to that map vertex/point. The u corresponds to the x
|
|
|
|
* coordinate of this mapped point and v, the y coordinate. Note that these
|
|
|
|
* coordinates describe a bounding region to sample. If you have a 200x100
|
|
|
|
* source image and wannt to display it at 200x100 with proper pixel
|
|
|
|
* precision, then do:
|
|
|
|
*
|
|
|
|
* @code
|
|
|
|
* Evas_Map *m = evas_map_new(4);
|
|
|
|
* evas_map_point_coord_set(m, 0, 0, 0, 0);
|
|
|
|
* evas_map_point_coord_set(m, 1, 200, 0, 0);
|
|
|
|
* evas_map_point_coord_set(m, 2, 200, 100, 0);
|
|
|
|
* evas_map_point_coord_set(m, 3, 0, 100, 0);
|
|
|
|
* evas_map_point_image_uv_set(m, 0, 0, 0);
|
|
|
|
* evas_map_point_image_uv_set(m, 1, 200, 0);
|
|
|
|
* evas_map_point_image_uv_set(m, 2, 200, 100);
|
|
|
|
* evas_map_point_image_uv_set(m, 3, 0, 100);
|
|
|
|
* evas_object_map_set(obj, m);
|
|
|
|
* evas_map_free(m);
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* Note that the map points a uv coordinates match the image geometry. If
|
|
|
|
* the @p map parameter is NULL, the sotred map will be freed and geometry
|
|
|
|
* prior to enabling/setting a map will be restored.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param obj object to change transformation map
|
|
|
|
* @param map new map to use
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @see evas_map_new()
|
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-22 13:11:33 -07:00
|
|
|
evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
|
|
return;
|
|
|
|
MAGIC_CHECK_END();
|
2009-10-22 13:11:33 -07:00
|
|
|
if (!map)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
if (obj->cur.map)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-31 02:08:01 -07:00
|
|
|
if (obj->cur.map->surface)
|
|
|
|
{
|
|
|
|
obj->layer->evas->engine.func->image_map_surface_free
|
|
|
|
(obj->layer->evas->engine.data.output,
|
|
|
|
obj->cur.map->surface);
|
|
|
|
obj->cur.map->surface = NULL;
|
|
|
|
}
|
2009-11-03 07:41:36 -08:00
|
|
|
obj->prev.geometry = obj->cur.map->normal_geometry;
|
2009-10-22 13:11:33 -07:00
|
|
|
if (!obj->prev.map)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2010-04-12 01:23:53 -07:00
|
|
|
_evas_map_free(obj, obj->cur.map);
|
2009-10-22 13:11:33 -07:00
|
|
|
obj->cur.map = NULL;
|
2009-10-22 08:47:30 -07:00
|
|
|
return;
|
|
|
|
}
|
2010-04-12 01:23:53 -07:00
|
|
|
_evas_map_free(obj, obj->cur.map);
|
2009-10-22 13:11:33 -07:00
|
|
|
obj->cur.map = NULL;
|
2009-10-28 01:59:01 -07:00
|
|
|
if (!obj->cur.usemap) _evas_map_calc_geom_change(obj);
|
|
|
|
else _evas_map_calc_map_geometry(obj);
|
2010-08-31 15:16:08 -07:00
|
|
|
if (obj->cur.usemap)
|
|
|
|
evas_object_mapped_clip_across_mark(obj);
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2009-10-22 13:11:33 -07:00
|
|
|
if (!obj->cur.map)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
obj->cur.map = _evas_map_dup(map);
|
|
|
|
obj->prev.map = NULL;
|
2010-08-31 15:16:08 -07:00
|
|
|
if (obj->cur.usemap)
|
|
|
|
evas_object_mapped_clip_across_mark(obj);
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
_evas_map_copy(obj->cur.map, map);
|
|
|
|
obj->prev.map = NULL;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
2009-11-02 07:58:48 -08:00
|
|
|
_evas_map_calc_map_geometry(obj);
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
|
|
|
* Get current object transformation map.
|
2009-10-28 01:59:01 -07:00
|
|
|
*
|
|
|
|
* This returns the current internal map set on the indicated object. It is
|
|
|
|
* intended for read-only acces and is only valid as long as the object is
|
|
|
|
* not deleted or the map on the object is not changed. If you wish to modify
|
|
|
|
* the map and set it back do the following:
|
|
|
|
*
|
|
|
|
* @code
|
|
|
|
* const Evas_Map *m = evas_object_map_get(obj);
|
|
|
|
* Evas_Map *m2 = evas_map_dup(m);
|
|
|
|
* evas_map_util_rotate(m2, 30.0, 0, 0);
|
|
|
|
* evas_object_map_set(obj);
|
|
|
|
* evas_map_free(m2);
|
|
|
|
* @endcode
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @param obj object to query transformation map.
|
2009-10-28 01:59:01 -07:00
|
|
|
* @return map reference to map in use. This is an internal data structure, so
|
|
|
|
* do not modify it.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @see evas_object_map_set()
|
|
|
|
*/
|
|
|
|
EAPI const Evas_Map *
|
|
|
|
evas_object_map_get(const Evas_Object *obj)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
2009-10-22 13:11:33 -07:00
|
|
|
return NULL;
|
2009-10-22 08:47:30 -07:00
|
|
|
MAGIC_CHECK_END();
|
2009-10-28 01:59:01 -07:00
|
|
|
if (obj->cur.map) return obj->cur.map;
|
|
|
|
return NULL;
|
2009-10-22 13:11:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-10-28 01:59:01 -07:00
|
|
|
* Create map of transformation points to be later used with an evas object.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* This creates a set of points (currently only 4 is supported. no other
|
|
|
|
* number for @p count will work). That is empty and ready to be modified
|
|
|
|
* with evas_map calls.
|
|
|
|
*
|
|
|
|
* @param count number of points in the map. *
|
|
|
|
* @return a newly allocated map or NULL on errors.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @see evas_map_free()
|
|
|
|
* @see evas_map_dup()
|
|
|
|
* @see evas_map_point_coord_set()
|
|
|
|
* @see evas_map_point_image_uv_set()
|
2009-11-11 04:33:52 -08:00
|
|
|
* @see evas_map_util_points_populate_from_object_full()
|
|
|
|
* @see evas_map_util_points_populate_from_object()
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @see evas_object_map_set()
|
|
|
|
*/
|
|
|
|
EAPI Evas_Map *
|
2009-10-28 01:59:01 -07:00
|
|
|
evas_map_new(int count)
|
2009-10-22 13:11:33 -07:00
|
|
|
{
|
|
|
|
if (count != 4)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-31 02:08:01 -07:00
|
|
|
ERR("num (%i) != 4 is unsupported!", count);
|
2009-10-22 13:11:33 -07:00
|
|
|
return NULL;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
2009-10-22 13:11:33 -07:00
|
|
|
return _evas_map_new(count);
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-31 02:08:01 -07:00
|
|
|
/**
|
|
|
|
* Set the smoothing for map rendering
|
|
|
|
*
|
|
|
|
* This sets smoothing for map rendering. If the object is a type that has
|
|
|
|
* its own smoothing settings, then both the smooth settings for this object
|
|
|
|
* and the map must be turned off. By default smooth maps are enabled.
|
|
|
|
*
|
|
|
|
* @param m map to modify. Must not be NULL.
|
|
|
|
* @param enabled enable or disable smooth map rendering
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
|
|
|
|
{
|
|
|
|
if (!m) return;
|
|
|
|
m->smooth = enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the smoothing for map rendering
|
|
|
|
*
|
|
|
|
* This gets smoothing for map rendering.
|
|
|
|
*
|
|
|
|
* @param m map to get the smooth from. Must not be NULL.
|
|
|
|
*/
|
|
|
|
EAPI Eina_Bool
|
|
|
|
evas_map_smooth_get(const Evas_Map *m)
|
|
|
|
{
|
|
|
|
if (!m) return 0;
|
|
|
|
return m->smooth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the alpha flag for map rendering
|
|
|
|
*
|
|
|
|
* This sets alpha flag for map rendering. If the object is a type that has
|
|
|
|
* its own alpha settings, then this will take precedence. Only image objects
|
|
|
|
* have this currently. Fits stops alpha blending of the map area, and is
|
|
|
|
* useful if you know the object and/or all sub-objects is 100% solid.
|
|
|
|
*
|
|
|
|
* @param m map to modify. Must not be NULL.
|
|
|
|
* @param enabled enable or disable alpha map rendering
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
|
|
|
|
{
|
|
|
|
if (!m) return;
|
|
|
|
m->alpha = enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the alpha flag for map rendering
|
|
|
|
*
|
|
|
|
* This gets the alph flag for map rendering.
|
|
|
|
*
|
|
|
|
* @param m map to get the alpha from. Must not be NULL.
|
|
|
|
*/
|
|
|
|
EAPI Eina_Bool
|
|
|
|
evas_map_alpha_get(const Evas_Map *m)
|
|
|
|
{
|
|
|
|
if (!m) return 0;
|
|
|
|
return m->alpha;
|
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
|
|
|
* Copy a previously allocated map.
|
2009-10-28 01:59:01 -07:00
|
|
|
*
|
|
|
|
* This makes a duplicate of the @p m object and returns it.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param m map to copy. Must not be NULL.
|
|
|
|
* @return newly allocated map with the same count and contents as @p m.
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
|
|
|
EAPI Evas_Map *
|
|
|
|
evas_map_dup(const Evas_Map *m)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
if (!m) return NULL;
|
|
|
|
return _evas_map_dup(m);
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
2009-10-28 01:59:01 -07:00
|
|
|
* Free a previously allocated map.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* This frees a givem map @p m and all memory associated with it. You must NOT
|
|
|
|
* free a map returned by evas_object_map_get() as this is internal.
|
|
|
|
*
|
|
|
|
* @param m map to free.
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-22 13:11:33 -07:00
|
|
|
evas_map_free(Evas_Map *m)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
if (!m) return;
|
2010-04-12 01:23:53 -07:00
|
|
|
_evas_map_free(NULL, m);
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
|
|
|
* Change the map point's coordinate.
|
2009-10-28 01:59:01 -07:00
|
|
|
*
|
|
|
|
* This sets the fixen point's coordinate in the map. Note that points
|
|
|
|
* describe the outline of a quadrangle and are ordered either clockwise
|
|
|
|
* or anit-clock-wise. It is suggested to keep your quadrangles concave and
|
|
|
|
* non-complex, though these polygon modes may work, they may not render
|
|
|
|
* a desired set of output. The quadrangle will use points 0 and 1 , 1 and 2,
|
|
|
|
* 2 and 3, and 3 and 0 to describe the edges of the quandrangle.
|
|
|
|
*
|
|
|
|
* The X and Y and Z coordinates are in canvas units. Z is optional and may
|
|
|
|
* or may not be honored in drawing. Z is a hint and does not affect the
|
|
|
|
* X and Y rendered coordinates. It may be used for calculating fills with
|
|
|
|
* perspective correct rendering.
|
|
|
|
*
|
|
|
|
* Remember all coordinates are canvas global ones like with move and reize
|
|
|
|
* in evas.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @param m map to change point. Must not be @c NULL.
|
|
|
|
* @param idx index of point to change. Must be smaller than map size.
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param x Point X Coordinate
|
|
|
|
* @param y Point Y Coordinate
|
|
|
|
* @param z Point Z Coordinate hint (pre-perspective transform)
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @see evas_map_util_rotate()
|
|
|
|
* @see evas_map_util_zoom()
|
2009-11-11 04:33:52 -08:00
|
|
|
* @see evas_map_util_points_populate_from_object_full()
|
|
|
|
* @see evas_map_util_points_populate_from_object()
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-28 01:59:01 -07:00
|
|
|
evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
Evas_Map_Point *p;
|
|
|
|
if (!m) return;
|
|
|
|
if (idx >= m->count) return;
|
|
|
|
p = m->points + idx;
|
|
|
|
p->x = x;
|
|
|
|
p->y = y;
|
|
|
|
p->z = z;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
|
|
|
* Get the map point's coordinate.
|
2009-10-28 01:59:01 -07:00
|
|
|
*
|
|
|
|
* This returns the coordinates of the given point in the map.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param m map to query point.
|
2009-10-22 13:11:33 -07:00
|
|
|
* @param idx index of point to query. Must be smaller than map size.
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param x where to return the X coordinate.
|
|
|
|
* @param y where to return the Y coordinate.
|
|
|
|
* @param z where to return the Z coordinate.
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-28 01:59:01 -07:00
|
|
|
evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
const Evas_Map_Point *p;
|
2009-10-28 01:59:01 -07:00
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
if (!m) goto error;
|
|
|
|
if (idx >= m->count) goto error;
|
|
|
|
p = m->points + idx;
|
|
|
|
if (x) *x = p->x;
|
|
|
|
if (y) *y = p->y;
|
|
|
|
if (z) *z = p->z;
|
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (x) *x = 0;
|
|
|
|
if (y) *y = 0;
|
|
|
|
if (z) *z = 0;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
2009-10-28 01:59:01 -07:00
|
|
|
* Change the map point's U and V texture source point
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* This sets the U and V coordinates for the point. This determines which
|
|
|
|
* coordinate in the source image is mapped to the given point, much like
|
|
|
|
* OpenGL and textures. Notes that these points do select the pixel, but
|
|
|
|
* are double floating point values to allow for accuracy and sub-pixel
|
|
|
|
* selection.
|
|
|
|
*
|
|
|
|
* @param m map to change the point of.
|
2009-10-22 13:11:33 -07:00
|
|
|
* @param idx index of point to change. Must be smaller than map size.
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param u the X coordinate within the image/texture source
|
|
|
|
* @param v the Y coordinate within the image/texture source
|
|
|
|
*
|
|
|
|
* @see evas_map_point_coord_set()
|
|
|
|
* @see evas_object_map_set()
|
2009-11-11 04:33:52 -08:00
|
|
|
* @see evas_map_util_points_populate_from_object_full()
|
|
|
|
* @see evas_map_util_points_populate_from_object()
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-28 01:59:01 -07:00
|
|
|
evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
Evas_Map_Point *p;
|
|
|
|
if (!m) return;
|
|
|
|
if (idx >= m->count) return;
|
|
|
|
p = m->points + idx;
|
|
|
|
p->u = u;
|
|
|
|
p->v = v;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
2009-10-28 01:59:01 -07:00
|
|
|
* Get the map point's U and V texture source points
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* This returns the texture points set by evas_map_point_image_uv_set().
|
|
|
|
*
|
|
|
|
* @param m map to query point.
|
2009-10-22 13:11:33 -07:00
|
|
|
* @param idx index of point to query. Must be smaller than map size.
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param u where to write the X coordinate within the image/texture source
|
|
|
|
* @param v where to write the Y coordinate within the image/texture source
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-28 01:59:01 -07:00
|
|
|
evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
const Evas_Map_Point *p;
|
|
|
|
if (!m) goto error;
|
|
|
|
if (idx >= m->count) goto error;
|
|
|
|
p = m->points + idx;
|
|
|
|
if (u) *u = p->u;
|
|
|
|
if (v) *v = p->v;
|
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (u) *u = 0.0;
|
|
|
|
if (v) *v = 0.0;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
|
2009-10-31 18:32:23 -07:00
|
|
|
/**
|
|
|
|
* Set the color of a vertex in the map
|
|
|
|
*
|
|
|
|
* This sets the color of the vertex in the map. Colors will be linearly
|
|
|
|
* interpolated between vertex points through the map. Color will multiply
|
|
|
|
* the "texture" pixels (like GL_MODULATE in OpenGL). The default color of
|
|
|
|
* a vertex in a map is white solid (255, 255, 255, 255) which means it will
|
|
|
|
* have no affect on modifying the texture pixels.
|
|
|
|
*
|
|
|
|
* @param m map to change the color of.
|
|
|
|
* @param idx index of point to change. Must be smaller than map size.
|
|
|
|
* @param r red (0 - 255)
|
|
|
|
* @param g green (0 - 255)
|
|
|
|
* @param b blue (0 - 255)
|
|
|
|
* @param a alpha (0 - 255)
|
2009-11-11 04:33:52 -08:00
|
|
|
*
|
|
|
|
* @see evas_map_util_points_color_set()
|
2009-10-31 18:32:23 -07:00
|
|
|
* @see evas_map_point_coord_set()
|
|
|
|
* @see evas_object_map_set()
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
|
|
|
|
{
|
|
|
|
Evas_Map_Point *p;
|
|
|
|
if (!m) return;
|
|
|
|
if (idx >= m->count) return;
|
|
|
|
p = m->points + idx;
|
|
|
|
p->r = r;
|
|
|
|
p->g = g;
|
|
|
|
p->b = b;
|
|
|
|
p->a = a;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the color set on a vertex in the map
|
|
|
|
*
|
|
|
|
* This gets the color set by evas_map_point_color_set() on the given vertex
|
|
|
|
* of the map.
|
|
|
|
*
|
|
|
|
* @param m map to get the color of the vertex from.
|
|
|
|
* @param idx index of point get. Must be smaller than map size.
|
|
|
|
* @param r pointer to red return
|
|
|
|
* @param g pointer to green return
|
|
|
|
* @param b pointer to blue return
|
|
|
|
* @param a pointer to alpha return (0 - 255)
|
|
|
|
*
|
|
|
|
* @see evas_map_point_coord_set()
|
|
|
|
* @see evas_object_map_set()
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
|
|
|
|
{
|
2009-11-02 00:52:23 -08:00
|
|
|
const Evas_Map_Point *p;
|
2009-10-31 18:32:23 -07:00
|
|
|
if (!m) return;
|
|
|
|
if (idx >= m->count) return;
|
|
|
|
p = m->points + idx;
|
|
|
|
if (r) *r = p->r;
|
|
|
|
if (g) *g = p->g;
|
|
|
|
if (b) *b = p->b;
|
|
|
|
if (a) *a = p->a;
|
|
|
|
}
|
|
|
|
|
2009-10-28 01:59:01 -07:00
|
|
|
/****************************************************************************/
|
|
|
|
/* util functions for manipulating maps, so you don't need to know the math */
|
|
|
|
/****************************************************************************/
|
2009-11-11 04:33:52 -08:00
|
|
|
static inline void
|
|
|
|
_evas_map_util_points_populate(Evas_Map *m, const Evas_Coord x, const Evas_Coord y, const Evas_Coord w, const Evas_Coord h, const Evas_Coord z)
|
|
|
|
{
|
|
|
|
Evas_Map_Point *p = m->points;
|
|
|
|
|
|
|
|
p[0].x = x;
|
|
|
|
p[0].y = y;
|
2009-11-11 04:47:46 -08:00
|
|
|
p[0].z = z;
|
2009-11-11 04:33:52 -08:00
|
|
|
p[0].u = 0.0;
|
|
|
|
p[0].v = 0.0;
|
|
|
|
|
|
|
|
p[1].x = x + w;
|
|
|
|
p[1].y = y;
|
2009-11-11 04:47:46 -08:00
|
|
|
p[1].z = z;
|
2009-11-11 04:33:52 -08:00
|
|
|
p[1].u = w;
|
|
|
|
p[1].v = 0.0;
|
|
|
|
|
|
|
|
p[2].x = x + w;
|
|
|
|
p[2].y = y + h;
|
2009-11-11 04:47:46 -08:00
|
|
|
p[2].z = z;
|
2009-11-11 04:33:52 -08:00
|
|
|
p[2].u = w;
|
|
|
|
p[2].v = h;
|
|
|
|
|
|
|
|
p[3].x = x;
|
|
|
|
p[3].y = y + h;
|
2009-11-11 04:47:46 -08:00
|
|
|
p[3].z = z;
|
2009-11-11 04:33:52 -08:00
|
|
|
p[3].u = 0.0;
|
|
|
|
p[3].v = h;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Populate source and destination map points to match exactly object.
|
|
|
|
*
|
|
|
|
* Usually one initialize map of an object to match it's original
|
|
|
|
* position and size, then transform these with evas_map_util_*
|
|
|
|
* functions, such as evas_map_util_rotate() or
|
|
|
|
* evas_map_util_3d_rotate(). The original set is done by this
|
|
|
|
* function, avoiding code duplication all around.
|
|
|
|
*
|
|
|
|
* @param m map to change all 4 points (must be of size 4).
|
|
|
|
* @param obj object to use unmapped geometry to populate map coordinates.
|
|
|
|
* @param z Point Z Coordinate hint (pre-perspective transform). This value
|
|
|
|
* will be used for all four points.
|
|
|
|
*
|
|
|
|
* @see evas_map_util_points_populate_from_object()
|
|
|
|
* @see evas_map_point_coord_set()
|
|
|
|
* @see evas_map_point_image_uv_set()
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *obj, Evas_Coord z)
|
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
|
|
return;
|
|
|
|
MAGIC_CHECK_END();
|
|
|
|
if (!m)
|
|
|
|
{
|
|
|
|
ERR("map == NULL");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m->count != 4)
|
|
|
|
{
|
|
|
|
ERR("map has count=%d where 4 was expected.", m->count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
|
|
|
|
obj->cur.geometry.w, obj->cur.geometry.h, z);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Populate source and destination map points to match exactly object.
|
|
|
|
*
|
|
|
|
* Usually one initialize map of an object to match it's original
|
|
|
|
* position and size, then transform these with evas_map_util_*
|
|
|
|
* functions, such as evas_map_util_rotate() or
|
|
|
|
* evas_map_util_3d_rotate(). The original set is done by this
|
|
|
|
* function, avoiding code duplication all around.
|
|
|
|
*
|
|
|
|
* Z Point coordinate is assumed as 0 (zero).
|
|
|
|
*
|
|
|
|
* @param m map to change all 4 points (must be of size 4).
|
|
|
|
* @param obj object to use unmapped geometry to populate map coordinates.
|
|
|
|
*
|
|
|
|
* @see evas_map_util_points_populate_from_object_full()
|
|
|
|
* @see evas_map_util_points_populate_from_geometry()
|
|
|
|
* @see evas_map_point_coord_set()
|
|
|
|
* @see evas_map_point_image_uv_set()
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *obj)
|
|
|
|
{
|
|
|
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
|
|
|
return;
|
|
|
|
MAGIC_CHECK_END();
|
|
|
|
if (!m)
|
|
|
|
{
|
|
|
|
ERR("map == NULL");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m->count != 4)
|
|
|
|
{
|
|
|
|
ERR("map has count=%d where 4 was expected.", m->count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
|
|
|
|
obj->cur.geometry.w, obj->cur.geometry.h, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Populate source and destination map points to match given geometry.
|
|
|
|
*
|
|
|
|
* Similar to evas_map_util_points_populate_from_object_full(), this
|
|
|
|
* call takes raw values instead of querying object's unmapped
|
|
|
|
* geometry. The given width will be used to calculate destination
|
|
|
|
* points (evas_map_point_coord_set()) and set the image uv
|
|
|
|
* (evas_map_point_image_uv_set()).
|
|
|
|
*
|
|
|
|
* @param m map to change all 4 points (must be of size 4).
|
|
|
|
* @param x Point X Coordinate
|
|
|
|
* @param y Point Y Coordinate
|
|
|
|
* @param w width to use to calculate second and third points.
|
|
|
|
* @param h height to use to calculate third and fourth points.
|
|
|
|
* @param z Point Z Coordinate hint (pre-perspective transform). This value
|
|
|
|
* will be used for all four points.
|
|
|
|
*
|
|
|
|
* @see evas_map_util_points_populate_from_object()
|
|
|
|
* @see evas_map_point_coord_set()
|
|
|
|
* @see evas_map_point_image_uv_set()
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_util_points_populate_from_geometry(Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Evas_Coord z)
|
|
|
|
{
|
|
|
|
if (!m)
|
|
|
|
{
|
|
|
|
ERR("map == NULL");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m->count != 4)
|
|
|
|
{
|
|
|
|
ERR("map has count=%d where 4 was expected.", m->count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_evas_map_util_points_populate(m, x, y, w, h, z);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set color of all points to given color.
|
|
|
|
*
|
|
|
|
* This call is useful to reuse maps after they had 3d lightning or
|
|
|
|
* any other colorization applied before.
|
|
|
|
*
|
|
|
|
* @param m map to change the color of.
|
|
|
|
* @param r red (0 - 255)
|
|
|
|
* @param g green (0 - 255)
|
|
|
|
* @param b blue (0 - 255)
|
|
|
|
* @param a alpha (0 - 255)
|
|
|
|
*
|
|
|
|
* @see evas_map_point_color_set()
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
|
|
|
|
{
|
|
|
|
Evas_Map_Point *p, *p_end;
|
|
|
|
if (!m)
|
|
|
|
{
|
|
|
|
ERR("map == NULL");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p = m->points;
|
|
|
|
p_end = p + m->count;
|
|
|
|
for (; p < p_end; p++)
|
|
|
|
{
|
|
|
|
p->r = r;
|
|
|
|
p->g = g;
|
|
|
|
p->b = b;
|
|
|
|
p->a = a;
|
|
|
|
}
|
|
|
|
}
|
2009-10-28 01:59:01 -07:00
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
2009-10-28 01:59:01 -07:00
|
|
|
* Change the map to apply the given rotation.
|
|
|
|
*
|
|
|
|
* This rotates the indicated map's coordinates around the center coordinate
|
|
|
|
* given by @p cx and @p cy as the rotation center. The points will have their
|
|
|
|
* X and Y coordinates rotated clockwise by @p degrees degress (360.0 is a
|
|
|
|
* full rotation). Negative values for degrees will rotate counter-clockwise
|
|
|
|
* by that amount. All coordinates are canvas global coordinates.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param m map to change.
|
|
|
|
* @param degrees amount of degrees from 0.0 to 360.0 to rotate.
|
|
|
|
* @param cx rotation's center horizontal positon.
|
|
|
|
* @param cy rotation's center vertical positon.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @see evas_map_point_coord_set()
|
2009-10-28 01:59:01 -07:00
|
|
|
* @see evas_map_util_zoom()
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-22 13:11:33 -07:00
|
|
|
evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
|
|
|
double r = (degrees * M_PI) / 180.0;
|
2009-10-22 13:11:33 -07:00
|
|
|
Evas_Map_Point *p, *p_end;
|
|
|
|
|
|
|
|
if (!m) return;
|
|
|
|
p = m->points;
|
2009-11-02 00:52:23 -08:00
|
|
|
p_end = p + m->count;
|
2009-10-22 13:11:33 -07:00
|
|
|
|
|
|
|
for (; p < p_end; p++)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
|
|
|
Evas_Coord x, y, xx, yy;
|
2009-10-22 13:11:33 -07:00
|
|
|
|
|
|
|
xx = x = p->x - cx;
|
|
|
|
yy = y = p->y - cy;
|
|
|
|
|
2009-10-22 08:47:30 -07:00
|
|
|
xx = (x * cos(r));
|
|
|
|
yy = (x * sin(r));
|
|
|
|
x = xx + (y * cos(r + (M_PI / 2.0)));
|
|
|
|
y = yy + (y * sin(r + (M_PI / 2.0)));
|
2009-10-22 13:11:33 -07:00
|
|
|
|
|
|
|
p->x = x + cx;
|
|
|
|
p->y = y + cy;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-22 13:11:33 -07:00
|
|
|
/**
|
2009-10-28 01:59:01 -07:00
|
|
|
* Change the map to apply the given zooming.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
2009-10-28 01:59:01 -07:00
|
|
|
* Like evas_map_util_rotate(), this zooms the points of the map from a center
|
|
|
|
* point. That center is defined by @p cx and @p cy. The @p zoomx and @p zoomy
|
|
|
|
* parameters specific how much to zoom in the X and Y direction respectively.
|
|
|
|
* A value of 1.0 means "don't zoom". 2.0 means "dobule the size". 0.5 is
|
|
|
|
* "half the size" etc. All coordinates are canvas global coordinates.
|
|
|
|
*
|
|
|
|
* @param m map to change.
|
2009-10-22 13:11:33 -07:00
|
|
|
* @param zoomx horizontal zoom to use.
|
|
|
|
* @param zoomy vertical zoom to use.
|
2009-10-28 01:59:01 -07:00
|
|
|
* @param cx zooming center horizontal positon.
|
|
|
|
* @param cy zooming center vertical positon.
|
2009-10-22 13:11:33 -07:00
|
|
|
*
|
|
|
|
* @see evas_map_point_coord_set()
|
2009-10-28 01:59:01 -07:00
|
|
|
* @see evas_map_util_rotate()
|
2009-10-22 13:11:33 -07:00
|
|
|
*/
|
2009-10-22 08:47:30 -07:00
|
|
|
EAPI void
|
2009-10-22 13:11:33 -07:00
|
|
|
evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
2009-10-22 13:11:33 -07:00
|
|
|
Evas_Map_Point *p, *p_end;
|
|
|
|
|
|
|
|
if (!m) return;
|
|
|
|
p = m->points;
|
2009-11-02 00:52:23 -08:00
|
|
|
p_end = p + m->count;
|
2009-10-22 13:11:33 -07:00
|
|
|
|
|
|
|
for (; p < p_end; p++)
|
2009-10-22 08:47:30 -07:00
|
|
|
{
|
|
|
|
Evas_Coord x, y;
|
2009-10-22 13:11:33 -07:00
|
|
|
|
|
|
|
x = p->x - cx;
|
|
|
|
y = p->y - cy;
|
|
|
|
|
2009-10-22 08:47:30 -07:00
|
|
|
x = (((double)x) * zoomx);
|
|
|
|
y = (((double)y) * zoomy);
|
2009-10-22 13:11:33 -07:00
|
|
|
|
|
|
|
p->x = x + cx;
|
|
|
|
p->y = y + cy;
|
2009-10-22 08:47:30 -07:00
|
|
|
}
|
|
|
|
}
|
2009-11-02 00:52:23 -08:00
|
|
|
|
|
|
|
/**
|
2009-11-02 07:43:51 -08:00
|
|
|
* Rotate the map around 3 axes in 3D
|
|
|
|
*
|
|
|
|
* This will rotate not just around the "Z" axis as in evas_map_util_rotate()
|
|
|
|
* (which is a convenience call for those only wanting 2D). This will rotate
|
|
|
|
* around the X, Y and Z axes. The Z axis points "into" the screen with low
|
|
|
|
* values at the screen and higher values further away. The X axis runs from
|
|
|
|
* left to right on the screen and the Y axis from top to bottom. Like with
|
|
|
|
* evas_map_util_rotate(0 you provide a center point to rotate around (in 3D).
|
2009-11-02 00:52:23 -08:00
|
|
|
*
|
|
|
|
* @param m map to change.
|
2009-11-02 04:20:50 -08:00
|
|
|
* @param dx amount of degrees from 0.0 to 360.0 to rotate arount X axis.
|
|
|
|
* @param dy amount of degrees from 0.0 to 360.0 to rotate arount Y axis.
|
|
|
|
* @param dz amount of degrees from 0.0 to 360.0 to rotate arount Z axis.
|
2009-11-02 00:52:23 -08:00
|
|
|
* @param cx rotation's center horizontal positon.
|
|
|
|
* @param cy rotation's center vertical positon.
|
2009-11-02 04:20:50 -08:00
|
|
|
* @param cz rotation's center vertical positon.
|
2009-11-02 00:52:23 -08:00
|
|
|
*/
|
|
|
|
EAPI void
|
2009-11-02 04:20:50 -08:00
|
|
|
evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
|
|
|
|
Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
|
2009-11-02 00:52:23 -08:00
|
|
|
{
|
|
|
|
double rz = (dz * M_PI) / 180.0;
|
|
|
|
double rx = (dx * M_PI) / 180.0;
|
|
|
|
double ry = (dy * M_PI) / 180.0;
|
|
|
|
Evas_Map_Point *p, *p_end;
|
|
|
|
|
|
|
|
if (!m) return;
|
|
|
|
p = m->points;
|
|
|
|
p_end = p + m->count;
|
|
|
|
|
|
|
|
for (; p < p_end; p++)
|
|
|
|
{
|
|
|
|
double x, y, z, xx, yy, zz;
|
|
|
|
|
|
|
|
x = p->x - cx;
|
|
|
|
y = p->y - cy;
|
|
|
|
z = p->z - cz;
|
|
|
|
|
|
|
|
if (rz != 0.0)
|
|
|
|
{
|
|
|
|
xx = x * cos(rz);
|
|
|
|
yy = x * sin(rz);
|
|
|
|
x = xx + (y * cos(rz + M_PI_2));
|
|
|
|
y = yy + (y * sin(rz + M_PI_2));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ry != 0.0)
|
|
|
|
{
|
|
|
|
xx = x * cos(ry);
|
|
|
|
zz = x * sin(ry);
|
|
|
|
x = xx + (z * cos(ry + M_PI_2));
|
|
|
|
z = zz + (z * sin(ry + M_PI_2));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rx != 0.0)
|
|
|
|
{
|
|
|
|
zz = z * cos(rx);
|
|
|
|
yy = z * sin(rx);
|
|
|
|
z = zz + (y * cos(rx + M_PI_2));
|
|
|
|
y = yy + (y * sin(rx + M_PI_2));
|
|
|
|
}
|
|
|
|
|
2009-11-02 04:20:50 -08:00
|
|
|
p->x = x + cx;
|
|
|
|
p->y = y + cy;
|
|
|
|
p->z = z + cz;
|
|
|
|
}
|
|
|
|
}
|
2009-11-02 00:52:23 -08:00
|
|
|
|
2009-11-02 04:20:50 -08:00
|
|
|
/**
|
2009-11-02 07:43:51 -08:00
|
|
|
* Perform lighting calculations on the given Map
|
|
|
|
*
|
|
|
|
* This is used to apply lighting calculations (from a single light source)
|
|
|
|
* to a given map. The R, G and B values of each vertex will be modified to
|
|
|
|
* reflect the lighting based on the lixth point coordinates, the light
|
|
|
|
* color and the ambient color, and at what angle the map is facing the
|
|
|
|
* light source. A surface should have its points be declared in a
|
|
|
|
* clockwise fashion if the face is "facing" towards you (as opposed to
|
|
|
|
* away from you) as faces have a "logical" side for lighting.
|
2009-11-02 04:20:50 -08:00
|
|
|
*
|
|
|
|
* @param m map to change.
|
|
|
|
* @param lx X coordinate in space of light point
|
|
|
|
* @param ly Y coordinate in space of light point
|
|
|
|
* @param lz Z coordinate in space of light point
|
2009-11-02 07:43:51 -08:00
|
|
|
* @param lr light red value (0 - 255)
|
|
|
|
* @param lg light green value (0 - 255)
|
|
|
|
* @param lb light blue value (0 - 255)
|
2010-03-17 21:57:40 -07:00
|
|
|
* @param ar ambient color red value (0 - 255)
|
|
|
|
* @param ag ambient color green value (0 - 255)
|
|
|
|
* @param ab ambient color blue value (0 - 255)
|
2009-11-02 04:20:50 -08:00
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_map_util_3d_lighting(Evas_Map *m,
|
|
|
|
Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
|
2010-03-17 21:57:40 -07:00
|
|
|
int lr, int lg, int lb, int ar, int ag, int ab)
|
2009-11-02 04:20:50 -08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!m) return;
|
|
|
|
|
|
|
|
for (i = 0; i < m->count; i++)
|
|
|
|
{
|
|
|
|
double x, y, z;
|
|
|
|
double nx, ny, nz, x1, y1, z1, x2, y2, z2, ln, br;
|
|
|
|
int h, j, mr, mg, mb;
|
|
|
|
|
|
|
|
x = m->points[i].x;
|
|
|
|
y = m->points[i].y;
|
|
|
|
z = m->points[i].z;
|
|
|
|
|
|
|
|
// calc normal
|
|
|
|
h = (i + m->count - 1) % m->count; // prev point
|
|
|
|
j = (i + 1) % m->count; // next point
|
|
|
|
|
|
|
|
x1 = m->points[h].x - x;
|
|
|
|
y1 = m->points[h].y - y;
|
|
|
|
z1 = m->points[h].z - z;
|
|
|
|
|
|
|
|
x2 = m->points[j].x - x;
|
|
|
|
y2 = m->points[j].y - y;
|
|
|
|
z2 = m->points[j].z - z;
|
|
|
|
|
|
|
|
nx = (y1 * z2) - (z1 * y2);
|
|
|
|
ny = (z1 * x2) - (x1 * z2);
|
|
|
|
nz = (x1 * y2) - (y1 * x2);
|
|
|
|
|
|
|
|
ln = (nx * nx) + (ny * ny) + (nz * nz);
|
|
|
|
ln = sqrt(ln);
|
|
|
|
|
|
|
|
if (ln != 0.0)
|
2009-11-02 00:52:23 -08:00
|
|
|
{
|
2009-11-02 04:20:50 -08:00
|
|
|
nx /= ln;
|
|
|
|
ny /= ln;
|
|
|
|
nz /= ln;
|
|
|
|
}
|
|
|
|
|
|
|
|
// calc point -> light vector
|
|
|
|
x = lx - x;
|
|
|
|
y = ly - y;
|
|
|
|
z = lz - z;
|
|
|
|
|
|
|
|
ln = (x * x) + (y * y) + (z * z);
|
|
|
|
ln = sqrt(ln);
|
|
|
|
|
|
|
|
if (ln != 0.0)
|
|
|
|
{
|
|
|
|
x /= ln;
|
|
|
|
y /= ln;
|
|
|
|
z /= ln;
|
2009-11-02 00:52:23 -08:00
|
|
|
}
|
|
|
|
|
2009-11-02 04:20:50 -08:00
|
|
|
// brightness - tan (0.0 -> 1.0 brightness really)
|
|
|
|
br = (nx * x) + (ny * y) + (nz * z);
|
|
|
|
if (br < 0.0) br = 0.0;
|
|
|
|
|
|
|
|
mr = ar + ((lr - ar) * br);
|
|
|
|
mg = ag + ((lg - ag) * br);
|
|
|
|
mb = ab + ((lb - ab) * br);
|
2009-11-04 01:25:52 -08:00
|
|
|
mr = (mr * m->points[i].a) / 255;
|
|
|
|
mg = (mg * m->points[i].a) / 255;
|
|
|
|
mb = (mb * m->points[i].a) / 255;
|
2009-11-02 04:20:50 -08:00
|
|
|
m->points[i].r = (m->points[i].r * mr) / 255;
|
|
|
|
m->points[i].g = (m->points[i].g * mg) / 255;
|
|
|
|
m->points[i].b = (m->points[i].b * mb) / 255;
|
2009-11-02 00:52:23 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-11-02 07:43:51 -08:00
|
|
|
* Apply a perspective transform to the map
|
|
|
|
*
|
|
|
|
* This applies a given perspective (3D) to the map coordinates. X, Y and Z
|
|
|
|
* values are used. The px and py points specify the "infinite distance" point
|
|
|
|
* in the 3D conversion (where all lines converge to like when artists draw
|
|
|
|
* 3D by hand). The @p z0 value specifis the z value at which there is a 1:1
|
|
|
|
* mapping between spatial coorinates and screen coordinates. Any points
|
|
|
|
* on this z value will not have their X and Y values modified in the transform.
|
|
|
|
* Those further away (Z value higher) will shrink into the distance, and
|
|
|
|
* those less than this value will expand and become bigger. The @p foc value
|
|
|
|
* determines the "focal length" of the camera. This is in reality the distance
|
|
|
|
* between the camera lens plane itself (at or closer than this rendering
|
|
|
|
* results are undefined) and the "z0" z value. This allows for some "depth"
|
|
|
|
* control and @p foc must be greater than 0.
|
2009-11-02 00:52:23 -08:00
|
|
|
*
|
|
|
|
* @param m map to change.
|
2009-11-02 07:43:51 -08:00
|
|
|
* @param px The pespective distance X coordinate
|
|
|
|
* @param py The pespective distance Y coordinate
|
|
|
|
* @param z0 The "0" z plane value
|
|
|
|
* @param foc The focal distance
|
2009-11-02 00:52:23 -08:00
|
|
|
*/
|
|
|
|
EAPI void
|
2009-11-02 04:20:50 -08:00
|
|
|
evas_map_util_3d_perspective(Evas_Map *m,
|
|
|
|
Evas_Coord px, Evas_Coord py,
|
|
|
|
Evas_Coord z0, Evas_Coord foc)
|
2009-11-02 00:52:23 -08:00
|
|
|
{
|
|
|
|
Evas_Map_Point *p, *p_end;
|
|
|
|
|
|
|
|
if (!m) return;
|
|
|
|
p = m->points;
|
|
|
|
p_end = p + m->count;
|
|
|
|
|
|
|
|
for (; p < p_end; p++)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, zz;
|
|
|
|
|
|
|
|
if (foc > 0)
|
|
|
|
{
|
|
|
|
x = p->x - px;
|
|
|
|
y = p->y - py;
|
|
|
|
|
|
|
|
zz = ((p->z - z0) + foc);
|
|
|
|
|
|
|
|
if (zz > 0)
|
|
|
|
{
|
|
|
|
x = (x * foc) / zz;
|
|
|
|
y = (y * foc) / zz;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->x = px + x;
|
|
|
|
p->y = py + y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-11-02 07:43:51 -08:00
|
|
|
* Get the clockwise state of a map
|
2009-11-02 00:52:23 -08:00
|
|
|
*
|
2009-11-02 07:43:51 -08:00
|
|
|
* This determines if the output points (X and Y. Z is not used) are
|
|
|
|
* clockwise or anti-clockwise. This can be used for "back-face culling". This
|
|
|
|
* is where you hide objects that "face away" from you. In this case objects
|
|
|
|
* that are not clockwise.
|
2009-11-02 00:52:23 -08:00
|
|
|
*
|
|
|
|
* @param m map to query.
|
|
|
|
* @return 1 if clockwise, 0 otherwise
|
|
|
|
*/
|
|
|
|
EAPI Eina_Bool
|
|
|
|
evas_map_util_clockwise_get(Evas_Map *m)
|
|
|
|
{
|
|
|
|
int i, j, k, count;
|
|
|
|
long long c;
|
|
|
|
|
|
|
|
if (!m) return 0;
|
|
|
|
if (m->count < 3) return 0;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
for (i = 0; i < m->count; i++)
|
|
|
|
{
|
|
|
|
j = (i + 1) % m->count;
|
|
|
|
k = (i + 2) % m->count;
|
|
|
|
c =
|
|
|
|
((m->points[j].x - m->points[i].x) *
|
|
|
|
(m->points[k].y - m->points[j].y))
|
|
|
|
-
|
|
|
|
((m->points[j].y - m->points[i].y) *
|
|
|
|
(m->points[k].x - m->points[j].x));
|
|
|
|
if (c < 0) count--;
|
|
|
|
else if (c > 0) count++;
|
|
|
|
}
|
|
|
|
if (count > 0) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-17 21:57:40 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|