Implement rsvg_length_normalize() fully in Rust

We add an RsvgLength::normalize() method, and the corresponding
rsvg_length_normalize() function to make this accessible to the C code.

This removes the old _rsvg_css_normalize_length() function.
parent 4eca2e07
......@@ -2195,7 +2195,7 @@ rsvg_get_normalized_stroke_width (RsvgDrawingCtx *ctx)
{
RsvgState *state = rsvg_current_state (ctx);
return _rsvg_css_normalize_length (&state->stroke_width, ctx);
return rsvg_length_normalize (&state->stroke_width, ctx);
}
......
......@@ -101,10 +101,10 @@ _set_source_rsvg_linear_gradient (RsvgDrawingCtx * ctx,
if (linear->obj_bbox)
rsvg_drawing_ctx_push_view_box (ctx, 1., 1.);
pattern = cairo_pattern_create_linear (_rsvg_css_normalize_length (&linear->x1, ctx),
_rsvg_css_normalize_length (&linear->y1, ctx),
_rsvg_css_normalize_length (&linear->x2, ctx),
_rsvg_css_normalize_length (&linear->y2, ctx));
pattern = cairo_pattern_create_linear (rsvg_length_normalize (&linear->x1, ctx),
rsvg_length_normalize (&linear->y1, ctx),
rsvg_length_normalize (&linear->x2, ctx),
rsvg_length_normalize (&linear->y2, ctx));
if (linear->obj_bbox)
rsvg_drawing_ctx_pop_view_box (ctx);
......@@ -210,12 +210,12 @@ _set_source_rsvg_radial_gradient (RsvgDrawingCtx * ctx,
if (radial->obj_bbox)
rsvg_drawing_ctx_push_view_box (ctx, 1., 1.);
fx = _rsvg_css_normalize_length (&radial->fx, ctx);
fy = _rsvg_css_normalize_length (&radial->fy, ctx);
fx = rsvg_length_normalize (&radial->fx, ctx);
fy = rsvg_length_normalize (&radial->fy, ctx);
cx = _rsvg_css_normalize_length (&radial->cx, ctx);
cy = _rsvg_css_normalize_length (&radial->cy, ctx);
radius = _rsvg_css_normalize_length (&radial->r, ctx);
cx = rsvg_length_normalize (&radial->cx, ctx);
cy = rsvg_length_normalize (&radial->cy, ctx);
radius = rsvg_length_normalize (&radial->r, ctx);
fix_focus_point (fx, fy, cx, cy, radius, &new_fx, &new_fy);
......@@ -289,10 +289,10 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
if (rsvg_pattern->obj_bbox)
rsvg_drawing_ctx_push_view_box (ctx, 1., 1.);
patternx = _rsvg_css_normalize_length (&rsvg_pattern->x, ctx);
patterny = _rsvg_css_normalize_length (&rsvg_pattern->y, ctx);
patternw = _rsvg_css_normalize_length (&rsvg_pattern->width, ctx);
patternh = _rsvg_css_normalize_length (&rsvg_pattern->height, ctx);
patternx = rsvg_length_normalize (&rsvg_pattern->x, ctx);
patterny = rsvg_length_normalize (&rsvg_pattern->y, ctx);
patternw = rsvg_length_normalize (&rsvg_pattern->width, ctx);
patternh = rsvg_length_normalize (&rsvg_pattern->height, ctx);
if (rsvg_pattern->obj_bbox)
rsvg_drawing_ctx_pop_view_box (ctx);
......@@ -484,7 +484,7 @@ setup_cr_for_stroke (cairo_t *cr, RsvgDrawingCtx *ctx, RsvgState *state)
cairo_set_line_cap (cr, (cairo_line_cap_t) state->cap);
cairo_set_line_join (cr, (cairo_line_join_t) state->join);
cairo_set_dash (cr, state->dash.dash, state->dash.n_dash,
_rsvg_css_normalize_length (&state->dash.offset, ctx));
rsvg_length_normalize (&state->dash.offset, ctx));
}
void
......@@ -740,10 +740,10 @@ rsvg_cairo_generate_mask (cairo_t * cr, RsvgMask * self, RsvgDrawingCtx * ctx, R
if (self->maskunits == objectBoundingBox)
rsvg_drawing_ctx_push_view_box (ctx, 1, 1);
sx = _rsvg_css_normalize_length (&self->x, ctx);
sy = _rsvg_css_normalize_length (&self->y, ctx);
sw = _rsvg_css_normalize_length (&self->width, ctx);
sh = _rsvg_css_normalize_length (&self->height, ctx);
sx = rsvg_length_normalize (&self->x, ctx);
sy = rsvg_length_normalize (&self->y, ctx);
sw = rsvg_length_normalize (&self->width, ctx);
sh = rsvg_length_normalize (&self->height, ctx);
if (self->maskunits == objectBoundingBox)
rsvg_drawing_ctx_pop_view_box (ctx);
......
......@@ -109,7 +109,7 @@ normalize_font_size (RsvgState * state, RsvgDrawingCtx * ctx)
}
break;
default:
return _rsvg_css_normalize_length (&state->font_size, ctx);
return rsvg_length_normalize (&state->font_size, ctx);
break;
}
......@@ -122,68 +122,6 @@ rsvg_drawing_ctx_get_normalized_font_size (RsvgDrawingCtx *ctx)
return normalize_font_size (rsvg_current_state (ctx), ctx);
}
static double
viewport_percentage (double width, double height)
{
/* https://www.w3.org/TR/SVG/coords.html#Units
*
* "For any other length value expressed as a percentage of the viewport, the
* percentage is calculated as the specified percentage of
* sqrt((actual-width)**2 + (actual-height)**2))/sqrt(2)."
*/
return sqrt (width * width + height * height) / M_SQRT2;
}
double
_rsvg_css_normalize_length (const RsvgLength * in, RsvgDrawingCtx * ctx)
{
if (in->unit == LENGTH_UNIT_DEFAULT)
return in->length;
else if (in->unit == LENGTH_UNIT_PERCENT) {
double w, h;
rsvg_drawing_ctx_get_view_box_size (ctx, &w, &h);
switch (in->dir) {
case LENGTH_DIR_HORIZONTAL:
return in->length * w;
case LENGTH_DIR_VERTICAL:
return in->length * h;
case LENGTH_DIR_BOTH:
return in->length * viewport_percentage (w, h);
}
} else if (in->unit == LENGTH_UNIT_FONT_EM || in->unit == LENGTH_UNIT_FONT_EX) {
double font = rsvg_drawing_ctx_get_normalized_font_size (ctx);
if (in->unit == LENGTH_UNIT_FONT_EM)
return in->length * font;
else
return in->length * font / 2.;
} else if (in->unit == LENGTH_UNIT_INCH) {
double dpi_x, dpi_y;
rsvg_drawing_ctx_get_dpi (ctx, &dpi_x, &dpi_y);
switch (in->dir) {
case LENGTH_DIR_HORIZONTAL:
return in->length * dpi_x;
case LENGTH_DIR_VERTICAL:
return in->length * dpi_y;
case LENGTH_DIR_BOTH:
return in->length * viewport_percentage (dpi_x, dpi_y);
}
} else if (in->unit == LENGTH_UNIT_RELATIVE_LARGER) {
/* todo: "larger" */
} else if (in->unit == LENGTH_UNIT_RELATIVE_SMALLER) {
/* todo: "smaller" */
}
return 0;
}
/* Recursive evaluation of all parent elements regarding basline-shift */
double
_rsvg_css_accumulate_baseline_shift (RsvgState * state, RsvgDrawingCtx * ctx)
......
......@@ -161,10 +161,10 @@ rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext
otherbox.virgin = 0;
if (ctx->filter->filterunits == objectBoundingBox)
rsvg_drawing_ctx_push_view_box (ctx->ctx, 1., 1.);
otherbox.rect.x = _rsvg_css_normalize_length (&ctx->filter->x, ctx->ctx);
otherbox.rect.y = _rsvg_css_normalize_length (&ctx->filter->y, ctx->ctx);
otherbox.rect.width = _rsvg_css_normalize_length (&ctx->filter->width, ctx->ctx);
otherbox.rect.height = _rsvg_css_normalize_length (&ctx->filter->height, ctx->ctx);
otherbox.rect.x = rsvg_length_normalize (&ctx->filter->x, ctx->ctx);
otherbox.rect.y = rsvg_length_normalize (&ctx->filter->y, ctx->ctx);
otherbox.rect.width = rsvg_length_normalize (&ctx->filter->width, ctx->ctx);
otherbox.rect.height = rsvg_length_normalize (&ctx->filter->height, ctx->ctx);
if (ctx->filter->filterunits == objectBoundingBox)
rsvg_drawing_ctx_pop_view_box (ctx->ctx);
......@@ -177,11 +177,11 @@ rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext
if (ctx->filter->primitiveunits == objectBoundingBox)
rsvg_drawing_ctx_push_view_box (ctx->ctx, 1., 1.);
if (self->x_specified)
otherbox.rect.x = _rsvg_css_normalize_length (&self->x, ctx->ctx);
otherbox.rect.x = rsvg_length_normalize (&self->x, ctx->ctx);
else
otherbox.rect.x = 0;
if (self->y_specified)
otherbox.rect.y = _rsvg_css_normalize_length (&self->y, ctx->ctx);
otherbox.rect.y = rsvg_length_normalize (&self->y, ctx->ctx);
else
otherbox.rect.y = 0;
......@@ -191,12 +191,12 @@ rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext
rsvg_drawing_ctx_get_view_box_size (ctx->ctx, &curr_vbox_w, &curr_vbox_h);
if (self->width_specified)
otherbox.rect.width = _rsvg_css_normalize_length (&self->width, ctx->ctx);
otherbox.rect.width = rsvg_length_normalize (&self->width, ctx->ctx);
else
otherbox.rect.width = curr_vbox_w;
if (self->height_specified)
otherbox.rect.height = _rsvg_css_normalize_length (&self->height, ctx->ctx);
otherbox.rect.height = rsvg_length_normalize (&self->height, ctx->ctx);
else
otherbox.rect.height = curr_vbox_h;
}
......@@ -2018,8 +2018,8 @@ rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterConte
output_pixels = cairo_image_surface_get_data (output);
dx = _rsvg_css_normalize_length (&upself->dx, ctx->ctx);
dy = _rsvg_css_normalize_length (&upself->dy, ctx->ctx);
dx = rsvg_length_normalize (&upself->dx, ctx->ctx);
dy = rsvg_length_normalize (&upself->dy, ctx->ctx);
ox = ctx->paffine.xx * dx + ctx->paffine.xy * dy;
oy = ctx->paffine.yx * dx + ctx->paffine.yy * dy;
......@@ -4263,9 +4263,9 @@ get_light_direction (RsvgNodeLightSource * source, gdouble x1, gdouble y1, gdoub
double x, y;
x = affine->xx * x1 + affine->xy * y1 + affine->x0;
y = affine->yx * x1 + affine->yy * y1 + affine->y0;
output.x = _rsvg_css_normalize_length (&source->x, ctx) - x;
output.y = _rsvg_css_normalize_length (&source->y, ctx) - y;
output.z = _rsvg_css_normalize_length (&source->z, ctx) - z;
output.x = rsvg_length_normalize (&source->x, ctx) - x;
output.y = rsvg_length_normalize (&source->y, ctx) - y;
output.z = rsvg_length_normalize (&source->z, ctx) - z;
output = normalise (output);
}
break;
......@@ -4286,12 +4286,12 @@ get_light_color (RsvgNodeLightSource * source, vector3 color,
if (source->type != SPOTLIGHT)
return color;
sx = _rsvg_css_normalize_length (&source->x, ctx);
sy = _rsvg_css_normalize_length (&source->y, ctx);
sz = _rsvg_css_normalize_length (&source->z, ctx);
spx = _rsvg_css_normalize_length (&source->pointsAtX, ctx);
spy = _rsvg_css_normalize_length (&source->pointsAtY, ctx);
spz = _rsvg_css_normalize_length (&source->pointsAtZ, ctx);
sx = rsvg_length_normalize (&source->x, ctx);
sy = rsvg_length_normalize (&source->y, ctx);
sz = rsvg_length_normalize (&source->z, ctx);
spx = rsvg_length_normalize (&source->pointsAtX, ctx);
spy = rsvg_length_normalize (&source->pointsAtY, ctx);
spz = rsvg_length_normalize (&source->pointsAtZ, ctx);
x = affine->xx * x1 + affine->xy * y1 + affine->x0;
y = affine->yx * x1 + affine->yy * y1 + affine->y0;
......
......@@ -172,10 +172,10 @@ rsvg_node_image_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
if (surface == NULL)
return;
x = _rsvg_css_normalize_length (&z->x, ctx);
y = _rsvg_css_normalize_length (&z->y, ctx);
w = _rsvg_css_normalize_length (&z->w, ctx);
h = _rsvg_css_normalize_length (&z->h, ctx);
x = rsvg_length_normalize (&z->x, ctx);
y = rsvg_length_normalize (&z->y, ctx);
w = rsvg_length_normalize (&z->w, ctx);
h = rsvg_length_normalize (&z->h, ctx);
rsvg_state_reinherit_top (ctx, z->super.state, dominate);
......
......@@ -141,8 +141,8 @@ rsvg_marker_render (const char * marker_name, gdouble xpos, gdouble ypos, gdoubl
if (self->vbox.active) {
double w, h, x, y;
w = _rsvg_css_normalize_length (&self->width, ctx);
h = _rsvg_css_normalize_length (&self->height, ctx);
w = rsvg_length_normalize (&self->width, ctx);
h = rsvg_length_normalize (&self->height, ctx);
x = 0;
y = 0;
......@@ -158,8 +158,8 @@ rsvg_marker_render (const char * marker_name, gdouble xpos, gdouble ypos, gdoubl
}
cairo_matrix_init_translate (&taffine,
-_rsvg_css_normalize_length (&self->refX, ctx),
-_rsvg_css_normalize_length (&self->refY, ctx));
-rsvg_length_normalize (&self->refX, ctx),
-rsvg_length_normalize (&self->refY, ctx));
cairo_matrix_multiply (&affine, &taffine, &affine);
rsvg_state_push (ctx);
......@@ -181,8 +181,8 @@ rsvg_marker_render (const char * marker_name, gdouble xpos, gdouble ypos, gdoubl
self->vbox.rect.width, self->vbox.rect.height);
else
rsvg_add_clipping_rect (ctx, 0, 0,
_rsvg_css_normalize_length (&self->width, ctx),
_rsvg_css_normalize_length (&self->height, ctx));
rsvg_length_normalize (&self->width, ctx),
rsvg_length_normalize (&self->height, ctx));
}
for (i = 0; i < self->super.children->len; i++) {
......
......@@ -420,8 +420,10 @@ G_GNUC_INTERNAL
void rsvg_bbox_insert (RsvgBbox * dst, RsvgBbox * src);
G_GNUC_INTERNAL
void rsvg_bbox_clip (RsvgBbox * dst, RsvgBbox * src);
/* This is implemented in rust/src/length.rs */
G_GNUC_INTERNAL
double _rsvg_css_normalize_length (const RsvgLength * in, RsvgDrawingCtx * ctx);
double rsvg_length_normalize (const RsvgLength *length, RsvgDrawingCtx * ctx);
/* This is implemented in rust/src/length.rs */
G_GNUC_INTERNAL
......
......@@ -278,10 +278,10 @@ _rsvg_node_line_draw (RsvgNode * overself, RsvgDrawingCtx * ctx, int dominate)
builder = rsvg_path_builder_new ();
x1 = _rsvg_css_normalize_length (&self->x1, ctx);
y1 = _rsvg_css_normalize_length (&self->y1, ctx);
x2 = _rsvg_css_normalize_length (&self->x2, ctx);
y2 = _rsvg_css_normalize_length (&self->y2, ctx);
x1 = rsvg_length_normalize (&self->x1, ctx);
y1 = rsvg_length_normalize (&self->y1, ctx);
x2 = rsvg_length_normalize (&self->x2, ctx);
y2 = rsvg_length_normalize (&self->y2, ctx);
rsvg_path_builder_move_to (builder, x1, y1);
rsvg_path_builder_line_to (builder, x2, y2);
......@@ -354,16 +354,16 @@ _rsvg_node_rect_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
RsvgPathBuilder *builder;
RsvgNodeRect *rect = (RsvgNodeRect *) self;
x = _rsvg_css_normalize_length (&rect->x, ctx);
y = _rsvg_css_normalize_length (&rect->y, ctx);
x = rsvg_length_normalize (&rect->x, ctx);
y = rsvg_length_normalize (&rect->y, ctx);
/* FIXME: negative w/h/rx/ry is an error, per http://www.w3.org/TR/SVG11/shapes.html#RectElement
* For now we'll just take the absolute value.
*/
w = fabs (_rsvg_css_normalize_length (&rect->w, ctx));
h = fabs (_rsvg_css_normalize_length (&rect->h, ctx));
rx = fabs (_rsvg_css_normalize_length (&rect->rx, ctx));
ry = fabs (_rsvg_css_normalize_length (&rect->ry, ctx));
w = fabs (rsvg_length_normalize (&rect->w, ctx));
h = fabs (rsvg_length_normalize (&rect->h, ctx));
rx = fabs (rsvg_length_normalize (&rect->rx, ctx));
ry = fabs (rsvg_length_normalize (&rect->ry, ctx));
if (w == 0. || h == 0.)
return;
......@@ -534,9 +534,9 @@ _rsvg_node_circle_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
double cx, cy, r;
RsvgPathBuilder *builder;
cx = _rsvg_css_normalize_length (&circle->cx, ctx);
cy = _rsvg_css_normalize_length (&circle->cy, ctx);
r = _rsvg_css_normalize_length (&circle->r, ctx);
cx = rsvg_length_normalize (&circle->cx, ctx);
cy = rsvg_length_normalize (&circle->cy, ctx);
r = rsvg_length_normalize (&circle->r, ctx);
if (r <= 0)
return;
......@@ -626,10 +626,10 @@ _rsvg_node_ellipse_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
double cx, cy, rx, ry;
RsvgPathBuilder *builder;
cx = _rsvg_css_normalize_length (&ellipse->cx, ctx);
cy = _rsvg_css_normalize_length (&ellipse->cy, ctx);
rx = _rsvg_css_normalize_length (&ellipse->rx, ctx);
ry = _rsvg_css_normalize_length (&ellipse->ry, ctx);
cx = rsvg_length_normalize (&ellipse->cx, ctx);
cy = rsvg_length_normalize (&ellipse->cy, ctx);
rx = rsvg_length_normalize (&ellipse->rx, ctx);
ry = rsvg_length_normalize (&ellipse->ry, ctx);
if (rx <= 0 || ry <= 0)
return;
......
......@@ -176,10 +176,10 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
RsvgState *state;
cairo_matrix_t affine;
double x, y, w, h;
x = _rsvg_css_normalize_length (&use->x, ctx);
y = _rsvg_css_normalize_length (&use->y, ctx);
w = _rsvg_css_normalize_length (&use->w, ctx);
h = _rsvg_css_normalize_length (&use->h, ctx);
x = rsvg_length_normalize (&use->x, ctx);
y = rsvg_length_normalize (&use->y, ctx);
w = rsvg_length_normalize (&use->w, ctx);
h = rsvg_length_normalize (&use->h, ctx);
rsvg_state_reinherit_top (ctx, self->state, dominate);
......@@ -253,10 +253,10 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
double nx, ny, nw, nh;
sself = (RsvgNodeSvg *) self;
nx = _rsvg_css_normalize_length (&sself->x, ctx);
ny = _rsvg_css_normalize_length (&sself->y, ctx);
nw = _rsvg_css_normalize_length (&sself->w, ctx);
nh = _rsvg_css_normalize_length (&sself->h, ctx);
nx = rsvg_length_normalize (&sself->x, ctx);
ny = rsvg_length_normalize (&sself->y, ctx);
nw = rsvg_length_normalize (&sself->w, ctx);
nh = rsvg_length_normalize (&sself->h, ctx);
rsvg_state_reinherit_top (ctx, self->state, dominate);
......
......@@ -282,10 +282,10 @@ _rsvg_node_text_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
RsvgNodeText *text = (RsvgNodeText *) self;
rsvg_state_reinherit_top (ctx, self->state, dominate);
x = _rsvg_css_normalize_length (&text->x, ctx);
y = _rsvg_css_normalize_length (&text->y, ctx);
dx = _rsvg_css_normalize_length (&text->dx, ctx);
dy = _rsvg_css_normalize_length (&text->dy, ctx);
x = rsvg_length_normalize (&text->x, ctx);
y = rsvg_length_normalize (&text->y, ctx);
dx = rsvg_length_normalize (&text->dx, ctx);
dy = rsvg_length_normalize (&text->dy, ctx);
if (rsvg_current_state (ctx)->text_anchor != TEXT_ANCHOR_START) {
_rsvg_node_text_length_children (self, ctx, &length, &lastwasspace, FALSE);
......@@ -332,8 +332,8 @@ _rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
double dx, dy, length = 0;
rsvg_state_reinherit_top (ctx, self->super.state, 0);
dx = _rsvg_css_normalize_length (&self->dx, ctx);
dy = _rsvg_css_normalize_length (&self->dy, ctx);
dx = rsvg_length_normalize (&self->dx, ctx);
dy = rsvg_length_normalize (&self->dy, ctx);
if (rsvg_current_state (ctx)->text_anchor != TEXT_ANCHOR_START) {
gboolean lws = *lastwasspace;
......@@ -344,7 +344,7 @@ _rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
}
if (self->x_specified) {
*x = _rsvg_css_normalize_length (&self->x, ctx);
*x = rsvg_length_normalize (&self->x, ctx);
if (!PANGO_GRAVITY_IS_VERTICAL (rsvg_current_state (ctx)->text_gravity)) {
*x -= length;
if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
......@@ -356,7 +356,7 @@ _rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
*x += dx;
if (self->y_specified) {
*y = _rsvg_css_normalize_length (&self->y, ctx);
*y = rsvg_length_normalize (&self->y, ctx);
if (PANGO_GRAVITY_IS_VERTICAL (rsvg_current_state (ctx)->text_gravity)) {
*y -= length;
if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
......@@ -379,9 +379,9 @@ _rsvg_node_text_length_tspan (RsvgNodeText * self,
return TRUE;
if (PANGO_GRAVITY_IS_VERTICAL (rsvg_current_state (ctx)->text_gravity))
*length += _rsvg_css_normalize_length (&self->dy, ctx);
*length += rsvg_length_normalize (&self->dy, ctx);
else
*length += _rsvg_css_normalize_length (&self->dx, ctx);
*length += rsvg_length_normalize (&self->dx, ctx);
return _rsvg_node_text_length_children (&self->super, ctx, length,
lastwasspace, usetextonly);
......@@ -545,7 +545,7 @@ rsvg_text_create_layout (RsvgDrawingCtx * ctx, const char *text, PangoContext *
pango_font_description_free (font_desc);
attr_list = pango_attr_list_new ();
attribute = pango_attr_letter_spacing_new (_rsvg_css_normalize_length (&state->letter_spacing, ctx) * PANGO_SCALE);
attribute = pango_attr_letter_spacing_new (rsvg_length_normalize (&state->letter_spacing, ctx) * PANGO_SCALE);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_attr_list_insert (attr_list, attribute);
......
pub enum RsvgDrawingCtx {}
extern "C" {
fn rsvg_drawing_ctx_get_dpi (draw_ctx: *const RsvgDrawingCtx,
out_dpi_x: *mut f64,
out_dpi_y: *mut f64);
fn rsvg_drawing_ctx_get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64;
fn rsvg_drawing_ctx_get_view_box_size (draw_ctx: *const RsvgDrawingCtx,
out_x: *mut f64,
out_y: *mut f64);
}
pub fn get_dpi (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
let mut dpi_x: f64 = 0.0;
let mut dpi_y: f64 = 0.0;
unsafe { rsvg_drawing_ctx_get_dpi (draw_ctx, &mut dpi_x, &mut dpi_y); }
(dpi_x, dpi_y)
}
pub fn get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64 {
unsafe { rsvg_drawing_ctx_get_normalized_font_size (draw_ctx) }
}
pub fn get_view_box_size (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
let mut w: f64 = 0.0;
let mut h: f64 = 0.0;
......
extern crate libc;
extern crate glib;
use std::f64;
use self::glib::translate::*;
use strtod::*;
use drawing_ctx;
use drawing_ctx::RsvgDrawingCtx;
/* Keep this in sync with ../../rsvg-private.h:LengthUnit */
#[repr(C)]
......@@ -40,8 +44,6 @@ pub struct RsvgLength {
dir: LengthDir
}
pub enum RsvgDrawingCtx {}
const POINTS_PER_INCH: f64 = 72.0;
const CM_PER_INCH: f64 = 2.54;
const MM_PER_INCH: f64 = 25.4;
......@@ -79,7 +81,7 @@ pub extern fn rsvg_length_parse (string: *const libc::c_char, dir: LengthDir) ->
* need to know if they are horizontal/vertical/both. For example,
* a some_object.width="50%" is 50% with respect to the current
* viewport's width. In this case, the @dir argument is used
* when _rsvg_css_normalize_length() needs to know to what the
* inside RsvgLength::normalize(), when it needs to know to what the
* length refers.
*/
impl RsvgLength {
......@@ -157,6 +159,46 @@ impl RsvgLength {
}
}
pub fn normalize (&self, draw_ctx: *const RsvgDrawingCtx) -> f64 {
match self.unit {
LengthUnit::Default => {
self.length
},
LengthUnit::Percent => {
let (width, height) = drawing_ctx::get_view_box_size (draw_ctx);
match self.dir {
LengthDir::Horizontal => { self.length * width },
LengthDir::Vertical => { self.length * height },
LengthDir::Both => { self.length * viewport_percentage (width, height) }
}
},
LengthUnit::FontEm => {
self.length * drawing_ctx::get_normalized_font_size (draw_ctx)
},
LengthUnit::FontEx => {
self.length * drawing_ctx::get_normalized_font_size (draw_ctx) / 2.0
},
LengthUnit::Inch => {
let (dpi_x, dpi_y) = drawing_ctx::get_dpi (draw_ctx);
match self.dir {
LengthDir::Horizontal => { self.length * dpi_x },
LengthDir::Vertical => { self.length * dpi_y },
LengthDir::Both => { self.length * viewport_percentage (dpi_x, dpi_y) }
}
},
// FIXME: these are pending: https://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#propdef-font-size
LengthUnit::RelativeLarger |
LengthUnit::RelativeSmaller => { 0.0 }
}
}
pub fn hand_normalize (&self,
pixels_per_inch: f64,
width_or_height: f64,
......@@ -177,9 +219,23 @@ impl RsvgLength {
}
}
fn viewport_percentage (x: f64, y: f64) -> f64 {
/* https://www.w3.org/TR/SVG/coords.html#Units
*
* "For any other length value expressed as a percentage of the viewport, the
* percentage is calculated as the specified percentage of
* sqrt((actual-width)**2 + (actual-height)**2))/sqrt(2)."
*/
return (x * x + y * y).sqrt () / f64::consts::SQRT_2;
}
#[no_mangle]
pub extern fn rsvg_length_normalize (raw_length: *const RsvgLength, draw_ctx: *const RsvgDrawingCtx) -> f64 {
unimplemented! ();
assert! (!raw_length.is_null ());
let length: &RsvgLength = unsafe { &*raw_length };
length.normalize (draw_ctx)
}
#[no_mangle]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment