895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free * viewBox helper class, common code used by root, symbol, marker, pattern, image, view
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free * Lauris Kaplinski <lauris@kaplinski.com> (code extracted from symbol.cpp)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free * Tavmjong Bah <tavmjong@free.fr>
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen * Johan Engelen
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen * Copyright (C) 2013-2014 Tavmjong Bah, authors
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free * Released under GNU GPL, read the file 'COPYING' for more information
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen , aspect_align(SP_ASPECT_XMID_YMID) // Default per spec
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freevoid SPViewBox::set_viewBox(const gchar* value) {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen gchar *eptr = const_cast<gchar*>(value); // const-cast necessary because of const-incorrect interface definition of g_ascii_strtod
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen double x = g_ascii_strtod (eptr, &eptr);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free while (*eptr && ((*eptr == ',') || (*eptr == ' '))) {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen double y = g_ascii_strtod (eptr, &eptr);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free while (*eptr && ((*eptr == ',') || (*eptr == ' '))) {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen double width = g_ascii_strtod (eptr, &eptr);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free while (*eptr && ((*eptr == ',') || (*eptr == ' '))) {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen double height = g_ascii_strtod (eptr, &eptr);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free while (*eptr && ((*eptr == ',') || (*eptr == ' '))) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Set viewbox */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free this->viewBox = Geom::Rect::from_xywh(x, y, width, height);
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen // The C++ way? -- not necessarily using iostreams
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // std::string sv( value );
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // std::replace( sv.begin(), sv.end(), ',', ' ');
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // std::stringstream ss( sv );
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // double x, y, width, height;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // ss >> x >> y >> width >> height;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freevoid SPViewBox::set_preserveAspectRatio(const gchar* value) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Do setup before, so we can use break to escape */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free this->aspect_align = SP_ASPECT_XMID_YMID; // Default per spec
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen while (*p && (*p == 32)) {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen while (*e && (*e != 32)) {
dca8db2be67c87ad222c2c58cca33d3e57f1b650tavmjong-free if (len > 8) { // Can't have buffer overflow as 8 < 256
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Now the actual part */
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen while (*e && (*e == 32)) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free// Apply scaling from viewbox
71c8c050ee018790e1eb72748f193b1d25dab706apennervoid SPViewBox::apply_viewbox(const Geom::Rect& in, double scale_none) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Determine actual viewbox in viewport coordinates */
71c8c050ee018790e1eb72748f193b1d25dab706apenner // scale_none is the scale that would apply if the viewbox and page size are same size
71c8c050ee018790e1eb72748f193b1d25dab706apenner // it is passed here because it is a double-precision variable, while 'in' is originally float
81efba162b1fc851b6bf0a5ca33928c37effa779apenner double x = 0.0;
81efba162b1fc851b6bf0a5ca33928c37effa779apenner double y = 0.0;
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner double scale_x = in.width() / this->viewBox.width();
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner double scale_y = in.height() / this->viewBox.height();
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner double scale_uniform = 1.0; // used only if scaling is uniform
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner if (Geom::are_near(scale_x / scale_y, 1.0, Geom::EPSILON)) {
81efba162b1fc851b6bf0a5ca33928c37effa779apenner // scaling is already uniform, reduce numerical error
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner if (Geom::are_near(scale_uniform / scale_none, 1.0, Geom::EPSILON))
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner scale_uniform = scale_none; // objects are same size, reduce numerical error
81efba162b1fc851b6bf0a5ca33928c37effa779apenner // scaling is not uniform, but force it to be
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner scale_uniform = (this->aspect_clip == SP_ASPECT_MEET) ? MIN (scale_x, scale_y) : MAX (scale_x, scale_y);
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner double width = this->viewBox.width() * scale_uniform;
0ff02b3688fe274104311bd443e7c5eee89d92e9apenner double height = this->viewBox.height() * scale_uniform;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Now place viewbox to requested position */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free switch (this->aspect_align) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Viewbox transform from scale and position */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // std::cout << " q\n" << q << std::endl;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Append viewbox transformation */
71c8c050ee018790e1eb72748f193b1d25dab706apennerSPItemCtx SPViewBox::get_rctx(const SPItemCtx* ictx, double scale_none) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Create copy of item context */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Calculate child to parent transformation */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Apply parent translation (set up as viewport) */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free this->c2p = Geom::Translate(rctx.viewport.min());
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // Adjusts c2p for viewbox
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* If viewBox is set initialize child viewport */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* Otherwise it is already correct */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free Local Variables:
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free c-file-style:"stroustrup"
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free c-basic-offset:2
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free indent-tabs-mode:nil
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free fill-column:99
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free// vim: filetype=cpp:expandtab:shiftwidth=2:tabstop=8:softtabstop=2:fileencoding=utf-8:textwidth=99 :