broadway: Add linear gradient node

This commit is contained in:
Alexander Larsson 2017-11-22 12:31:36 +01:00
parent f7ff6dbb66
commit 278370c8e5
4 changed files with 106 additions and 9 deletions

View File

@ -16,6 +16,7 @@ typedef enum { /* Sync changes with broadway.js */
BROADWAY_NODE_OUTSET_SHADOW = 4,
BROADWAY_NODE_INSET_SHADOW = 5,
BROADWAY_NODE_ROUNDED_CLIP = 6,
BROADWAY_NODE_LINEAR_GRADIENT = 7,
} BroadwayNodeType;
typedef enum {

View File

@ -331,15 +331,16 @@ SwapNodes.prototype.decode_int32 = function() {
SwapNodes.prototype.decode_color = function() {
var rgba = this.decode_uint32();
a = (rgba >> 24) & 0xff;
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
b = (rgba >> 0) & 0xff;
var a = (rgba >> 24) & 0xff;
var r = (rgba >> 16) & 0xff;
var g = (rgba >> 8) & 0xff;
var b = (rgba >> 0) & 0xff;
var c;
if (a == 0)
c = "rgb(" + r + "," + g + "," + b + ")";
else
c = "rgba(" + r + "," + g + "," + b + "," + (a / 255.0) + ")";
return c
return c;
}
SwapNodes.prototype.decode_float = function() {
@ -350,7 +351,14 @@ SwapNodes.prototype.decode_size = function() {
var s = new Object();
s.width = this.decode_float ();
s.height = this.decode_float ();
return s
return s;
}
SwapNodes.prototype.decode_point = function() {
var p = new Object();
p.x = this.decode_float ();
p.y = this.decode_float ();
return p;
}
SwapNodes.prototype.decode_rect = function() {
@ -374,10 +382,25 @@ SwapNodes.prototype.decode_irect = function() {
SwapNodes.prototype.decode_rounded_rect = function() {
var r = new Object();
r.bounds = this.decode_rect();
r.sizes = []
r.sizes = [];
for (var i = 0; i < 4; i++)
r.sizes[i] = this.decode_size();
return r
return r;
}
SwapNodes.prototype.decode_color_stop = function() {
var s = new Object();
s.offset = this.decode_float ();
s.color = this.decode_color ();
return s;
}
SwapNodes.prototype.decode_color_stops = function() {
var stops = [];
var len = this.decode_uint32();
for (var i = 0; i < len; i++)
stops[i] = this.decode_color_stop();
return stops;
}
function args() {
@ -524,6 +547,51 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
}
break;
case 7: // LINEAR_GRADIENT
{
var rect = this.decode_rect();
var start = this.decode_point ();
var end = this.decode_point ();
var stops = this.decode_color_stops ();
var div = document.createElement('div');
div.style["position"] = "absolute";
set_rect_style(div, rect, offset_x, offset_y);
// direction:
var dx = end.x - start.x;
var dy = end.y - start.y;
// Angle in css coords (clockwise degrees, up = 0), note that y goes downwards so we have to invert
var angle = Math.atan2(dx, -dy) * 180.0 / Math.PI;
// Figure out which corner has offset == 0 in css
var start_corner_x, start_corner_y;
if (dx >= 0) // going right
start_corner_x = rect.x;
else
start_corner_x = rect.x + rect.width;
if (dy >= 0) // going down
start_corner_y = rect.y;
else
start_corner_y = rect.y + rect.height;
/* project start corner on the line */
var l2 = dx*dx + dy*dy;
var l = Math.sqrt(l2);
var offset = ((start_corner_x - start.x) * dx + (start_corner_y - start.y) * dy) / l2;
var gradient = "linear-gradient(" + angle + "deg";
for (var i = 0; i < stops.length; i++) {
var stop = stops[i];
gradient = gradient + ", " + stop.color + " " + px(stop.offset * l - offset);
}
gradient = gradient + ")";
div.style["background-image"] = gradient;
parent.appendChild(div);
}
break;
default:
alert("Unexpected node type " + type);
}

View File

@ -221,13 +221,14 @@ get_client_serial (BroadwayClient *client, guint32 daemon_serial)
#define NODE_SIZE_SIZE 2
#define NODE_SIZE_RECT (NODE_SIZE_POINT + NODE_SIZE_SIZE)
#define NODE_SIZE_RRECT (NODE_SIZE_RECT + 4 * NODE_SIZE_SIZE)
#define NODE_SIZE_COLOR_STOP (NODE_SIZE_FLOAT + NODE_SIZE_COLOR)
static int
rewrite_node_textures (BroadwayClient *client,
int len, guint32 data[], int pos)
{
guint32 type;
guint32 i, n_children;
guint32 i, n_children, n_stops;
g_assert (pos < len);
@ -257,6 +258,11 @@ rewrite_node_textures (BroadwayClient *client,
pos += NODE_SIZE_RRECT;
pos = rewrite_node_textures (client, len, data, pos);
break;
case BROADWAY_NODE_LINEAR_GRADIENT:
pos += NODE_SIZE_RECT + 2 * NODE_SIZE_POINT;
n_stops = data[pos++];
pos += n_stops * NODE_SIZE_COLOR_STOP;
break;
default:
g_assert_not_reached ();
}

View File

@ -145,6 +145,13 @@ add_rounded_rect (GArray *nodes, const GskRoundedRect *rrect)
add_size (nodes, &rrect->corner[i]);
}
static void
add_color_stop (GArray *nodes, const GskColorStop *stop)
{
add_float (nodes, stop->offset);
add_rgba (nodes, &stop->color);
}
static void
gsk_broadway_renderer_add_node (GskRenderer *self,
GArray *nodes,
@ -228,6 +235,21 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
}
return;
case GSK_LINEAR_GRADIENT_NODE:
{
guint i, n;
add_uint32 (nodes, BROADWAY_NODE_LINEAR_GRADIENT);
add_rect (nodes, &node->bounds);
add_point (nodes, gsk_linear_gradient_node_peek_start (node));
add_point (nodes, gsk_linear_gradient_node_peek_end (node));
n = gsk_linear_gradient_node_get_n_color_stops (node);
add_uint32 (nodes, n);
for (i = 0; i < n; i++)
add_color_stop (nodes, &gsk_linear_gradient_node_peek_color_stops (node)[i]);
}
return;
default:
{
cairo_surface_t *surface;