evas map: Reach feature parity with legacy API

I've done this by translating "Flip Page" to this new set of
EO APIs. In particular, absolute coordinates need to be used
in some calls, and the map needs to be calculated between
get and set operations.

This required an adjustment of the raw_coord API as the flip_page
code does some math after reading and then writing to the map.
Same for color. Those two properties now act like commands (ie.
like the other gfx map functions).

This also introduces a duplicate set of APIs to handle absolute
coordinates. Other solutions included:

 - Use an enum to specify the type of coordinates (but then the
   unit of cx,cy varies between non-unit relative position and
   pixel position. Also this adds an extra argument to all those
   function calls.

 - Pass a special value (an empty eo object) as the argument for
   pivot. Same remark about the unit as above. This way was
   deemed too confusing because of the weird object.

Those two options have been discarded after asking the opinion
of a few developers I could reach.

@feature
This commit is contained in:
Jean-Philippe Andre 2017-05-11 16:59:54 +09:00
parent 0a224da86f
commit 290f1893cd
6 changed files with 674 additions and 282 deletions

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,13 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
cw: bool; [[$true if clockwise, $false if counter clockwise]]
}
}
// FIXME: This needs modes such as "default", "smooth", "fast", "fastest"
// In SW: default, fast and fastest are not smooth
// In GL: All but fastest are smooth
// Same remark for alpha - it's only for performance
// Same remark for (MISSING) anti-aliasing
@property map_smooth {
[[Smoothing state for map rendering.
@ -92,9 +99,8 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
Remember all coordinates are canvas global ones like with move and resize
in the canvas.
This function should rarely be used as it overrides any other
transformation set. This property can be read to get the 4 points
positions on the canvas, or set to manually place them.
This property can be read to get the 4 points positions on the
canvas, or set to manually place them.
]]
keys {
idx: int; [[ID of the point, from 0 to 3 (included).]]
@ -149,6 +155,20 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
a: int; [[Alpha (0 - 255)]]
}
}
translate {
[[Apply a translation to the object using map.
This does not change the real geometry of the object but will affect
its visible position.
]]
params {
dx: double; [[Distance in pixels along the X axis.]]
dy: double; [[Distance in pixels along the Y axis.]]
dz: double; [[Distance in pixels along the Z axis.]]
}
}
// Transformations with a relative coordinates pivot
// FIXME: pivot & center need to be optional, but double(0.5) doesn't work!
rotate {
[[Apply a rotation to the object.
@ -168,7 +188,7 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
]]
params {
degrees: double; [[CCW rotation in degrees.]]
pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]]
pivot: const(Efl.Gfx); [[A pivot object for the center point, can be $null.]]
cx: double; [[X relative coordinate of the center point.]]
cy: double; [[y relative coordinate of the center point.]]
}
@ -191,7 +211,7 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
dx: double; [[Rotation in degrees around X axis (0 to 360).]]
dy: double; [[Rotation in degrees around Y axis (0 to 360).]]
dz: double; [[Rotation in degrees around Z axis (0 to 360).]]
pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]]
pivot: const(Efl.Gfx); [[A pivot object for the center point, can be $null.]]
cx: double; [[X relative coordinate of the center point.]]
cy: double; [[y relative coordinate of the center point.]]
cz: double; [[Z absolute coordinate of the center point.]]
@ -214,7 +234,7 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
qy: double; [[The y component of the imaginary part of the quaternion.]]
qz: double; [[The z component of the imaginary part of the quaternion.]]
qw: double; [[The w component of the real part of the quaternion.]]
pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]]
pivot: const(Efl.Gfx); [[A pivot object for the center point, can be $null.]]
cx: double; [[X relative coordinate of the center point.]]
cy: double; [[y relative coordinate of the center point.]]
cz: double; [[Z absolute coordinate of the center point.]]
@ -235,23 +255,11 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
params {
zoomx: double; [[Zoom in X direction]]
zoomy: double; [[Zoom in Y direction]]
pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]]
pivot: const(Efl.Gfx); [[A pivot object for the center point, can be $null.]]
cx: double; [[X relative coordinate of the center point.]]
cy: double; [[y relative coordinate of the center point.]]
}
}
translate {
[[Apply a translation to the object using map.
This does not change the real geometry of the object but will affect
its visible position.
]]
params {
dx: double; [[Distance in pixels along the X axis.]]
dy: double; [[Distance in pixels along the Y axis.]]
dz: double; [[Distance in pixels along the Z axis.]]
}
}
lightning_3d {
[[Apply a lightning effect on the object.
@ -270,7 +278,7 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
is $null then this object will be its own pivot.
]]
params {
pivot: Efl.Gfx; [[A pivot object for the light point, can be $null.]]
pivot: const(Efl.Gfx); [[A pivot object for the light point, can be $null.]]
lx: double; [[X relative coordinate in space of light point.]]
ly: double; [[Y relative coordinate in space of light point.]]
lz: double; [[Z absolute coordinate in space of light point.]]
@ -304,7 +312,143 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
is $null then this object will be its own pivot.
]]
params {
pivot: Efl.Gfx; [[A pivot object for the infinite point, can be $null.]]
pivot: const(Efl.Gfx); [[A pivot object for the infinite point, can be $null.]]
px: double; [[The perspective distance X relative coordinate.]]
py: double; [[The perspective distance Y relative coordinate.]]
z0: double; [[The "0" Z plane value.]]
foc: double; [[The focal distance, must be greater than 0.]]
}
}
// Transformations with an absolute center
rotate_absolute {
[[Apply a rotation to the object, using absolute coordinates.
This rotates the object clockwise by $degrees degrees, around the
center specified by the relative position ($cx, $cy) in the $pivot
object. If $pivot is $null then this object is used as its own pivot
center. 360 degrees is a full rotation, equivalent to no rotation.
Negative values for $degrees will rotate clockwise by that amount.
The given coordinates are absolute values in pixels. See also
@.rotate for a relative coordinate version.
]]
params {
degrees: double; [[CCW rotation in degrees.]]
cx: double; [[X absolute coordinate in pixels of the center point.]]
cy: double; [[y absolute coordinate in pixels of the center point.]]
}
}
rotate_3d_absolute {
[[Rotate the object around 3 axes in 3D, using absolute coordinates.
This will rotate in 3D and not just around the "Z" axis as the case
with @.rotate. 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.
The coordinates of the center point are given in absolute canvas
coordinates. See also @.rotate_3d for a pivot-based 3D rotation.
]]
params {
dx: double; [[Rotation in degrees around X axis (0 to 360).]]
dy: double; [[Rotation in degrees around Y axis (0 to 360).]]
dz: double; [[Rotation in degrees around Z axis (0 to 360).]]
cx: double; [[X absolute coordinate in pixels of the center point.]]
cy: double; [[y absolute coordinate in pixels of the center point.]]
cz: double; [[Z absolute coordinate of the center point.]]
}
}
rotate_quat_absolute {
[[Rotate the object in 3D using a unit quaternion, using absolute
coordinates.
This is similar to @.rotate_3d but uses a unit quaternion (also
known as versor) rather than a direct angle-based rotation around a
center point. Use this to avoid gimbal locks.
The coordinates of the center point are given in absolute canvas
coordinates. See also @.rotate_quat for a pivot-based 3D rotation.
]]
params {
qx: double; [[The x component of the imaginary part of the quaternion.]]
qy: double; [[The y component of the imaginary part of the quaternion.]]
qz: double; [[The z component of the imaginary part of the quaternion.]]
qw: double; [[The w component of the real part of the quaternion.]]
cx: double; [[X absolute coordinate in pixels of the center point.]]
cy: double; [[y absolute coordinate in pixels of the center point.]]
cz: double; [[Z absolute coordinate of the center point.]]
}
}
zoom_absolute {
[[Apply a zoom to the object, using absolute coordinates.
This zooms the points of the map from a center point. That center is
defined by $cx and $cy. The $zoomx and $zoomy parameters specify how
much to zoom in the X and Y direction respectively.
A value of 1.0 means "don't zoom". 2.0 means "double the size". 0.5 is
"half the size" etc.
The coordinates of the center point are given in absolute canvas
coordinates. See also @.zoom for a pivot-based zoom.
]]
params {
zoomx: double; [[Zoom in X direction]]
zoomy: double; [[Zoom in Y direction]]
cx: double; [[X absolute coordinate in pixels of the center point.]]
cy: double; [[y absolute coordinate in pixels of the center point.]]
}
}
lightning_3d_absolute {
[[Apply a lightning effect on the object.
This is used to apply lighting calculations (from a single light
source) to a given mapped object. The R, G and B values of each
vertex will be modified to reflect the lighting based on the light
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.
The coordinates of the center point are given in absolute canvas
coordinates. See also @.lightning_3d for a pivot-based lightning
effect.
]]
params {
lx: double; [[X absolute coordinate in pixels of the light point.]]
ly: double; [[y absolute coordinate in pixels of the light point.]]
lz: double; [[Z absolute coordinate in space of light point.]]
lr: int; [[Light red value (0 - 255).]]
lg: int; [[Light green value (0 - 255).]]
lb: int; [[Light blue value (0 - 255).]]
ar: int; [[Ambient color red value (0 - 255).]]
ag: int; [[Ambient color green value (0 - 255).]]
ab: int; [[Ambient color blue value (0 - 255).]]
}
}
perspective_3d_absolute {
[[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 $z0 value specifies the z value at which there is a 1:1
mapping between spatial coordinates 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 $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 $foc must be greater than 0.
The coordinates of the center point are given in absolute canvas
coordinates. See also @.perspective_3d for a pivot-based perspective
effect.
]]
params {
px: double; [[The perspective distance X relative coordinate.]]
py: double; [[The perspective distance Y relative coordinate.]]
z0: double; [[The "0" Z plane value.]]

View File

@ -134,19 +134,9 @@ evas_object_map_move_sync(Evas_Object *eo_obj)
_evas_map_calc_map_geometry(eo_obj);
}
Evas_Map *
_evas_map_new(int count, Eina_Bool sync)
static void
_evas_map_init(Evas_Map *m, int count, Eina_Bool sync)
{
Evas_Map *m;
int alloc;
/* Adjust allocation such that: at least 4 points, and always an even
* number: this allows the software engine to work efficiently */
alloc = (count < 4) ? 4 : count;
if (alloc & 0x1) alloc ++;
m = malloc(sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
if (!m) return NULL;
m->move_sync.enabled = sync;
m->count = count;
m->persp.foc = 0;
@ -160,9 +150,32 @@ _evas_map_new(int count, Eina_Bool sync)
m->points[i].b = 255;
m->points[i].a = 255;
}
}
Evas_Map *
_evas_map_new(int count, Eina_Bool sync)
{
Evas_Map *m;
int alloc;
/* Adjust allocation such that: at least 4 points, and always an even
* number: this allows the software engine to work efficiently */
alloc = (count < 4) ? 4 : count;
if (alloc & 0x1) alloc ++;
m = malloc(sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
if (!m) return NULL;
_evas_map_init(m, count, sync);
return m;
}
void
_evas_map_reset(Evas_Map *m)
{
if (!m) return;
_evas_map_init(m, m->count, m->move_sync.enabled);
}
static inline Eina_Bool
_evas_map_copy(Evas_Map *dst, const Evas_Map *src)
{

View File

@ -8,6 +8,7 @@
#include <math.h>
Evas_Map *_evas_map_new(int count, Eina_Bool sync);
void _evas_map_reset(Evas_Map *m);
void _evas_map_calc_map_geometry(Evas_Object *eo_obj);
void _map_util_rotate(Evas_Map *m, double degrees, double cx, double cy);
void _map_util_zoom(Evas_Map *m, double zoomx, double zoomy, double cx, double cy);

View File

@ -1416,6 +1416,7 @@ evas_object_image_init(Evas_Object *eo_obj)
obj->func = &object_func;
obj->private_data = efl_data_ref(eo_obj, MY_CLASS);
obj->type = o_type;
obj->is_image_object = EINA_TRUE;
}
EOLIAN static void

View File

@ -1222,6 +1222,7 @@ struct _Evas_Object_Protected_Data
Eina_Bool snapshot_needs_redraw : 1;
Eina_Bool snapshot_no_obscure : 1;
Eina_Bool is_image_object : 1;
Eina_Bool gfx_map_has : 1;
Eina_Bool gfx_map_update : 1;