Friday, December 28, 2012

Escen broken

In order to advance on the automatic bindings for Ender elements, Escen is broken and thus Eon. Sadly Escen needs a heavy refactor right now, but at least new features have reached Ender. Now, it is possible to define functions for structs so basically we can now map into Ender more C libraries. This was a requirement for Ender long time ago to basically support properties and functions for known-size native objects. This allows for example to match the following header:

typedef struct _Enesim_Matrix
{
 double xx, xy, xz;
 double yx, yy, yz;
 double zx, zy, zz;
} Enesim_Matrix;

EAPI void enesim_matrix_translate(Enesim_Matrix *t, double tx, double ty);
EAPI void enesim_matrix_scale(Enesim_Matrix *t, double sx, double sy);
EAPI void enesim_matrix_rotate(Enesim_Matrix *t, double rad);


With the following Ender definition:
struct "Matrix" {
 double "xx";
 double "xy";
 double "xz";
 double "yx";
 double "yy";
 double "yz";
 double "zx";
 double "zy";
 double "zz";
 translate(double, double);
 scale(double, double);
 rotate(double);
};


And then do something like this on ender:
Ender_Element *e;
e = ender_namespace_element_new(ns, "Matrix");
ender_element_property_set(e, "xx", 150.0, "yy", 320.0, NULL);
ender_element_function_call(e, "rotate", 180.0, NULL);


So now both structs and unions behave as an opaque pointer (objects). Another pending issue was to remove the Enesim dependency on Ender and Escen. That implies that the types SURFACE and MATRIX are no longer valid and things like this on escen files are not supported anymore:

set { transformation = rotate(0.78, 64, 64), translate(-30, -30); };

Later we will find a solution, maybe add scripting directly? Who knows ...

Monday, August 20, 2012

Recent enesim changes

It's been a long time since I write here, but the changes on the enesim stack deserve a new post. In the past months a lot of new features have been added and lots of bugs have been fixed. Just a small update of the changes given that I'm about to leave for vacations ...

Enesim is now more OpenGL friendly, it is possible to render complete SVG files with GL, still not as good as the software based backend, but is evolving nicely.

Egueb and specially Esvg is now able to render animated SVG files, it is still missing input (to be able to interact with the SVG files) and scripting (Javascript) support. But those will come in a near future. As an example, I'm attaching an animated clock rendered (and animated) with Esvg. You'll see some differences between the original file and our own version, mostly the lack of filters and some text glitches.


The past weeks I've been coding again the Eon toolkit and left Esvg for a while. I wanted to make it compile again with the new API changes and be able to start doing applications. So I took the Escen viewer again as an example and here is the result:


Monday, January 2, 2012

Enesim does OpenGL

Finally I got some time to start implementing the OpenGL backend interface on the renderer side. On the surface side, it was already possible to create surfaces with a GL texture associated using the OpenGL Enesim's pool but we were missing renderers.

Right now only simple renderers are implemented through fragment shaders. Mainly: stripes, checker and background. The approach is to always use shaders, being it geometric, fragment or vertex, I'm working on implementing geometric shaders for the different shapes but I don't have the hardware that supports it, so I suppose it will have to wait .... but good things will come in the future, like having a full GUI (Eon) done on OpenGL or rendering SVG files (ESVG) with full hardware acceleration

Anyway, here is a screenshot, everyone loves screenshots! Here is a simple GLX window displaying a surface which was previously rendered with a stripes renderer which is  rotated.


Tuesday, December 13, 2011

Esvg, Ecss

Sometime ago I started creating a library for SVG parsing and rendering. It was called Esvg. The initial version didn't do much, it was just using cairo to actually draw the different SVG tags. Now, a new version of Esvg has arrived into Enesim's repository, thanks to Vincent and his great effort to make this library a success.

The main ideas we had in mind for this library were:

  1. We should not only parse the SVG tags and render them, but create a fully statefull scene of SVG elements where you can manipulate each element by a C API, change the properties, make an element be a child of another, etc.
  2. Make every SVG element an Enesim Renderer, this way we can use all the already available stack (Escen, Ender, Emage ...) to interact and manipulate such elements.
  3. Create a simple parser for the SVG tags but make it optional in a sense that the rendering elements can be created without the need of an existing XML file.
So far all our goals have been achieved, even if the results are not graphically perfect it should be straightforward to fine tune it. This also helps the Enesim project reach its final 1.0 release.

In the process of building this library we required a CSS parser too, the options out there did not satisfied us, we needed a CSS parser which will let us (from the library's user point of view) provide an implementation of the DOM interface. That is, a way to traverse the tree: getting a tag's parent, its childs, its sibling, etc to match the CSS rules easily and be able to apply this library not only for SVG based XML but for any other tree based library as long as it provides such interface.
Another requirement was that the CSS library must not assume that every tag or property is HTML only, but any kind of tag name or attribute definition. I mean, the library should be DOCTYPE agnostic.

Sadly the above requirements were not met by any library, so we decided to create our own: Ecss, which of course has all the above features.

As a simple example of what the library can do, check out this SVG example parsed by our library and rendered using Emage into a PNG (the rendering is not perfect but is a very good start):


Sunday, August 14, 2011

Evoak?

About 6 years ago I wrote a post about Evoak, reading it I noticed how bad my posting abilities are (not that Im good now either) because there was no exaplanation on what my goal was, it was a post of about the status of something and I suppose is difficult to valorate a milestone whenever you dont know the final goal. On that time I was really fascinated about the evoak concept but was scared of the amount of work it was needed given the Evas unstability and Edje emerge. How to code such a great idea when you know your work will be uselss two months later?

I used Evoak on my final project on the univserity, it was a real success and for me it was enviosining a different approach to the classic server-client we had on that time (and still now), X11. This topic might be taken care off on another post.

Six years later and a complete different set of libraries and tools I'm able to code again that idea. The responsible of such possibility is Ender. When I started creating Enesim, Emage and several other libraries my main goal was to actually replace some of the bits of the current EFL stack specially Evas, to be able to improve and advance with new and good technical ideas. From the current state of EFL I would say that both projects are riding its own road for now, who knows later ... The situation was that I was trying to create some kind of object system or better, a description system which will allow me to serialize properties and values easily, if I were able to create a toolkit/canvas library using only properties and values then the next step, that is, send those properties through the network, would be easy and the Evoak concept could rise again.

That moment has arrived. Everything is still on an alpha status (everything is just a proof of concept) but the idea is working. Right now, with Eon being a toolkit system with objects I can create and manipulate on a generic way (through properties, values and events) I was able to create such network bridge to serialize the widgets data through the network and create a server which shows those applications without any change. If you take a look on the ecore_remote backend of Eon and the eon_server application on the Enesim repository you'll see the actual implementation. This is a very good milestone on the idea I wanted to accomplish: bring Evoak back! :)

Friday, August 12, 2011

Enesim Renderer Compound Tutorial

Now that you know how to create renderers and draw them into a surface as seen on the previous post, now we will see how to achieve the image below only using Enesim renderers, no images are allowed! Thanks Jose for the example code.



I'll update this post as soon as I have time ...

The complete code can be found here

Enesim Tutorials

This is the first post in a series of tutorial posts for every component on the Enesim project. From Enesim itself to Eon. On this first tutorial we'll learn how to draw this sample image:



The first step is to create the renderer we want to draw. A renderer is just an abstraction of something that draws, nothing else. It can be a rectangle, a circle a gradient or even a bubble, as long as it draws something we are fine. This is the main difference between Enesim and other graphics libraries, on Enesim there's no concept of graphics primitives or texturizing, every renderer is both a primitive and a texture.

Let's begin by creating our rectangle renderer

Enesim_Renderer *r;

r = enesim_renderer_rectangle_new();

The Enesim_Renderer design in a way has an object oriented approach. Every renderer inherits from the base Enesim_Renderer type and so, you can use the generic renderer API to set generic renderer properties. Also note that a rectangle renderer also inherits from a shape and again you can use all the shape API. More on this later.

Now let's set some common properties

enesim_renderer_origin_set(r, 15.0, 15.0);
enesim_renderer_rop_set(r, ENESIM_BLEND);

In the above code we are setting the renderer origin to 15 on the X axis and 15 on the Y axis. The important thing here is to understand that every renderer has it's own coordinate system and by setting its origin you are actually translating its center by 15 units.

The rop property is the raster operation. Setting it, informs the system how it should be drawn on a target surface. In this case we are waying that we want to blend the renderer with what is already on the surface.

Now lets set some rectangle properties

enesim_renderer_rectangle_width_set(r, 128);
enesim_renderer_rectangle_height_set(r, 128);
enesim_renderer_rectangle_corner_radius_set(r, 15);
enesim_renderer_rectangle_corners_set(r, EINA_TRUE, EINA_FALSE, EINA_FALSE, EINA_TRUE);

The rectangle renderer can have rounded corners, with the above code we are setting the top left corner and bottom right corner to be rounded with a radius of 15. Note that the rectangle renderer uses the origin property as the start of the rectangle, that means that right now we will draw a rectangle of with 128 and height 128 starting at 15 on the X axis and 15 on the Y axis. But what about filling? and stroking?

Given that a rectangle inhertis from a shape, you can use all the shape API to set more properties.

enesim_renderer_shape_fill_color_set(r, 0xff00ffff);
enesim_renderer_shape_stroke_color_set(r, 0xffff0000);
enesim_renderer_shape_stroke_weight_set(r, 3.0);
enesim_renderer_shape_draw_mode_set(r, ENESIM_SHAPE_DRAW_MODE_STROKE_FILL);

So now we are setting the fill color to ARGB(255, 0, 255, 255) the stroke to ARGB(255, 255, 0, 0) and the width or weight of the stroke to 3. Even if those properties are set, it does not mean that we will actually draw with such fill/stroke configuration. We need to set the drawing mode we are going to use, being it fill only, stroke only or both. For this case we will use stroke and fill. Note that we are not using any alpha different than 255 (i.e full opaque) to simplify this description. Every color used on Enesim has to be premultiplied by its alpha, but no worries about that, we do have some helper functions that transform an ARGB value to a premultiplied ARGB value.

Now that we have all the renderer set up, we want to actually draw it. For that we create an Enesim_Surface. A surface is just a pixel area where you can actually draw your renderer. On some systems this is called Drawable, on other Pixmaps or Textures.


Enesim_Surface *s

s = enesim_surface_new(ENESIM_FORMAT_ARGB8888, 256, 256);


So, you have created an ARGB surface with 8 bits per component of size 256 x 256. Now the real drawing


enesim_renderer_draw(r, s, NULL, 0, 0);

Note that we haven't set all the parameters for simplicity. But I will explain them too. The first argument of course is the renderer you want to draw and the second one the target surface you want to draw, those were easy. The third one defines the clipping area you want to draw on the destination surface and the last two is the origin of the destination surface. Remember that every renderer has it's own coordinate space? in this case a surface does have it too. It is always from 0 on the X axis and 0 on the Y axis and the width and height are the same as the surface width and height. With the two last arguments you can translate the surface origin, but to make this initial tutorial simple we wont describe the whole functionality, yet! :)

The complete code can be found here