static int merged_svg(gstack_t *ross, svg_t *svg) { svg_stop_t ss; rgbop_stop_t ros; while (gstack_pop(ross, &ros) == 0) { ss.colour.red = svg_it_rgb(ros.r); ss.colour.green = svg_it_rgb(ros.g); ss.colour.blue = svg_it_rgb(ros.b); ss.opacity = svg_it_op(ros.op); ss.value = svg_it_z(ros.z); svg_append(ss,svg); } return 0; }
static gstack_t* merge(gstack_t *rss, gstack_t *oss) { gstack_t *ross; int err = 0; size_t n = gstack_size(rss) + gstack_size(oss); /* get the first two of each type of stop */ rgb_stop_t rs0, rs1; err += gstack_pop(rss, &rs0); err += gstack_pop(rss, &rs1); if (err) { btrace("%i errors rgb", err); return NULL; } op_stop_t os0, os1; err += gstack_pop(oss, &os0); err += gstack_pop(oss, &os1); if (err) { btrace("%i errors op", err); return NULL; } if ((rs0.z != 0) || (os0.z != 0)) { btrace("nonzero initial stop"); btrace("RGB %.3f", svg_it_z(rs0.z)); btrace("Opacity %.3f", svg_it_z(os0.z)); return NULL; } /* merged stack to return */ if ((ross = gstack_new(sizeof(rgbop_stop_t), n, n)) == NULL) return NULL; rgbop_stop_t ros; while (1) { ros = stop_merge(rs0, os0); gstack_push(ross, &ros); if (rs1.z > os1.z) { rs0 = rgb_stop_interp(rs0, rs1, os1.z); os0 = os1; if (gstack_pop(oss, &os1) != 0) { btrace("early termination of opacity channel"); break; } } else if (rs1.z < os1.z) { os0 = op_stop_interp(os0, os1, rs1.z); rs0 = rs1; if (gstack_pop(rss, &rs1) != 0) { btrace("early termination of rgb channel"); break; } } else { rs0 = rs1; os0 = os1; int odone = gstack_pop(oss, &os1), rdone = gstack_pop(rss, &rs1); if (odone && rdone) { ros = stop_merge(rs0, os0); gstack_push(ross, &ros); gstack_reverse(ross); return ross; } else if (odone && !rdone) { btrace("early termination of opacity channel"); break; } else if (rdone && ! odone) { btrace("early termination of rgb channel"); break; } else { /* OK, so now we continue */ } } } /* something has gone pear-shaped */ gstack_destroy(ross); btrace("merge failed"); return NULL; }