Code

Cleaned up DOS line ends that had snuck in.
authorjoncruz <joncruz@users.sourceforge.net>
Mon, 19 Feb 2007 20:48:09 +0000 (20:48 +0000)
committerjoncruz <joncruz@users.sourceforge.net>
Mon, 19 Feb 2007 20:48:09 +0000 (20:48 +0000)
35 files changed:
src/display/canvas-axonomgrid.cpp
src/display/canvas-axonomgrid.h
src/display/nr-filter-gaussian.cpp
src/dom/util/digest.cpp
src/dom/util/digest.h
src/extension/internal/cairo-pdf-out.cpp
src/extension/internal/cairo-pdf-out.h
src/extension/internal/cairo-png-out.cpp
src/extension/internal/cairo-png-out.h
src/extension/internal/cairo-renderer-pdf-out.cpp
src/extension/internal/cairo-renderer-pdf-out.h
src/extension/internal/emf-win32-inout.cpp
src/extension/internal/emf-win32-inout.h
src/extension/internal/emf-win32-print.cpp
src/extension/internal/emf-win32-print.h
src/extension/internal/libwpg/WPGOLEStream.h
src/extension/internal/libwpg/WPGXParser.cpp
src/extension/internal/libwpg/WPGXParser.h
src/extension/internal/libwpg/WPGraphics.cpp
src/extension/internal/libwpg/WPGraphics.h
src/extension/internal/wpg-input.cpp
src/extension/paramenum.cpp
src/extension/paramenum.h
src/extension/paramnotebook.cpp
src/extension/paramnotebook.h
src/extension/paramradiobutton.cpp
src/extension/paramradiobutton.h
src/pixmaps/cursor-gradient-add.xpm
src/pixmaps/cursor-gradient-delete.xpm
src/sp-filter-primitive.cpp
src/sp-filter-primitive.h
src/sp-filter.cpp
src/ui/widget/entry.cpp
src/ui/widget/entry.h
src/util/fixed_point.h

index 2f986f16f748e35c83c125db224fd789be07b0c2..9dfbed9255b9089dfede98270c5e86e0e3b1c454 100644 (file)
-#define SP_CANVAS_AXONOMGRID_C\r
-\r
-/*\r
- * SPCAxonomGrid\r
- *\r
- * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>\r
- * Copyright (C) 2000 Lauris Kaplinski\r
- *\r
- */                         \r
\r
- /* \r
-  * Current limits are: one axis (y-axis) is always vertical. The other two\r
-  * axes are bound to a certain range of angles. The z-axis always has an angle \r
-  * smaller than 90 degrees (measured from horizontal, 0 degrees being a line extending\r
-  * to the right). The x-axis will always have an angle between 0 and 90 degrees.\r
-  * When I quickly think about it: all possibilities are probably covered this way. Eg.\r
-  * a z-axis with negative angle can be replaced with an x-axis, etc.\r
-  */              \r
-  \r
- /*\r
-  *  TODO:  LOTS LOTS LOTS. Optimization etc.\r
-  *\r
-  */\r
-\r
-#include "sp-canvas-util.h"\r
-#include "canvas-axonomgrid.h"\r
-#include "display-forward.h"\r
-#include <libnr/nr-pixops.h>\r
-\r
-#define SAFE_SETPIXEL   //undefine this when it is certain that setpixel is never called with invalid params\r
-\r
-enum {\r
-    ARG_0,\r
-    ARG_ORIGINX,\r
-    ARG_ORIGINY,\r
-    ARG_ANGLEX,\r
-    ARG_SPACINGY,\r
-    ARG_ANGLEZ,\r
-    ARG_COLOR,\r
-    ARG_EMPCOLOR,\r
-    ARG_EMPSPACING\r
-};\r
-\r
-enum Dim3 { X=0, Y, Z };\r
-\r
-#ifndef M_PI\r
-#define M_PI 3.14159265358979323846\r
-#endif\r
-\r
-static double deg_to_rad(double deg) { return deg*M_PI/180.0;}\r
-\r
-\r
-static void sp_caxonomgrid_class_init (SPCAxonomGridClass *klass);\r
-static void sp_caxonomgrid_init (SPCAxonomGrid *grid);\r
-static void sp_caxonomgrid_destroy (GtkObject *object);\r
-static void sp_caxonomgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);\r
-\r
-static void sp_caxonomgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags);\r
-static void sp_caxonomgrid_render (SPCanvasItem *item, SPCanvasBuf *buf);\r
-\r
-static SPCanvasItemClass * parent_class;\r
-\r
-GtkType\r
-sp_caxonomgrid_get_type (void)\r
-{\r
-    static GtkType caxonomgrid_type = 0;\r
-\r
-    if (!caxonomgrid_type) {\r
-        GtkTypeInfo caxonomgrid_info = {\r
-            "SPCAxonomGrid",\r
-            sizeof (SPCAxonomGrid),\r
-            sizeof (SPCAxonomGridClass),\r
-            (GtkClassInitFunc) sp_caxonomgrid_class_init,\r
-            (GtkObjectInitFunc) sp_caxonomgrid_init,\r
-            NULL, NULL,\r
-            (GtkClassInitFunc) NULL\r
-        };\r
-        caxonomgrid_type = gtk_type_unique (sp_canvas_item_get_type (), &caxonomgrid_info);\r
-    }\r
-    return caxonomgrid_type;\r
-}\r
-\r
-static void\r
-sp_caxonomgrid_class_init (SPCAxonomGridClass *klass)\r
-{\r
-\r
-    GtkObjectClass *object_class;\r
-    SPCanvasItemClass *item_class;\r
-\r
-    object_class = (GtkObjectClass *) klass;\r
-    item_class = (SPCanvasItemClass *) klass;\r
-\r
-    parent_class = (SPCanvasItemClass*)gtk_type_class (sp_canvas_item_get_type ());\r
-\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::originx", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINX);\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::originy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINY);\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::anglex", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ANGLEX);\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::spacingy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_SPACINGY);\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::anglez", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ANGLEZ);\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::color", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_COLOR);\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::empcolor", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPCOLOR);\r
-    gtk_object_add_arg_type ("SPCAxonomGrid::empspacing", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPSPACING);\r
-\r
-    object_class->destroy = sp_caxonomgrid_destroy;\r
-    object_class->set_arg = sp_caxonomgrid_set_arg;\r
-\r
-    item_class->update = sp_caxonomgrid_update;\r
-    item_class->render = sp_caxonomgrid_render;\r
-  \r
-}\r
-\r
-static void\r
-sp_caxonomgrid_init (SPCAxonomGrid *grid)\r
-{\r
-    grid->origin[NR::X] = grid->origin[NR::Y] = 0.0;\r
-//    grid->spacing[X] = grid->spacing[Y] = grid->spacing[Z] = 8.0;\r
-    grid->color = 0x0000ff7f;\r
-    grid->empcolor = 0x3F3FFF40;\r
-    grid->empspacing = 5;\r
-}\r
-\r
-static void\r
-sp_caxonomgrid_destroy (GtkObject *object)\r
-{\r
-    g_return_if_fail (object != NULL);\r
-    g_return_if_fail (SP_IS_CAXONOMGRID (object));\r
-\r
-    if (GTK_OBJECT_CLASS (parent_class)->destroy)\r
-        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);\r
-}\r
-\r
-static void\r
-sp_caxonomgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)\r
-{\r
-    SPCanvasItem *item = SP_CANVAS_ITEM (object);\r
-    SPCAxonomGrid *grid = SP_CAXONOMGRID (object);\r
-    \r
-    switch (arg_id) {\r
-    case ARG_ORIGINX:\r
-        grid->origin[NR::X] = GTK_VALUE_DOUBLE (* arg);\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    case ARG_ORIGINY:\r
-        grid->origin[NR::Y] = GTK_VALUE_DOUBLE (* arg);\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    case ARG_ANGLEX:\r
-        grid->angle_deg[X] = GTK_VALUE_DOUBLE (* arg);\r
-        if (grid->angle_deg[X] < 0.0) grid->angle_deg[X] = 0.0;\r
-        if (grid->angle_deg[X] > 89.0) grid->angle_deg[X] = 89.0;\r
-        grid->angle_rad[X] = deg_to_rad(grid->angle_deg[X]);\r
-        grid->tan_angle[X] = tan(grid->angle_rad[X]);\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    case ARG_SPACINGY:\r
-        grid->lengthy = GTK_VALUE_DOUBLE (* arg);\r
-        if (grid->lengthy < 0.01) grid->lengthy = 0.01;\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    case ARG_ANGLEZ:\r
-        grid->angle_deg[Z] = GTK_VALUE_DOUBLE (* arg);\r
-        if (grid->angle_deg[Z] < 0.0) grid->angle_deg[Z] = 0.0;\r
-        if (grid->angle_deg[X] > 89.0) grid->angle_deg[X] = 89.0;\r
-        grid->angle_rad[Z] = deg_to_rad(grid->angle_deg[Z]);\r
-        grid->tan_angle[Z] = tan(grid->angle_rad[Z]);\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    case ARG_COLOR:\r
-        grid->color = GTK_VALUE_INT (* arg);\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    case ARG_EMPCOLOR:\r
-        grid->empcolor = GTK_VALUE_INT (* arg);\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    case ARG_EMPSPACING:\r
-        grid->empspacing = GTK_VALUE_INT (* arg);\r
-        // std::cout << "Emphasis Spacing: " << grid->empspacing << std::endl;\r
-        sp_canvas_item_request_update (item);\r
-        break;\r
-    default:\r
-        break;\r
-    }\r
-}\r
-\r
-\r
-\r
-/**\r
-    \brief  This function renders a pixel on a particular buffer.\r
-                \r
-    The topleft of the buffer equals\r
-                        ( rect.x0 , rect.y0 )  in screen coordinates\r
-                        ( 0 , 0 )  in setpixel coordinates\r
-    The bottomright of the buffer equals\r
-                        ( rect.x1 , rect,y1 )  in screen coordinates\r
-                        ( rect.x1 - rect.x0 , rect.y1 - rect.y0 )  in setpixel coordinates\r
-*/\r
-static void \r
-sp_caxonomgrid_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba) {\r
-#ifdef SAFE_SETPIXEL\r
-    if ( (x >= buf->rect.x0) && (x < buf->rect.x1) && (y >= buf->rect.y0) && (y < buf->rect.y1) ) {\r
-#endif        \r
-        guint r, g, b, a;          \r
-        r = NR_RGBA32_R (rgba);\r
-        g = NR_RGBA32_G (rgba);\r
-        b = NR_RGBA32_B (rgba);\r
-        a = NR_RGBA32_A (rgba);  \r
-        guchar * p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;\r
-        p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);\r
-        p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);\r
-        p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);\r
-#ifdef SAFE_SETPIXEL\r
-    }\r
-#endif    \r
-}\r
-\r
-/**\r
-    \brief  This function renders a line on a particular canvas buffer,\r
-            using Bresenham's line drawing function.\r
-            http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html \r
-            Coordinates are interpreted as SCREENcoordinates\r
-*/\r
-static void \r
-sp_caxonomgrid_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba) {\r
-    int dy = y1 - y0;\r
-    int dx = x1 - x0;\r
-    int stepx, stepy;\r
-\r
-    if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }\r
-    if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }\r
-    dy <<= 1;                                                  // dy is now 2*dy\r
-    dx <<= 1;                                                  // dx is now 2*dx\r
-\r
-    sp_caxonomgrid_setpixel(buf, x0, y0, rgba);\r
-    if (dx > dy) {\r
-        int fraction = dy - (dx >> 1);                         // same as 2*dy - dx\r
-        while (x0 != x1) {\r
-            if (fraction >= 0) {\r
-                y0 += stepy;\r
-                fraction -= dx;                                // same as fraction -= 2*dx\r
-            }\r
-            x0 += stepx;\r
-            fraction += dy;                                    // same as fraction -= 2*dy\r
-            sp_caxonomgrid_setpixel(buf, x0, y0, rgba);\r
-        }\r
-    } else {\r
-        int fraction = dx - (dy >> 1);\r
-        while (y0 != y1) {\r
-            if (fraction >= 0) {\r
-                x0 += stepx;\r
-                fraction -= dy;\r
-            }\r
-            y0 += stepy;\r
-            fraction += dx;\r
-            sp_caxonomgrid_setpixel(buf, x0, y0, rgba);\r
-        }\r
-    }\r
-    \r
-}\r
-\r
-static void\r
-sp_grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba)\r
-{\r
-    if ((x >= buf->rect.x0) && (x < buf->rect.x1)) {\r
-        guint r, g, b, a;\r
-        gint y0, y1, y;\r
-        guchar *p;\r
-        r = NR_RGBA32_R(rgba);\r
-        g = NR_RGBA32_G (rgba);\r
-        b = NR_RGBA32_B (rgba);\r
-        a = NR_RGBA32_A (rgba);\r
-        y0 = MAX (buf->rect.y0, ys);\r
-        y1 = MIN (buf->rect.y1, ye + 1);\r
-        p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;\r
-        for (y = y0; y < y1; y++) {\r
-            p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);\r
-            p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);\r
-            p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);\r
-            p += buf->buf_rowstride;\r
-        }\r
-    }\r
-}\r
-\r
-/**\r
-    \brief  This function renders the grid on a particular canvas buffer\r
-    \param  item  The grid to render on the buffer\r
-    \param  buf   The buffer to render the grid on\r
-    \r
-    This function gets called a touch more than you might believe,\r
-    about once per tile.  This means that it could probably be optimized\r
-    and help things out.\r
-\r
-    Basically this function has to determine where in the canvas it is,\r
-    and how that associates with the grid.  It does this first by looking\r
-    at the bounding box of the buffer, and then calculates where the grid\r
-    starts in that buffer.  It will then step through grid lines until\r
-    it is outside of the buffer.\r
-\r
-    For each grid line it is drawn using the function \c sp_grid_hline\r
-    or \c sp_grid_vline.  These are convience functions for the sake\r
-    of making the function easier to read.\r
-\r
-    Also, there are emphasized lines on the grid.  While the \c syg and\r
-    \c sxg variable track grid positioning, the \c xlinestart and \c\r
-    ylinestart variables track the 'count' of what lines they are.  If\r
-    that count is a multiple of the line seperation between emphasis\r
-    lines, then that line is drawn in the emphasis color.\r
-*/\r
-static void\r
-sp_caxonomgrid_render (SPCanvasItem * item, SPCanvasBuf * buf)\r
-{\r
-    SPCAxonomGrid *grid = SP_CAXONOMGRID (item);\r
-\r
-    sp_canvas_prepare_buffer (buf);\r
-              \r
-     // gc = gridcoordinates (the coordinates calculated from the grids origin 'grid->ow'.\r
-     // sc = screencoordinates ( for example "buf->rect.x0" is in screencoordinates )\r
-     // bc = buffer patch coordinates \r
-     \r
-     // tl = topleft ; br = bottomright\r
-    NR::Point buf_tl_gc;\r
-    NR::Point buf_br_gc;\r
-    buf_tl_gc[NR::X] = buf->rect.x0 - grid->ow[NR::X];\r
-    buf_tl_gc[NR::Y] = buf->rect.y0 - grid->ow[NR::Y];\r
-    buf_br_gc[NR::X] = buf->rect.x1 - grid->ow[NR::X];\r
-    buf_br_gc[NR::Y] = buf->rect.y1 - grid->ow[NR::Y];\r
-\r
-\r
-    gdouble x;\r
-    gdouble y;\r
-\r
-    // render the three separate line groups representing the main-axes:\r
-    // x-axis always goes from topleft to bottomright. (0,0) - (1,1)  \r
-    const gdouble xintercept_y_bc = (buf_tl_gc[NR::X] * grid->tan_angle[X]) - buf_tl_gc[NR::Y] ;\r
-    const gdouble xstart_y_sc = ( xintercept_y_bc - floor(xintercept_y_bc/grid->lyw)*grid->lyw ) + buf->rect.y0;\r
-    const gint  xlinestart = (gint) Inkscape::round( (xstart_y_sc - grid->ow[NR::Y]) / grid->lyw );\r
-    gint xlinenum;\r
-    // lijnen vanaf linker zijkant.\r
-    for (y = xstart_y_sc, xlinenum = xlinestart; y < buf->rect.y1; y += grid->lyw, xlinenum++) {\r
-        const gint x0 = buf->rect.x0;\r
-        const gint y0 = (gint) Inkscape::round(y);\r
-        const gint x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - y) / grid->tan_angle[X] );\r
-        const gint y1 = buf->rect.y1;\r
-            \r
-        if (!grid->scaled && (xlinenum % grid->empspacing) == 0) {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
-        } else {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
-        }\r
-    }\r
-    // lijnen vanaf bovenkant.\r
-    const gdouble xstart_x_sc = buf->rect.x0 + (grid->lxw_x - (xstart_y_sc - buf->rect.y0) / grid->tan_angle[X]) ;\r
-    for (x = xstart_x_sc, xlinenum = xlinestart; x < buf->rect.x1; x += grid->lxw_x, xlinenum--) {\r
-        const gint y0 = buf->rect.y0;\r
-        const gint y1 = buf->rect.y1;\r
-        const gint x0 = (gint) Inkscape::round(x);\r
-        const gint x1 = x0 + (gint) Inkscape::round( (y1 - y0) / grid->tan_angle[X] );\r
-            \r
-        if (!grid->scaled && (xlinenum % grid->empspacing) == 0) {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
-        } else {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
-        }\r
-    }\r
-    \r
-\r
-    // y-axis lines (vertical)\r
-    const gdouble ystart_x_sc = floor (buf_tl_gc[NR::X] / grid->spacing_ylines) * grid->spacing_ylines + grid->ow[NR::X];\r
-    const gint  ylinestart = (gint) Inkscape::round((ystart_x_sc - grid->ow[NR::X]) / grid->spacing_ylines);\r
-    gint ylinenum;\r
-    for (x = ystart_x_sc, ylinenum = ylinestart; x < buf->rect.x1; x += grid->spacing_ylines, ylinenum++) {\r
-        const gint x0 = (gint) Inkscape::round(x);\r
-\r
-        if (!grid->scaled && (ylinenum % grid->empspacing) == 0) {\r
-            sp_grid_vline (buf, x0, buf->rect.y0, buf->rect.y1 - 1, grid->empcolor);\r
-        } else {\r
-            sp_grid_vline (buf, x0, buf->rect.y0, buf->rect.y1 - 1, grid->color);\r
-        }\r
-    }\r
-\r
-    // z-axis always goes from bottomleft to topright. (0,1) - (1,0)  \r
-    const gdouble zintercept_y_bc = (buf_tl_gc[NR::X] * -grid->tan_angle[Z]) - buf_tl_gc[NR::Y] ;\r
-    const gdouble zstart_y_sc = ( zintercept_y_bc - floor(zintercept_y_bc/grid->lyw)*grid->lyw ) + buf->rect.y0;\r
-    const gint  zlinestart = (gint) Inkscape::round( (zstart_y_sc - grid->ow[NR::Y]) / grid->lyw );\r
-    gint zlinenum;\r
-    // lijnen vanaf linker zijkant.\r
-    for (y = zstart_y_sc, zlinenum = zlinestart; y < buf->rect.y1; y += grid->lyw, zlinenum++) {\r
-        const gint x0 = buf->rect.x0;\r
-        const gint y0 = (gint) Inkscape::round(y);\r
-        const gint x1 = x0 + (gint) Inkscape::round( (y - buf->rect.y0 ) / grid->tan_angle[Z] );\r
-        const gint y1 = buf->rect.y0;\r
-            \r
-        if (!grid->scaled && (zlinenum % grid->empspacing) == 0) {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
-        } else {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
-        }\r
-    }\r
-    // lijnen vanaf onderkant.\r
-    const gdouble zstart_x_sc = buf->rect.x0 + (y - buf->rect.y1) / grid->tan_angle[Z] ;\r
-    for (x = zstart_x_sc; x < buf->rect.x1; x += grid->lxw_z, zlinenum--) {\r
-        const gint y0 = buf->rect.y1;\r
-        const gint y1 = buf->rect.y0;\r
-        const gint x0 = (gint) Inkscape::round(x);\r
-        const gint x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - buf->rect.y0) / grid->tan_angle[Z] );\r
-            \r
-        if (!grid->scaled && (zlinenum % grid->empspacing) == 0) {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
-        } else {\r
-            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
-        }\r
-    }\r
-    \r
-}\r
-\r
-static void\r
-sp_caxonomgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags)\r
-{\r
-    SPCAxonomGrid *grid = SP_CAXONOMGRID (item);\r
-\r
-    if (parent_class->update)\r
-        (* parent_class->update) (item, affine, flags);\r
-\r
-    grid->ow = grid->origin * affine;\r
-    grid->sw = NR::Point(fabs(affine[0]),fabs(affine[3]));\r
-    \r
-    for(int dim = 0; dim < 2; dim++) {\r
-        gint scaling_factor = grid->empspacing;\r
-\r
-        if (scaling_factor <= 1)\r
-            scaling_factor = 5;\r
-\r
-        grid->scaled = FALSE;\r
-        while (grid->sw[dim] < 8.0) {\r
-            grid->scaled = TRUE;\r
-            grid->sw[dim] *= scaling_factor;\r
-            // First pass, go up to the major line spacing, then\r
-            // keep increasing by two.\r
-            scaling_factor = 2;\r
-        }\r
-    }\r
-\r
-    grid->spacing_ylines = grid->sw[NR::X] * grid->lengthy  /(grid->tan_angle[X] + grid->tan_angle[Z]);\r
-    grid->lyw            = grid->lengthy * grid->sw[NR::Y];\r
-    grid->lxw_x          = (grid->lengthy / grid->tan_angle[X]) * grid->sw[NR::X];\r
-    grid->lxw_z          = (grid->lengthy / grid->tan_angle[Z]) * grid->sw[NR::X];\r
-\r
-    if (grid->empspacing == 0) {\r
-        grid->scaled = TRUE;\r
-    }\r
-\r
-    sp_canvas_request_redraw (item->canvas,\r
-                     -1000000, -1000000,\r
-                     1000000, 1000000);\r
-                     \r
-    item->x1 = item->y1 = -1000000;\r
-    item->x2 = item->y2 = 1000000;\r
-}\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+#define SP_CANVAS_AXONOMGRID_C
+
+/*
+ * SPCAxonomGrid
+ *
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
+ * Copyright (C) 2000 Lauris Kaplinski
+ *
+ */                         
+ /* 
+  * Current limits are: one axis (y-axis) is always vertical. The other two
+  * axes are bound to a certain range of angles. The z-axis always has an angle 
+  * smaller than 90 degrees (measured from horizontal, 0 degrees being a line extending
+  * to the right). The x-axis will always have an angle between 0 and 90 degrees.
+  * When I quickly think about it: all possibilities are probably covered this way. Eg.
+  * a z-axis with negative angle can be replaced with an x-axis, etc.
+  */              
+  
+ /*
+  *  TODO:  LOTS LOTS LOTS. Optimization etc.
+  *
+  */
+
+#include "sp-canvas-util.h"
+#include "canvas-axonomgrid.h"
+#include "display-forward.h"
+#include <libnr/nr-pixops.h>
+
+#define SAFE_SETPIXEL   //undefine this when it is certain that setpixel is never called with invalid params
+
+enum {
+    ARG_0,
+    ARG_ORIGINX,
+    ARG_ORIGINY,
+    ARG_ANGLEX,
+    ARG_SPACINGY,
+    ARG_ANGLEZ,
+    ARG_COLOR,
+    ARG_EMPCOLOR,
+    ARG_EMPSPACING
+};
+
+enum Dim3 { X=0, Y, Z };
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+static double deg_to_rad(double deg) { return deg*M_PI/180.0;}
+
+
+static void sp_caxonomgrid_class_init (SPCAxonomGridClass *klass);
+static void sp_caxonomgrid_init (SPCAxonomGrid *grid);
+static void sp_caxonomgrid_destroy (GtkObject *object);
+static void sp_caxonomgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
+
+static void sp_caxonomgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags);
+static void sp_caxonomgrid_render (SPCanvasItem *item, SPCanvasBuf *buf);
+
+static SPCanvasItemClass * parent_class;
+
+GtkType
+sp_caxonomgrid_get_type (void)
+{
+    static GtkType caxonomgrid_type = 0;
+
+    if (!caxonomgrid_type) {
+        GtkTypeInfo caxonomgrid_info = {
+            "SPCAxonomGrid",
+            sizeof (SPCAxonomGrid),
+            sizeof (SPCAxonomGridClass),
+            (GtkClassInitFunc) sp_caxonomgrid_class_init,
+            (GtkObjectInitFunc) sp_caxonomgrid_init,
+            NULL, NULL,
+            (GtkClassInitFunc) NULL
+        };
+        caxonomgrid_type = gtk_type_unique (sp_canvas_item_get_type (), &caxonomgrid_info);
+    }
+    return caxonomgrid_type;
+}
+
+static void
+sp_caxonomgrid_class_init (SPCAxonomGridClass *klass)
+{
+
+    GtkObjectClass *object_class;
+    SPCanvasItemClass *item_class;
+
+    object_class = (GtkObjectClass *) klass;
+    item_class = (SPCanvasItemClass *) klass;
+
+    parent_class = (SPCanvasItemClass*)gtk_type_class (sp_canvas_item_get_type ());
+
+    gtk_object_add_arg_type ("SPCAxonomGrid::originx", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINX);
+    gtk_object_add_arg_type ("SPCAxonomGrid::originy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINY);
+    gtk_object_add_arg_type ("SPCAxonomGrid::anglex", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ANGLEX);
+    gtk_object_add_arg_type ("SPCAxonomGrid::spacingy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_SPACINGY);
+    gtk_object_add_arg_type ("SPCAxonomGrid::anglez", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ANGLEZ);
+    gtk_object_add_arg_type ("SPCAxonomGrid::color", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_COLOR);
+    gtk_object_add_arg_type ("SPCAxonomGrid::empcolor", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPCOLOR);
+    gtk_object_add_arg_type ("SPCAxonomGrid::empspacing", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPSPACING);
+
+    object_class->destroy = sp_caxonomgrid_destroy;
+    object_class->set_arg = sp_caxonomgrid_set_arg;
+
+    item_class->update = sp_caxonomgrid_update;
+    item_class->render = sp_caxonomgrid_render;
+  
+}
+
+static void
+sp_caxonomgrid_init (SPCAxonomGrid *grid)
+{
+    grid->origin[NR::X] = grid->origin[NR::Y] = 0.0;
+//    grid->spacing[X] = grid->spacing[Y] = grid->spacing[Z] = 8.0;
+    grid->color = 0x0000ff7f;
+    grid->empcolor = 0x3F3FFF40;
+    grid->empspacing = 5;
+}
+
+static void
+sp_caxonomgrid_destroy (GtkObject *object)
+{
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (SP_IS_CAXONOMGRID (object));
+
+    if (GTK_OBJECT_CLASS (parent_class)->destroy)
+        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+sp_caxonomgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+    SPCanvasItem *item = SP_CANVAS_ITEM (object);
+    SPCAxonomGrid *grid = SP_CAXONOMGRID (object);
+    
+    switch (arg_id) {
+    case ARG_ORIGINX:
+        grid->origin[NR::X] = GTK_VALUE_DOUBLE (* arg);
+        sp_canvas_item_request_update (item);
+        break;
+    case ARG_ORIGINY:
+        grid->origin[NR::Y] = GTK_VALUE_DOUBLE (* arg);
+        sp_canvas_item_request_update (item);
+        break;
+    case ARG_ANGLEX:
+        grid->angle_deg[X] = GTK_VALUE_DOUBLE (* arg);
+        if (grid->angle_deg[X] < 0.0) grid->angle_deg[X] = 0.0;
+        if (grid->angle_deg[X] > 89.0) grid->angle_deg[X] = 89.0;
+        grid->angle_rad[X] = deg_to_rad(grid->angle_deg[X]);
+        grid->tan_angle[X] = tan(grid->angle_rad[X]);
+        sp_canvas_item_request_update (item);
+        break;
+    case ARG_SPACINGY:
+        grid->lengthy = GTK_VALUE_DOUBLE (* arg);
+        if (grid->lengthy < 0.01) grid->lengthy = 0.01;
+        sp_canvas_item_request_update (item);
+        break;
+    case ARG_ANGLEZ:
+        grid->angle_deg[Z] = GTK_VALUE_DOUBLE (* arg);
+        if (grid->angle_deg[Z] < 0.0) grid->angle_deg[Z] = 0.0;
+        if (grid->angle_deg[X] > 89.0) grid->angle_deg[X] = 89.0;
+        grid->angle_rad[Z] = deg_to_rad(grid->angle_deg[Z]);
+        grid->tan_angle[Z] = tan(grid->angle_rad[Z]);
+        sp_canvas_item_request_update (item);
+        break;
+    case ARG_COLOR:
+        grid->color = GTK_VALUE_INT (* arg);
+        sp_canvas_item_request_update (item);
+        break;
+    case ARG_EMPCOLOR:
+        grid->empcolor = GTK_VALUE_INT (* arg);
+        sp_canvas_item_request_update (item);
+        break;
+    case ARG_EMPSPACING:
+        grid->empspacing = GTK_VALUE_INT (* arg);
+        // std::cout << "Emphasis Spacing: " << grid->empspacing << std::endl;
+        sp_canvas_item_request_update (item);
+        break;
+    default:
+        break;
+    }
+}
+
+
+
+/**
+    \brief  This function renders a pixel on a particular buffer.
+                
+    The topleft of the buffer equals
+                        ( rect.x0 , rect.y0 )  in screen coordinates
+                        ( 0 , 0 )  in setpixel coordinates
+    The bottomright of the buffer equals
+                        ( rect.x1 , rect,y1 )  in screen coordinates
+                        ( rect.x1 - rect.x0 , rect.y1 - rect.y0 )  in setpixel coordinates
+*/
+static void 
+sp_caxonomgrid_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba) {
+#ifdef SAFE_SETPIXEL
+    if ( (x >= buf->rect.x0) && (x < buf->rect.x1) && (y >= buf->rect.y0) && (y < buf->rect.y1) ) {
+#endif        
+        guint r, g, b, a;          
+        r = NR_RGBA32_R (rgba);
+        g = NR_RGBA32_G (rgba);
+        b = NR_RGBA32_B (rgba);
+        a = NR_RGBA32_A (rgba);  
+        guchar * p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;
+        p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
+        p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
+        p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
+#ifdef SAFE_SETPIXEL
+    }
+#endif    
+}
+
+/**
+    \brief  This function renders a line on a particular canvas buffer,
+            using Bresenham's line drawing function.
+            http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html 
+            Coordinates are interpreted as SCREENcoordinates
+*/
+static void 
+sp_caxonomgrid_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba) {
+    int dy = y1 - y0;
+    int dx = x1 - x0;
+    int stepx, stepy;
+
+    if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }
+    if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }
+    dy <<= 1;                                                  // dy is now 2*dy
+    dx <<= 1;                                                  // dx is now 2*dx
+
+    sp_caxonomgrid_setpixel(buf, x0, y0, rgba);
+    if (dx > dy) {
+        int fraction = dy - (dx >> 1);                         // same as 2*dy - dx
+        while (x0 != x1) {
+            if (fraction >= 0) {
+                y0 += stepy;
+                fraction -= dx;                                // same as fraction -= 2*dx
+            }
+            x0 += stepx;
+            fraction += dy;                                    // same as fraction -= 2*dy
+            sp_caxonomgrid_setpixel(buf, x0, y0, rgba);
+        }
+    } else {
+        int fraction = dx - (dy >> 1);
+        while (y0 != y1) {
+            if (fraction >= 0) {
+                x0 += stepx;
+                fraction -= dy;
+            }
+            y0 += stepy;
+            fraction += dx;
+            sp_caxonomgrid_setpixel(buf, x0, y0, rgba);
+        }
+    }
+    
+}
+
+static void
+sp_grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba)
+{
+    if ((x >= buf->rect.x0) && (x < buf->rect.x1)) {
+        guint r, g, b, a;
+        gint y0, y1, y;
+        guchar *p;
+        r = NR_RGBA32_R(rgba);
+        g = NR_RGBA32_G (rgba);
+        b = NR_RGBA32_B (rgba);
+        a = NR_RGBA32_A (rgba);
+        y0 = MAX (buf->rect.y0, ys);
+        y1 = MIN (buf->rect.y1, ye + 1);
+        p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;
+        for (y = y0; y < y1; y++) {
+            p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
+            p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
+            p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
+            p += buf->buf_rowstride;
+        }
+    }
+}
+
+/**
+    \brief  This function renders the grid on a particular canvas buffer
+    \param  item  The grid to render on the buffer
+    \param  buf   The buffer to render the grid on
+    
+    This function gets called a touch more than you might believe,
+    about once per tile.  This means that it could probably be optimized
+    and help things out.
+
+    Basically this function has to determine where in the canvas it is,
+    and how that associates with the grid.  It does this first by looking
+    at the bounding box of the buffer, and then calculates where the grid
+    starts in that buffer.  It will then step through grid lines until
+    it is outside of the buffer.
+
+    For each grid line it is drawn using the function \c sp_grid_hline
+    or \c sp_grid_vline.  These are convience functions for the sake
+    of making the function easier to read.
+
+    Also, there are emphasized lines on the grid.  While the \c syg and
+    \c sxg variable track grid positioning, the \c xlinestart and \c
+    ylinestart variables track the 'count' of what lines they are.  If
+    that count is a multiple of the line seperation between emphasis
+    lines, then that line is drawn in the emphasis color.
+*/
+static void
+sp_caxonomgrid_render (SPCanvasItem * item, SPCanvasBuf * buf)
+{
+    SPCAxonomGrid *grid = SP_CAXONOMGRID (item);
+
+    sp_canvas_prepare_buffer (buf);
+              
+     // gc = gridcoordinates (the coordinates calculated from the grids origin 'grid->ow'.
+     // sc = screencoordinates ( for example "buf->rect.x0" is in screencoordinates )
+     // bc = buffer patch coordinates 
+     
+     // tl = topleft ; br = bottomright
+    NR::Point buf_tl_gc;
+    NR::Point buf_br_gc;
+    buf_tl_gc[NR::X] = buf->rect.x0 - grid->ow[NR::X];
+    buf_tl_gc[NR::Y] = buf->rect.y0 - grid->ow[NR::Y];
+    buf_br_gc[NR::X] = buf->rect.x1 - grid->ow[NR::X];
+    buf_br_gc[NR::Y] = buf->rect.y1 - grid->ow[NR::Y];
+
+
+    gdouble x;
+    gdouble y;
+
+    // render the three separate line groups representing the main-axes:
+    // x-axis always goes from topleft to bottomright. (0,0) - (1,1)  
+    const gdouble xintercept_y_bc = (buf_tl_gc[NR::X] * grid->tan_angle[X]) - buf_tl_gc[NR::Y] ;
+    const gdouble xstart_y_sc = ( xintercept_y_bc - floor(xintercept_y_bc/grid->lyw)*grid->lyw ) + buf->rect.y0;
+    const gint  xlinestart = (gint) Inkscape::round( (xstart_y_sc - grid->ow[NR::Y]) / grid->lyw );
+    gint xlinenum;
+    // lijnen vanaf linker zijkant.
+    for (y = xstart_y_sc, xlinenum = xlinestart; y < buf->rect.y1; y += grid->lyw, xlinenum++) {
+        const gint x0 = buf->rect.x0;
+        const gint y0 = (gint) Inkscape::round(y);
+        const gint x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - y) / grid->tan_angle[X] );
+        const gint y1 = buf->rect.y1;
+            
+        if (!grid->scaled && (xlinenum % grid->empspacing) == 0) {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);
+        } else {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);
+        }
+    }
+    // lijnen vanaf bovenkant.
+    const gdouble xstart_x_sc = buf->rect.x0 + (grid->lxw_x - (xstart_y_sc - buf->rect.y0) / grid->tan_angle[X]) ;
+    for (x = xstart_x_sc, xlinenum = xlinestart; x < buf->rect.x1; x += grid->lxw_x, xlinenum--) {
+        const gint y0 = buf->rect.y0;
+        const gint y1 = buf->rect.y1;
+        const gint x0 = (gint) Inkscape::round(x);
+        const gint x1 = x0 + (gint) Inkscape::round( (y1 - y0) / grid->tan_angle[X] );
+            
+        if (!grid->scaled && (xlinenum % grid->empspacing) == 0) {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);
+        } else {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);
+        }
+    }
+    
+
+    // y-axis lines (vertical)
+    const gdouble ystart_x_sc = floor (buf_tl_gc[NR::X] / grid->spacing_ylines) * grid->spacing_ylines + grid->ow[NR::X];
+    const gint  ylinestart = (gint) Inkscape::round((ystart_x_sc - grid->ow[NR::X]) / grid->spacing_ylines);
+    gint ylinenum;
+    for (x = ystart_x_sc, ylinenum = ylinestart; x < buf->rect.x1; x += grid->spacing_ylines, ylinenum++) {
+        const gint x0 = (gint) Inkscape::round(x);
+
+        if (!grid->scaled && (ylinenum % grid->empspacing) == 0) {
+            sp_grid_vline (buf, x0, buf->rect.y0, buf->rect.y1 - 1, grid->empcolor);
+        } else {
+            sp_grid_vline (buf, x0, buf->rect.y0, buf->rect.y1 - 1, grid->color);
+        }
+    }
+
+    // z-axis always goes from bottomleft to topright. (0,1) - (1,0)  
+    const gdouble zintercept_y_bc = (buf_tl_gc[NR::X] * -grid->tan_angle[Z]) - buf_tl_gc[NR::Y] ;
+    const gdouble zstart_y_sc = ( zintercept_y_bc - floor(zintercept_y_bc/grid->lyw)*grid->lyw ) + buf->rect.y0;
+    const gint  zlinestart = (gint) Inkscape::round( (zstart_y_sc - grid->ow[NR::Y]) / grid->lyw );
+    gint zlinenum;
+    // lijnen vanaf linker zijkant.
+    for (y = zstart_y_sc, zlinenum = zlinestart; y < buf->rect.y1; y += grid->lyw, zlinenum++) {
+        const gint x0 = buf->rect.x0;
+        const gint y0 = (gint) Inkscape::round(y);
+        const gint x1 = x0 + (gint) Inkscape::round( (y - buf->rect.y0 ) / grid->tan_angle[Z] );
+        const gint y1 = buf->rect.y0;
+            
+        if (!grid->scaled && (zlinenum % grid->empspacing) == 0) {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);
+        } else {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);
+        }
+    }
+    // lijnen vanaf onderkant.
+    const gdouble zstart_x_sc = buf->rect.x0 + (y - buf->rect.y1) / grid->tan_angle[Z] ;
+    for (x = zstart_x_sc; x < buf->rect.x1; x += grid->lxw_z, zlinenum--) {
+        const gint y0 = buf->rect.y1;
+        const gint y1 = buf->rect.y0;
+        const gint x0 = (gint) Inkscape::round(x);
+        const gint x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - buf->rect.y0) / grid->tan_angle[Z] );
+            
+        if (!grid->scaled && (zlinenum % grid->empspacing) == 0) {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);
+        } else {
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);
+        }
+    }
+    
+}
+
+static void
+sp_caxonomgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags)
+{
+    SPCAxonomGrid *grid = SP_CAXONOMGRID (item);
+
+    if (parent_class->update)
+        (* parent_class->update) (item, affine, flags);
+
+    grid->ow = grid->origin * affine;
+    grid->sw = NR::Point(fabs(affine[0]),fabs(affine[3]));
+    
+    for(int dim = 0; dim < 2; dim++) {
+        gint scaling_factor = grid->empspacing;
+
+        if (scaling_factor <= 1)
+            scaling_factor = 5;
+
+        grid->scaled = FALSE;
+        while (grid->sw[dim] < 8.0) {
+            grid->scaled = TRUE;
+            grid->sw[dim] *= scaling_factor;
+            // First pass, go up to the major line spacing, then
+            // keep increasing by two.
+            scaling_factor = 2;
+        }
+    }
+
+    grid->spacing_ylines = grid->sw[NR::X] * grid->lengthy  /(grid->tan_angle[X] + grid->tan_angle[Z]);
+    grid->lyw            = grid->lengthy * grid->sw[NR::Y];
+    grid->lxw_x          = (grid->lengthy / grid->tan_angle[X]) * grid->sw[NR::X];
+    grid->lxw_z          = (grid->lengthy / grid->tan_angle[Z]) * grid->sw[NR::X];
+
+    if (grid->empspacing == 0) {
+        grid->scaled = TRUE;
+    }
+
+    sp_canvas_request_redraw (item->canvas,
+                     -1000000, -1000000,
+                     1000000, 1000000);
+                     
+    item->x1 = item->y1 = -1000000;
+    item->x2 = item->y2 = 1000000;
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 22fceed4473560fc5cf79a09ed0d7375bd80a295..79de72b43340abe7adf65eba7980445207a3f723 100644 (file)
@@ -1,59 +1,59 @@
-#ifndef SP_CANVAS_AXONOMGRID_H\r
-#define SP_CANVAS_AXONOMGRID_H\r
-\r
-/*\r
- * SPCAxonomGrid\r
- *\r
- * Generic (and quite unintelligent) modified copy of the grid item for gnome canvas\r
- *\r
- * Copyright (C) 2006 Johan Engelen  <johan@shouraizou.nl>\r
- * Copyright (C) 2000 Lauris Kaplinski 2000\r
- *\r
- */\r
-\r
-#include <display/sp-canvas.h>\r
-#include <libnr/nr-coord.h>\r
-\r
-\r
-#define SP_TYPE_CAXONOMGRID            (sp_caxonomgrid_get_type ())\r
-#define SP_CAXONOMGRID(obj)            (GTK_CHECK_CAST ((obj), SP_TYPE_CAXONOMGRID, SPCAxonomGrid))\r
-#define SP_CAXONOMGRID_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_CAXONOMGRID, SPCAxonomGridClass))\r
-#define SP_IS_CAXONOMGRID(obj)         (GTK_CHECK_TYPE ((obj), SP_TYPE_CAXONOMGRID))\r
-#define SP_IS_CAXONOMGRID_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_CAXONOMGRID))\r
-\r
-\r
-/** \brief  All the variables that are tracked for a axonometric grid specific\r
-            canvas item. */\r
-struct SPCAxonomGrid : public SPCanvasItem{\r
-       NR::Point origin;     /**< Origin of the grid */\r
-       double lengthy;       /**< The lengths of the primary y-axis */\r
-       double angle_deg[3];  /**< Angle of each axis (note that angle[2] == 0) */\r
-       double angle_rad[3];  /**< Angle of each axis (note that angle[2] == 0) */\r
-       double tan_angle[3];  /**< tan(angle[.]) */\r
-       guint32 color;        /**< Color for normal lines */\r
-       guint32 empcolor;     /**< Color for emphasis lines */\r
-       gint empspacing;      /**< Spacing between emphasis lines */\r
-       bool scaled;          /**< Whether the grid is in scaled mode */\r
-       \r
-       NR::Point ow;         /**< Transformed origin by the affine for the zoom */\r
-       double lyw;           /**< Transformed length y by the affine for the zoom */\r
-       double lxw_x;\r
-       double lxw_z;\r
-       double spacing_ylines;\r
-                          \r
-    NR::Point sw;          /**< the scaling factors of the affine transform */\r
-};\r
-\r
-struct SPCAxonomGridClass {\r
-       SPCanvasItemClass parent_class;\r
-};\r
-\r
-\r
-/* Standard Gtk function */\r
-GtkType sp_caxonomgrid_get_type (void);\r
-\r
-\r
-\r
-#endif    \r
-\r
-\r
+#ifndef SP_CANVAS_AXONOMGRID_H
+#define SP_CANVAS_AXONOMGRID_H
+
+/*
+ * SPCAxonomGrid
+ *
+ * Generic (and quite unintelligent) modified copy of the grid item for gnome canvas
+ *
+ * Copyright (C) 2006 Johan Engelen  <johan@shouraizou.nl>
+ * Copyright (C) 2000 Lauris Kaplinski 2000
+ *
+ */
+
+#include <display/sp-canvas.h>
+#include <libnr/nr-coord.h>
+
+
+#define SP_TYPE_CAXONOMGRID            (sp_caxonomgrid_get_type ())
+#define SP_CAXONOMGRID(obj)            (GTK_CHECK_CAST ((obj), SP_TYPE_CAXONOMGRID, SPCAxonomGrid))
+#define SP_CAXONOMGRID_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_CAXONOMGRID, SPCAxonomGridClass))
+#define SP_IS_CAXONOMGRID(obj)         (GTK_CHECK_TYPE ((obj), SP_TYPE_CAXONOMGRID))
+#define SP_IS_CAXONOMGRID_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_CAXONOMGRID))
+
+
+/** \brief  All the variables that are tracked for a axonometric grid specific
+            canvas item. */
+struct SPCAxonomGrid : public SPCanvasItem{
+       NR::Point origin;     /**< Origin of the grid */
+       double lengthy;       /**< The lengths of the primary y-axis */
+       double angle_deg[3];  /**< Angle of each axis (note that angle[2] == 0) */
+       double angle_rad[3];  /**< Angle of each axis (note that angle[2] == 0) */
+       double tan_angle[3];  /**< tan(angle[.]) */
+       guint32 color;        /**< Color for normal lines */
+       guint32 empcolor;     /**< Color for emphasis lines */
+       gint empspacing;      /**< Spacing between emphasis lines */
+       bool scaled;          /**< Whether the grid is in scaled mode */
+       
+       NR::Point ow;         /**< Transformed origin by the affine for the zoom */
+       double lyw;           /**< Transformed length y by the affine for the zoom */
+       double lxw_x;
+       double lxw_z;
+       double spacing_ylines;
+                          
+    NR::Point sw;          /**< the scaling factors of the affine transform */
+};
+
+struct SPCAxonomGridClass {
+       SPCanvasItemClass parent_class;
+};
+
+
+/* Standard Gtk function */
+GtkType sp_caxonomgrid_get_type (void);
+
+
+
+#endif    
+
+
index be0c9c5be34c7d5a99e1708c33aba02500930a26..7ebeebd88bc6d4e497add35da11882eba21eb159 100644 (file)
@@ -501,7 +501,7 @@ int FilterGaussian::render(FilterSlot &slot, Matrix const &trans)
     int const PC = NR_PIXBLOCK_BPP(in);
 
     // Subsampling constants
-    int const quality = prefs_get_int_attribute("options.blurquality", "value", 0);\r
+    int const quality = prefs_get_int_attribute("options.blurquality", "value", 0);
     int const x_step_l2 = _effect_subsample_step_log2(deviation_x_org, quality);
     int const y_step_l2 = _effect_subsample_step_log2(deviation_y_org, quality);
     int const x_step = 1<<x_step_l2;
index 3c30ad58a15ca8d429199e9c40f4c4931f8210aa..f31f0e4f96affd880b9e072efb02709753e848a4 100644 (file)
-/**\r
- * Secure Hashing Tool\r
- * *\r
- * Authors:\r
- *   Bob Jamison\r
- *\r
- * Copyright (C) 2006 Bob Jamison\r
- *\r
- *  This library is free software; you can redistribute it and/or\r
- *  modify it under the terms of the GNU Lesser General Public\r
- *  License as published by the Free Software Foundation; either\r
- *  version 2.1 of the License, or (at your option) any later version.\r
- *\r
- *  This library is distributed in the hope that it will be useful,\r
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- *  Lesser General Public License for more details.\r
- *\r
- *  You should have received a copy of the GNU Lesser General Public\r
- *  License along with this library; if not, write to the Free Software\r
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
- */\r
-\r
-#include "digest.h"\r
-\r
-\r
-//########################################################################\r
-//##  U T I L\r
-//########################################################################\r
-\r
-/**\r
- * Use this to print out a 64-bit int when otherwise difficult\r
- */\r
-/*\r
-static void pl(unsigned long long val)\r
-{\r
-    for (int shift=56 ; shift>=0 ; shift-=8)\r
-        {\r
-        int ch = (val >> shift) & 0xff;\r
-        printf("%02x", ch);\r
-        }\r
-}\r
-*/\r
-\r
-\r
-static char *hexDigits = "0123456789abcdef";\r
-\r
-static std::string toHex(const std::vector<unsigned char> &bytes)\r
-{\r
-    std::string str;\r
-    std::vector<unsigned char>::const_iterator iter;\r
-    for (iter = bytes.begin() ; iter != bytes.end() ; iter++)\r
-       {\r
-       unsigned char ch = *iter;\r
-       str.push_back(hexDigits[(ch>>4) & 0x0f]);\r
-       str.push_back(hexDigits[(ch   ) & 0x0f]);\r
-       }\r
-    return str;\r
-}\r
-\r
-\r
-//########################################################################\r
-//##  D I G E S T\r
-//########################################################################\r
-\r
-\r
-/**\r
- *\r
- */\r
-std::string Digest::finishHex()\r
-{\r
-    std::vector<unsigned char> hash = finish();\r
-    std::string str = toHex(hash);\r
-    return str;\r
-}\r
-\r
-\r
-//4.1.1 and 4.1.2\r
-#define SHA_ROTL(X,n)  ( ((X) << (n)) | ( ((X) & 0xffffffffL) >> (32-(n))) )\r
-#define        SHA_Ch(x,y,z)  ((z)^((x)&((y)^(z))))\r
-#define        SHA_Maj(x,y,z) (((x)&(y))^((z)&((x)^(y))))\r
-\r
-\r
-//########################################################################\r
-//##  S H A 1\r
-//########################################################################\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha1Digest::reset()\r
-{\r
-    lenW   = 0;\r
-    size   = 0;\r
-\r
-    // Initialize H with the magic constants (see FIPS180 for constants)\r
-    H[0] = 0x67452301L;\r
-    H[1] = 0xefcdab89L;\r
-    H[2] = 0x98badcfeL;\r
-    H[3] = 0x10325476L;\r
-    H[4] = 0xc3d2e1f0L;\r
-\r
-    for (int i = 0 ; i < 80 ; i++)\r
-        W[i] = 0;\r
-}\r
-\r
-\r
-\r
-\r
-void Sha1Digest::hashblock()\r
-{\r
-    //for (int t = 0; t < 16 ; t++)\r
-    //    printf("%2d %08lx\n", t, W[t]);\r
-\r
-    //see 6.1.2\r
-    for (int t = 16; t < 80 ; t++)\r
-        W[t] = SHA_ROTL((W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]), 1);\r
-\r
-    unsigned long a = H[0];\r
-    unsigned long b = H[1];\r
-    unsigned long c = H[2];\r
-    unsigned long d = H[3];\r
-    unsigned long e = H[4];\r
-\r
-    unsigned long T;\r
-\r
-    int t = 0;\r
-    for ( ; t < 20 ; t++)\r
-        {\r
-        //see 4.1.1 for the boolops on B,C, and D\r
-        T = (SHA_ROTL(a,5) + ((b&c)^(~b&d)) +  //Ch(b,c,d))\r
-                e + 0x5a827999L + W[t]) & 0xffffffffL;\r
-        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;\r
-        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);\r
-        }\r
-    for ( ; t < 40 ; t++)\r
-        {\r
-        T = (SHA_ROTL(a,5) + (b^c^d) +\r
-                e + 0x6ed9eba1L + W[t]) & 0xffffffffL;\r
-        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;\r
-        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);\r
-        }\r
-    for ( ; t < 60 ; t++)\r
-        {\r
-        T = (SHA_ROTL(a,5) + ((b&c)^(b&d)^(c&d)) +\r
-                e + 0x8f1bbcdcL + W[t]) & 0xffffffffL;\r
-        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;\r
-        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);\r
-        }\r
-    for ( ; t < 80 ; t++)\r
-        {\r
-        T = (SHA_ROTL(a,5) + (b^c^d) +\r
-                e + 0xca62c1d6L + W[t]) & 0xffffffffL;\r
-        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;\r
-        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);\r
-        }\r
-\r
-    H[0] += a;\r
-    H[1] += b;\r
-    H[2] += c;\r
-    H[3] += d;\r
-    H[4] += e;\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha1Digest::update(unsigned char val)\r
-{\r
-    int wordNr = lenW >> 2;\r
-    W[wordNr] <<= 8;\r
-    W[wordNr] |= (unsigned long)val;\r
-    size += 8;\r
-    lenW++;\r
-    if (lenW >= 64)\r
-        {\r
-        hashblock();\r
-        lenW = 0;\r
-        }\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-std::vector<unsigned char> Sha1Digest::finish()\r
-{\r
-    //save our size before padding\r
-    unsigned long long sizeOut = size;\r
-    \r
-    // Pad with a binary 1 (0x80)\r
-    update((unsigned char)0x80);\r
-    //append 0's to make a 56-byte buf.\r
-       //use mod, so that we will loop around once if already over 56\r
-    while (lenW != 56)\r
-        update((unsigned char)0x00);\r
-    //append 64-bit size\r
-    for (int shift = 56 ; shift>=0 ; shift-= 8)\r
-        {\r
-        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);\r
-        update(ch);\r
-        }\r
-\r
-    // Output hash\r
-    std::vector<unsigned char> ret;\r
-    for (int wordNr = 0 ; wordNr < 5 ; wordNr++)\r
-        {\r
-        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));\r
-        }\r
-\r
-    // Re-initialize the context (also zeroizes contents)\r
-    reset();\r
-\r
-    return ret;\r
-\r
-}\r
-\r
-\r
-//########################################################################\r
-//##  SHA224\r
-//########################################################################\r
-\r
-\r
-/**\r
- * SHA-224 and SHA-512 share the same operations and constants\r
- */ \r
-\r
-#define        SHA_Rot32(x,s) (((x) >> s) | ((x) << (32 - s)))\r
-#define        SHA_SIGMA0(x)  (SHA_Rot32(x,  2) ^ SHA_Rot32(x, 13) ^ SHA_Rot32(x, 22))\r
-#define        SHA_SIGMA1(x)  (SHA_Rot32(x,  6) ^ SHA_Rot32(x, 11) ^ SHA_Rot32(x, 25))\r
-#define        SHA_sigma0(x)  (SHA_Rot32(x,  7) ^ SHA_Rot32(x, 18) ^ ((x) >> 3))\r
-#define        SHA_sigma1(x)  (SHA_Rot32(x, 17) ^ SHA_Rot32(x, 19) ^ ((x) >> 10))\r
-\r
-\r
-static unsigned long sha256constants[64] =\r
-{\r
-0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,\r
-0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,\r
-0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,\r
-0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,\r
-0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,\r
-0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,\r
-0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,\r
-0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,\r
-0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,\r
-0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,\r
-0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,\r
-0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,\r
-0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,\r
-0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,\r
-0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,\r
-0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL\r
-};\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha224Digest::reset()\r
-{\r
-    lenW   = 0;\r
-    size   = 0;\r
-\r
-    // Initialize H with the magic constants (see FIPS180 for constants)\r
-    H[0] = 0xc1059ed8L;\r
-    H[1] = 0x367cd507L;\r
-    H[2] = 0x3070dd17L;\r
-    H[3] = 0xf70e5939L;\r
-    H[4] = 0xffc00b31L;\r
-    H[5] = 0x68581511L;\r
-    H[6] = 0x64f98fa7L;\r
-    H[7] = 0xbefa4fa4L;\r
-\r
-    for (int i = 0 ; i < 64 ; i++)\r
-        W[i] = 0;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-void Sha224Digest::hashblock()\r
-{\r
-    //for (int t = 0; t < 16 ; t++)\r
-    //    printf("%2d %08lx\n", t, W[t]);\r
-\r
-    //see 6.2.2\r
-    for (int t = 16; t < 64 ; t++)\r
-        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];\r
-\r
-    unsigned long a = H[0];\r
-    unsigned long b = H[1];\r
-    unsigned long c = H[2];\r
-    unsigned long d = H[3];\r
-    unsigned long e = H[4];\r
-    unsigned long f = H[5];\r
-    unsigned long g = H[6];\r
-    unsigned long h = H[7];\r
-\r
-    for (int t = 0 ; t < 64 ; t++)\r
-        {\r
-        //see 4.1.1 for the boolops\r
-        unsigned long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +\r
-            sha256constants[t] + W[t];\r
-        unsigned long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);\r
-        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;\r
-        //printf("%2d %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",\r
-               //         t, a, b, c, d, e, f, g, h);\r
-        }\r
-\r
-    H[0] += a;\r
-    H[1] += b;\r
-    H[2] += c;\r
-    H[3] += d;\r
-    H[4] += e;\r
-    H[5] += f;\r
-    H[6] += g;\r
-    H[7] += h;\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha224Digest::update(unsigned char val)\r
-{\r
-    int wordNr = lenW >> 2;\r
-    W[wordNr] <<= 8;\r
-    W[wordNr] |= (unsigned long)val;\r
-    size += 8;\r
-    lenW++;\r
-    if (lenW >= 64)\r
-        {\r
-        hashblock();\r
-        lenW = 0;\r
-        }\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-std::vector<unsigned char> Sha224Digest::finish()\r
-{\r
-    //save our size before padding\r
-    unsigned long long sizeOut = size;\r
-    \r
-    // Pad with a binary 1 (0x80)\r
-    update((unsigned char)0x80);\r
-    //append 0's to make a 56-byte buf.\r
-       //use mod, so that we will loop around once if already over 56\r
-    while (lenW != 56)\r
-        update((unsigned char)0x00);\r
-    //append 64-bit size\r
-    for (int shift = 56 ; shift>=0 ; shift-= 8)\r
-        {\r
-        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);\r
-        update(ch);\r
-        }\r
-\r
-    // Output hash\r
-    std::vector<unsigned char> ret;\r
-    for (int wordNr = 0 ; wordNr < 7 ; wordNr++)\r
-        {\r
-        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));\r
-        }\r
-\r
-    // Re-initialize the context (also zeroizes contents)\r
-    reset();\r
-\r
-    return ret;\r
-\r
-}\r
-\r
-//########################################################################\r
-//##  SHA256\r
-//########################################################################\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha256Digest::reset()\r
-{\r
-    lenW   = 0;\r
-    size   = 0;\r
-\r
-    // Initialize H with the magic constants (see FIPS180 for constants)\r
-    H[0] = 0x6a09e667L;\r
-    H[1] = 0xbb67ae85L;\r
-    H[2] = 0x3c6ef372L;\r
-    H[3] = 0xa54ff53aL;\r
-    H[4] = 0x510e527fL;\r
-    H[5] = 0x9b05688cL;\r
-    H[6] = 0x1f83d9abL;\r
-    H[7] = 0x5be0cd19L;\r
-\r
-    for (int i = 0 ; i < 64 ; i++)\r
-        W[i] = 0;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-void Sha256Digest::hashblock()\r
-{\r
-    //for (int t = 0; t < 16 ; t++)\r
-    //    printf("%2d %08lx\n", t, W[t]);\r
-\r
-    //see 6.2.2\r
-    for (int t = 16; t < 64 ; t++)\r
-        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];\r
-\r
-    unsigned long a = H[0];\r
-    unsigned long b = H[1];\r
-    unsigned long c = H[2];\r
-    unsigned long d = H[3];\r
-    unsigned long e = H[4];\r
-    unsigned long f = H[5];\r
-    unsigned long g = H[6];\r
-    unsigned long h = H[7];\r
-\r
-    for (int t = 0 ; t < 64 ; t++)\r
-        {\r
-        //see 4.1.1 for the boolops\r
-        unsigned long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +\r
-            sha256constants[t] + W[t];\r
-        unsigned long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);\r
-        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;\r
-        //printf("%2d %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",\r
-               //         t, a, b, c, d, e, f, g, h);\r
-        }\r
-\r
-    H[0] += a;\r
-    H[1] += b;\r
-    H[2] += c;\r
-    H[3] += d;\r
-    H[4] += e;\r
-    H[5] += f;\r
-    H[6] += g;\r
-    H[7] += h;\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha256Digest::update(unsigned char val)\r
-{\r
-    int wordNr = lenW >> 2;\r
-    W[wordNr] <<= 8;\r
-    W[wordNr] |= (unsigned long)val;\r
-    size += 8;\r
-    lenW++;\r
-    if (lenW >= 64)\r
-        {\r
-        hashblock();\r
-        lenW = 0;\r
-        }\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-std::vector<unsigned char> Sha256Digest::finish()\r
-{\r
-    //save our size before padding\r
-    unsigned long long sizeOut = size;\r
-    \r
-    // Pad with a binary 1 (0x80)\r
-    update((unsigned char)0x80);\r
-    //append 0's to make a 56-byte buf.\r
-       //use mod, so that we will loop around once if already over 56\r
-    while (lenW != 56)\r
-        update((unsigned char)0x00);\r
-    //append 64-bit size\r
-    for (int shift = 56 ; shift>=0 ; shift-= 8)\r
-        {\r
-        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);\r
-        update(ch);\r
-        }\r
-\r
-    // Output hash\r
-    std::vector<unsigned char> ret;\r
-    for (int wordNr = 0 ; wordNr < 8 ; wordNr++)\r
-        {\r
-        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));\r
-        }\r
-\r
-    // Re-initialize the context (also zeroizes contents)\r
-    reset();\r
-\r
-    return ret;\r
-\r
-}\r
-\r
-\r
-\r
-//########################################################################\r
-//##  SHA384\r
-//########################################################################\r
-\r
-/**\r
- * SHA-384 and SHA-512 share the same operations and constants\r
- */\r
-  \r
-#undef SHA_SIGMA0\r
-#undef SHA_SIGMA1\r
-#undef SHA_sigma0\r
-#undef SHA_sigma1\r
-\r
-#define        SHA_Rot64(x,s) (((x) >> s) | ((x) << (64 - s)))\r
-#define        SHA_SIGMA0(x)  (SHA_Rot64(x, 28) ^ SHA_Rot64(x, 34) ^ SHA_Rot64(x, 39))\r
-#define        SHA_SIGMA1(x)  (SHA_Rot64(x, 14) ^ SHA_Rot64(x, 18) ^ SHA_Rot64(x, 41))\r
-#define        SHA_sigma0(x)  (SHA_Rot64(x,  1) ^ SHA_Rot64(x,  8) ^ ((x) >> 7))\r
-#define        SHA_sigma1(x)  (SHA_Rot64(x, 19) ^ SHA_Rot64(x, 61) ^ ((x) >> 6))\r
-\r
-\r
-static unsigned long long sha512constants[80] =\r
-{\r
-0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,\r
-0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,\r
-0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,\r
-0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,\r
-0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,\r
-0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,\r
-0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,\r
-0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,\r
-0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,\r
-0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,\r
-0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,\r
-0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,\r
-0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,\r
-0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,\r
-0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,\r
-0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,\r
-0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,\r
-0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,\r
-0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,\r
-0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,\r
-0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,\r
-0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,\r
-0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,\r
-0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,\r
-0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,\r
-0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,\r
-0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,\r
-0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,\r
-0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,\r
-0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,\r
-0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,\r
-0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,\r
-0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,\r
-0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,\r
-0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,\r
-0x113f9804bef90daeULL, 0x1b710b35131c471bULL,\r
-0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,\r
-0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,\r
-0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,\r
-0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL\r
-};\r
-\r
-\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha384Digest::reset()\r
-{\r
-    lenW   = 0;\r
-    size   = 0;\r
-\r
-    // SHA-384 differs from SHA-512 by these constants\r
-    H[0] = 0xcbbb9d5dc1059ed8ULL;\r
-    H[1] = 0x629a292a367cd507ULL;\r
-    H[2] = 0x9159015a3070dd17ULL;\r
-    H[3] = 0x152fecd8f70e5939ULL;\r
-    H[4] = 0x67332667ffc00b31ULL;\r
-    H[5] = 0x8eb44a8768581511ULL;\r
-    H[6] = 0xdb0c2e0d64f98fa7ULL;\r
-    H[7] = 0x47b5481dbefa4fa4ULL;\r
-\r
-    for (int i = 0 ; i < 80 ; i++)\r
-        W[i] = 0;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-void Sha384Digest::hashblock()\r
-{\r
-    /*\r
-       for (int t = 0; t < 16 ; t++)\r
-        {\r
-        printf("%2d ", t);\r
-        pl(W[t]);\r
-        printf("\n");\r
-        }\r
-    */\r
-\r
-    //see 6.2.2\r
-    for (int t = 16; t < 80 ; t++)\r
-        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];\r
-\r
-    unsigned long long a = H[0];\r
-    unsigned long long b = H[1];\r
-    unsigned long long c = H[2];\r
-    unsigned long long d = H[3];\r
-    unsigned long long e = H[4];\r
-    unsigned long long f = H[5];\r
-    unsigned long long g = H[6];\r
-    unsigned long long h = H[7];\r
-\r
-    for (int t = 0 ; t < 80 ; t++)\r
-        {\r
-        //see 4.1.1 for the boolops\r
-        unsigned long long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +\r
-            sha512constants[t] + W[t];\r
-        unsigned long long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);\r
-        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;\r
-        }\r
-\r
-    H[0] += a;\r
-    H[1] += b;\r
-    H[2] += c;\r
-    H[3] += d;\r
-    H[4] += e;\r
-    H[5] += f;\r
-    H[6] += g;\r
-    H[7] += h;\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha384Digest::update(unsigned char val)\r
-{\r
-    int wordNr = lenW >> 3;\r
-    W[wordNr] <<= 8;\r
-    W[wordNr] |= (unsigned long)val;\r
-    size += 8;\r
-    lenW++;\r
-    if (lenW >= 128)\r
-        {\r
-        hashblock();\r
-        lenW = 0;\r
-        }\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-std::vector<unsigned char> Sha384Digest::finish()\r
-{\r
-    //save our size before padding\r
-    unsigned long long sizeOut = size;\r
-    \r
-    // Pad with a binary 1 (0x80)\r
-    update((unsigned char)0x80);\r
-    //append 0's to make a 112-byte buf.\r
-       //we will loop around once if already over 112\r
-    while (lenW != 112)\r
-        update((unsigned char)0x00);\r
-        \r
-    //append 128-bit size\r
-    for (int i = 0 ; i < 8 ; i++) //64 upper bits\r
-        update((unsigned char)0x00);\r
-    for (int shift = 56 ; shift>=0 ; shift-= 8) //64 lower length bits\r
-        {\r
-        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);\r
-        update(ch);\r
-        }\r
-\r
-    // Output hash\r
-    //for SHA-384, we use the left-most 6 64-bit words\r
-    std::vector<unsigned char> ret;\r
-    for (int wordNr = 0 ; wordNr < 6 ; wordNr++)\r
-        {\r
-        ret.push_back((unsigned char)((H[wordNr] >> 56) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 48) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 40) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 32) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));\r
-        }\r
-\r
-    // Re-initialize the context (also zeroizes contents)\r
-    reset();\r
-\r
-    return ret;\r
-\r
-}\r
-\r
-\r
-//########################################################################\r
-//##  SHA512\r
-//########################################################################\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha512Digest::reset()\r
-{\r
-    lenW   = 0;\r
-    size   = 0;\r
-\r
-    // Initialize H with the magic constants (see FIPS180 for constants)\r
-    H[0] = 0x6a09e667f3bcc908ULL;\r
-    H[1] = 0xbb67ae8584caa73bULL;\r
-    H[2] = 0x3c6ef372fe94f82bULL;\r
-    H[3] = 0xa54ff53a5f1d36f1ULL;\r
-    H[4] = 0x510e527fade682d1ULL;\r
-    H[5] = 0x9b05688c2b3e6c1fULL;\r
-    H[6] = 0x1f83d9abfb41bd6bULL;\r
-    H[7] = 0x5be0cd19137e2179ULL;\r
-\r
-    for (int i = 0 ; i < 80 ; i++)\r
-        W[i] = 0;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-void Sha512Digest::hashblock()\r
-{\r
-    /*\r
-       for (int t = 0; t < 16 ; t++)\r
-        {\r
-        printf("%2d ", t);\r
-        pl(W[t]);\r
-        printf("\n");\r
-        }\r
-    */\r
-\r
-    //see 6.2.2\r
-    for (int t = 16; t < 80 ; t++)\r
-        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];\r
-\r
-    unsigned long long a = H[0];\r
-    unsigned long long b = H[1];\r
-    unsigned long long c = H[2];\r
-    unsigned long long d = H[3];\r
-    unsigned long long e = H[4];\r
-    unsigned long long f = H[5];\r
-    unsigned long long g = H[6];\r
-    unsigned long long h = H[7];\r
-\r
-    for (int t = 0 ; t < 80 ; t++)\r
-        {\r
-        //see 4.1.1 for the boolops\r
-        unsigned long long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +\r
-            sha512constants[t] + W[t];\r
-        unsigned long long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);\r
-        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;\r
-        }\r
-\r
-    H[0] += a;\r
-    H[1] += b;\r
-    H[2] += c;\r
-    H[3] += d;\r
-    H[4] += e;\r
-    H[5] += f;\r
-    H[6] += g;\r
-    H[7] += h;\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Sha512Digest::update(unsigned char val)\r
-{\r
-    int wordNr = lenW >> 3;\r
-    W[wordNr] <<= 8;\r
-    W[wordNr] |= (unsigned long)val;\r
-    size += 8;\r
-    lenW++;\r
-    if (lenW >= 128)\r
-        {\r
-        hashblock();\r
-        lenW = 0;\r
-        }\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-std::vector<unsigned char> Sha512Digest::finish()\r
-{\r
-    //save our size before padding\r
-    unsigned long long sizeOut = size;\r
-    \r
-    // Pad with a binary 1 (0x80)\r
-    update((unsigned char)0x80);\r
-    //append 0's to make a 112-byte buf.\r
-       //we will loop around once if already over 112\r
-    while (lenW != 112)\r
-        update((unsigned char)0x00);\r
-        \r
-    //append 128-bit size\r
-    for (int i = 0 ; i < 8 ; i++) //64 upper bits\r
-        update((unsigned char)0x00);\r
-    for (int shift = 56 ; shift>=0 ; shift-= 8) //64 lower length bits\r
-        {\r
-        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);\r
-        update(ch);\r
-        }\r
-\r
-    // Output hash\r
-    std::vector<unsigned char> ret;\r
-    for (int wordNr = 0 ; wordNr < 8 ; wordNr++)\r
-        {\r
-        ret.push_back((unsigned char)((H[wordNr] >> 56) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 48) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 40) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 32) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));\r
-        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));\r
-        }\r
-\r
-    // Re-initialize the context (also zeroizes contents)\r
-    reset();\r
-\r
-    return ret;\r
-\r
-}\r
-\r
-\r
-\r
-//########################################################################\r
-//##  M D 5\r
-//########################################################################\r
-\r
-static int md5r[64] =\r
-{\r
-   7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22, \r
-   5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,\r
-   4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,\r
-   6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21\r
-};\r
-\r
-static unsigned long md5k[64] =\r
-{\r
-0xd76aa478L, 0xe8c7b756L, 0x242070dbL, 0xc1bdceeeL, \r
-0xf57c0fafL, 0x4787c62aL, 0xa8304613L, 0xfd469501L, \r
-0x698098d8L, 0x8b44f7afL, 0xffff5bb1L, 0x895cd7beL, \r
-0x6b901122L, 0xfd987193L, 0xa679438eL, 0x49b40821L, \r
-0xf61e2562L, 0xc040b340L, 0x265e5a51L, 0xe9b6c7aaL, \r
-0xd62f105dL, 0x02441453L, 0xd8a1e681L, 0xe7d3fbc8L, \r
-0x21e1cde6L, 0xc33707d6L, 0xf4d50d87L, 0x455a14edL, \r
-0xa9e3e905L, 0xfcefa3f8L, 0x676f02d9L, 0x8d2a4c8aL, \r
-0xfffa3942L, 0x8771f681L, 0x6d9d6122L, 0xfde5380cL, \r
-0xa4beea44L, 0x4bdecfa9L, 0xf6bb4b60L, 0xbebfbc70L, \r
-0x289b7ec6L, 0xeaa127faL, 0xd4ef3085L, 0x04881d05L, \r
-0xd9d4d039L, 0xe6db99e5L, 0x1fa27cf8L, 0xc4ac5665L, \r
-0xf4292244L, 0x432aff97L, 0xab9423a7L, 0xfc93a039L, \r
-0x655b59c3L, 0x8f0ccc92L, 0xffeff47dL, 0x85845dd1L, \r
-0x6fa87e4fL, 0xfe2ce6e0L, 0xa3014314L, 0x4e0811a1L, \r
-0xf7537e82L, 0xbd3af235L, 0x2ad7d2bbL, 0xeb86d391L\r
-};\r
-\r
-#define MD5_ROTL(X,n) (((X) << (n)) | ((X) >> (32-(n))))\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Md5Digest::reset()\r
-{\r
-    size  = 0;\r
-    lenW  = 0;\r
-\r
-    hash[0]  = 0x67452301L;\r
-    hash[1]  = 0xefcdab89L;\r
-    hash[2]  = 0x98badcfeL;\r
-    hash[3]  = 0x10325476L;\r
-\r
-    for (int i = 0 ; i < 64 ; i++)\r
-        W[i] = 0;\r
-\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Md5Digest::hashblock()\r
-{\r
-    //for (int t = 0; t < 16 ; t++)\r
-    //    printf("%2d %08lx\n", t, W[t]);\r
-\r
-    unsigned long a = hash[0];\r
-    unsigned long b = hash[1];\r
-    unsigned long c = hash[2];\r
-    unsigned long d = hash[3];\r
-\r
-    int t = 0;\r
-    for ( ; t < 16 ; t++)\r
-        {\r
-        unsigned long f = d ^ ( b & ( c ^ d));\r
-        unsigned int g = t;\r
-        unsigned long temp = d; d = c; c = b;\r
-        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);\r
-        a = temp;\r
-        //printf("%2d %08lx %08lx %08lx %08lx\n", t, a, b, c, d);\r
-        }\r
-    for ( ; t < 32 ; t++)\r
-        {\r
-        unsigned long f = c ^ ( d & ( b ^ c));\r
-        unsigned int g = (5 * t + 1) & 0xf;\r
-        unsigned long temp = d; d = c; c = b;\r
-        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);\r
-        a = temp;\r
-        }\r
-    for ( ; t < 48 ; t++)\r
-        {\r
-        unsigned long f = b ^ c ^ d;\r
-        unsigned int g = (3 * t + 5) & 0xf;\r
-        unsigned long temp = d; d = c; c = b;\r
-        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);\r
-        a = temp;\r
-        }\r
-    for ( ; t < 64 ; t++)\r
-        {\r
-        unsigned long f = c ^ (b | ~d);\r
-        unsigned int g = (7 * t) & 0xf;\r
-        unsigned long temp = d; d = c; c = b;\r
-        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);\r
-        a = temp;\r
-        }\r
-\r
-    hash[0] += a;\r
-    hash[1] += b;\r
-    hash[2] += c;\r
-    hash[3] += d;\r
-}\r
-\r
-\r
-/**\r
- *\r
- */\r
-void Md5Digest::update(unsigned char val)\r
-{\r
-    int wordNr = lenW >> 2;\r
-    /*\r
-       W[wordNr] <<= 8;\r
-    W[wordNr] |= (unsigned long)val;\r
-    */\r
-    W[wordNr] = ( (W[wordNr] >> 8) & 0x00ffffff ) |\r
-                ( ((unsigned long)val) << 24    );\r
-    size += 8;\r
-    lenW++;\r
-    if (lenW >= 64)\r
-        {\r
-        hashblock();\r
-        lenW = 0;\r
-        }\r
-}\r
-\r
-\r
-\r
-\r
-/**\r
- *\r
- */\r
-std::vector<unsigned char> Md5Digest::finish()\r
-{\r
-    //save our size before padding\r
-    unsigned long long sizeOut = size;\r
-    \r
-    // Pad with a binary 1 (0x80)\r
-    update((unsigned char)0x80);\r
-    //append 0's to make a 56-byte buf.\r
-       //use mod, so that we will loop around once if already over 56\r
-    while (lenW != 56)\r
-        update((unsigned char)0x00);\r
-\r
-\r
-    //Append the length.  Lower 32 bits first\r
-    update( (unsigned char) ((sizeOut    ) & 0xff));\r
-    update( (unsigned char) ((sizeOut>> 8) & 0xff));\r
-    update( (unsigned char) ((sizeOut>>16) & 0xff));\r
-    update( (unsigned char) ((sizeOut>>24) & 0xff));\r
-    update( (unsigned char) ((sizeOut>>32) & 0xff));\r
-    update( (unsigned char) ((sizeOut>>40) & 0xff));\r
-    update( (unsigned char) ((sizeOut>>48) & 0xff));\r
-    update( (unsigned char) ((sizeOut>>56) & 0xff));\r
-\r
-    //Output hash\r
-    std::vector<unsigned char> ret;\r
-    for (int wordNr = 0 ; wordNr<4 ; wordNr++)\r
-        {\r
-        unsigned long w = hash[wordNr];\r
-        ret.push_back( (unsigned char) ((w      ) & 0xff) );\r
-        ret.push_back( (unsigned char) ((w >>  8) & 0xff) );\r
-        ret.push_back( (unsigned char) ((w >> 16) & 0xff) );\r
-        ret.push_back( (unsigned char) ((w >> 24) & 0xff) );\r
-        }\r
-\r
-    // Re-initialize the context (also zeroizes contents)\r
-    reset();\r
-\r
-    return ret;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-//########################################################################\r
-//## T E S T S\r
-//########################################################################\r
-\r
-/**\r
- * Compile this file alone with -DDIGEST_TEST to run the\r
- * tests below:\r
- * > gcc -DDIGEST_TEST digest.cpp -o digest\r
- * > digest   \r
- */\r
\r
- #ifdef DIGEST_TEST\r
-\r
-\r
-typedef struct\r
-{\r
-    char *msg;\r
-    char *val;\r
-} TestPair;\r
-\r
-static TestPair md5tests[] =\r
-{\r
-  {\r
-  "",\r
-  "d41d8cd98f00b204e9800998ecf8427e"\r
-  },\r
-  {\r
-  "a",\r
-  "0cc175b9c0f1b6a831c399e269772661"\r
-  },\r
-  {\r
-  "abc",\r
-  "900150983cd24fb0d6963f7d28e17f72"\r
-  },\r
-  {\r
-  "message digest",\r
-  "f96b697d7cb7938d525a2f31aaf161d0"\r
-  },\r
-  {\r
-  "abcdefghijklmnopqrstuvwxyz",\r
-  "c3fcd3d76192e4007dfb496cca67e13b"\r
-  },\r
-  {\r
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",\r
-  "d174ab98d277d9f5a5611c2c9f419d9f"\r
-  },\r
-  {\r
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890",\r
-  "57edf4a22be3c955ac49da2e2107b67a"\r
-  },\r
-  {\r
-  NULL,\r
-  NULL\r
-  }\r
-};\r
-\r
-\r
-\r
-static TestPair sha1tests[] =\r
-{\r
-  {\r
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",\r
-  "84983e441c3bd26ebaae4aa1f95129e5e54670f1"\r
-  },\r
-  {\r
-  NULL,\r
-  NULL\r
-  }\r
-};\r
-\r
-static TestPair sha224tests[] =\r
-{\r
-  {\r
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",\r
-  "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"\r
-  },\r
-  {\r
-  NULL,\r
-  NULL\r
-  }\r
-};\r
-\r
-static TestPair sha256tests[] =\r
-{\r
-  {\r
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",\r
-  "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"\r
-  },\r
-  {\r
-  NULL,\r
-  NULL\r
-  }\r
-};\r
-\r
-static TestPair sha384tests[] =\r
-{\r
-  {\r
-  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"\r
-       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",\r
-  "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"\r
-       "fcc7c71a557e2db966c3e9fa91746039"\r
-  },\r
-  {\r
-  NULL,\r
-  NULL\r
-  }\r
-};\r
-\r
-static TestPair sha512tests[] =\r
-{\r
-  {\r
-  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"\r
-       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",\r
-  "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"\r
-       "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"\r
-  },\r
-  {\r
-  NULL,\r
-  NULL\r
-  }\r
-};\r
-\r
-\r
-bool hashTests(Digest &digest, TestPair *tp)\r
-{\r
-    for (TestPair *pair = tp ; pair->msg ; pair++)\r
-        {\r
-        digest.reset();\r
-        std::string msg = pair->msg;\r
-        std::string val = pair->val;\r
-        digest.append(msg);\r
-        std::string res = digest.finishHex();\r
-        printf("### Msg '%s':\n   hash '%s'\n   exp  '%s'\n",\r
-            msg.c_str(), res.c_str(), val.c_str());\r
-        if (res != val)\r
-            {\r
-            printf("ERROR: Hash mismatch\n");\r
-            return false;\r
-            }\r
-        }\r
-    return true;\r
-}\r
-\r
-\r
-bool millionATest(Digest &digest, const std::string &exp)\r
-{\r
-    digest.reset();\r
-       for (int i=0 ; i<1000000 ; i++)\r
-        digest.append('a');\r
-    std::string res = digest.finishHex();\r
-    printf("\nHash of 1,000,000 'a'\n   calc %s\n   exp  %s\n",\r
-            res.c_str(), exp.c_str());\r
-    if (res != exp)\r
-        {\r
-        printf("ERROR: Mismatch.\n");\r
-        return false;\r
-        }\r
-    return true;\r
-}\r
-\r
-static bool doTests()\r
-{\r
-    printf("##########################################\n");\r
-    printf("## MD5\n");\r
-    printf("##########################################\n");\r
-    Md5Digest md5;\r
-    if (!hashTests(md5, md5tests))\r
-        return false;\r
-    if (!millionATest(md5, "7707d6ae4e027c70eea2a935c2296f21"))\r
-        return false;\r
-    printf("\n\n\n");\r
-    printf("##########################################\n");\r
-    printf("## SHA1\n");\r
-    printf("##########################################\n");\r
-    Sha1Digest sha1;\r
-    if (!hashTests(sha1, sha1tests))\r
-        return false;\r
-    if (!millionATest(sha1, "34aa973cd4c4daa4f61eeb2bdbad27316534016f"))\r
-        return false;\r
-    printf("\n\n\n");\r
-    printf("##########################################\n");\r
-    printf("## SHA224\n");\r
-    printf("##########################################\n");\r
-    Sha224Digest sha224;\r
-    if (!hashTests(sha224, sha224tests))\r
-        return false;\r
-    if (!millionATest(sha224,\r
-            "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"))\r
-        return false;\r
-    printf("\n\n\n");\r
-    printf("##########################################\n");\r
-    printf("## SHA256\n");\r
-    printf("##########################################\n");\r
-    Sha256Digest sha256;\r
-    if (!hashTests(sha256, sha256tests))\r
-        return false;\r
-    if (!millionATest(sha256,\r
-            "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"))\r
-        return false;\r
-    printf("\n\n\n");\r
-    printf("##########################################\n");\r
-    printf("## SHA384\n");\r
-    printf("##########################################\n");\r
-    Sha384Digest sha384;\r
-    if (!hashTests(sha384, sha384tests))\r
-        return false;\r
-    /**/\r
-       if (!millionATest(sha384,\r
-                "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"\r
-                "07b8b3dc38ecc4ebae97ddd87f3d8985"))\r
-        return false;\r
-    /**/\r
-    printf("\n\n\n");\r
-    printf("##########################################\n");\r
-    printf("## SHA512\n");\r
-    printf("##########################################\n");\r
-    Sha512Digest sha512;\r
-    if (!hashTests(sha512, sha512tests))\r
-        return false;\r
-    if (!millionATest(sha512,\r
-                "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"\r
-             "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"))\r
-        return false;\r
-    return true;\r
-}\r
-\r
-\r
-int main(int argc, char **argv)\r
-{\r
-    doTests();\r
-    printf("####### done ########\n");\r
-    return 0;\r
-}\r
-\r
-\r
-#endif /* DIGEST_TEST */\r
-\r
-//########################################################################\r
-//## E N D    O F    F I L E\r
-//########################################################################\r
+/**
+ * Secure Hashing Tool
+ * *
+ * Authors:
+ *   Bob Jamison
+ *
+ * Copyright (C) 2006 Bob Jamison
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "digest.h"
+
+
+//########################################################################
+//##  U T I L
+//########################################################################
+
+/**
+ * Use this to print out a 64-bit int when otherwise difficult
+ */
+/*
+static void pl(unsigned long long val)
+{
+    for (int shift=56 ; shift>=0 ; shift-=8)
+        {
+        int ch = (val >> shift) & 0xff;
+        printf("%02x", ch);
+        }
+}
+*/
+
+
+static char *hexDigits = "0123456789abcdef";
+
+static std::string toHex(const std::vector<unsigned char> &bytes)
+{
+    std::string str;
+    std::vector<unsigned char>::const_iterator iter;
+    for (iter = bytes.begin() ; iter != bytes.end() ; iter++)
+       {
+       unsigned char ch = *iter;
+       str.push_back(hexDigits[(ch>>4) & 0x0f]);
+       str.push_back(hexDigits[(ch   ) & 0x0f]);
+       }
+    return str;
+}
+
+
+//########################################################################
+//##  D I G E S T
+//########################################################################
+
+
+/**
+ *
+ */
+std::string Digest::finishHex()
+{
+    std::vector<unsigned char> hash = finish();
+    std::string str = toHex(hash);
+    return str;
+}
+
+
+//4.1.1 and 4.1.2
+#define SHA_ROTL(X,n)  ( ((X) << (n)) | ( ((X) & 0xffffffffL) >> (32-(n))) )
+#define        SHA_Ch(x,y,z)  ((z)^((x)&((y)^(z))))
+#define        SHA_Maj(x,y,z) (((x)&(y))^((z)&((x)^(y))))
+
+
+//########################################################################
+//##  S H A 1
+//########################################################################
+
+
+/**
+ *
+ */
+void Sha1Digest::reset()
+{
+    lenW   = 0;
+    size   = 0;
+
+    // Initialize H with the magic constants (see FIPS180 for constants)
+    H[0] = 0x67452301L;
+    H[1] = 0xefcdab89L;
+    H[2] = 0x98badcfeL;
+    H[3] = 0x10325476L;
+    H[4] = 0xc3d2e1f0L;
+
+    for (int i = 0 ; i < 80 ; i++)
+        W[i] = 0;
+}
+
+
+
+
+void Sha1Digest::hashblock()
+{
+    //for (int t = 0; t < 16 ; t++)
+    //    printf("%2d %08lx\n", t, W[t]);
+
+    //see 6.1.2
+    for (int t = 16; t < 80 ; t++)
+        W[t] = SHA_ROTL((W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]), 1);
+
+    unsigned long a = H[0];
+    unsigned long b = H[1];
+    unsigned long c = H[2];
+    unsigned long d = H[3];
+    unsigned long e = H[4];
+
+    unsigned long T;
+
+    int t = 0;
+    for ( ; t < 20 ; t++)
+        {
+        //see 4.1.1 for the boolops on B,C, and D
+        T = (SHA_ROTL(a,5) + ((b&c)^(~b&d)) +  //Ch(b,c,d))
+                e + 0x5a827999L + W[t]) & 0xffffffffL;
+        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;
+        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);
+        }
+    for ( ; t < 40 ; t++)
+        {
+        T = (SHA_ROTL(a,5) + (b^c^d) +
+                e + 0x6ed9eba1L + W[t]) & 0xffffffffL;
+        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;
+        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);
+        }
+    for ( ; t < 60 ; t++)
+        {
+        T = (SHA_ROTL(a,5) + ((b&c)^(b&d)^(c&d)) +
+                e + 0x8f1bbcdcL + W[t]) & 0xffffffffL;
+        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;
+        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);
+        }
+    for ( ; t < 80 ; t++)
+        {
+        T = (SHA_ROTL(a,5) + (b^c^d) +
+                e + 0xca62c1d6L + W[t]) & 0xffffffffL;
+        e = d; d = c; c = SHA_ROTL(b, 30); b = a; a = T;
+        //printf("%2d %08lx %08lx %08lx %08lx %08lx\n", t, a, b, c, d, e);
+        }
+
+    H[0] += a;
+    H[1] += b;
+    H[2] += c;
+    H[3] += d;
+    H[4] += e;
+}
+
+
+/**
+ *
+ */
+void Sha1Digest::update(unsigned char val)
+{
+    int wordNr = lenW >> 2;
+    W[wordNr] <<= 8;
+    W[wordNr] |= (unsigned long)val;
+    size += 8;
+    lenW++;
+    if (lenW >= 64)
+        {
+        hashblock();
+        lenW = 0;
+        }
+}
+
+
+/**
+ *
+ */
+std::vector<unsigned char> Sha1Digest::finish()
+{
+    //save our size before padding
+    unsigned long long sizeOut = size;
+    
+    // Pad with a binary 1 (0x80)
+    update((unsigned char)0x80);
+    //append 0's to make a 56-byte buf.
+       //use mod, so that we will loop around once if already over 56
+    while (lenW != 56)
+        update((unsigned char)0x00);
+    //append 64-bit size
+    for (int shift = 56 ; shift>=0 ; shift-= 8)
+        {
+        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);
+        update(ch);
+        }
+
+    // Output hash
+    std::vector<unsigned char> ret;
+    for (int wordNr = 0 ; wordNr < 5 ; wordNr++)
+        {
+        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));
+        }
+
+    // Re-initialize the context (also zeroizes contents)
+    reset();
+
+    return ret;
+
+}
+
+
+//########################################################################
+//##  SHA224
+//########################################################################
+
+
+/**
+ * SHA-224 and SHA-512 share the same operations and constants
+ */ 
+
+#define        SHA_Rot32(x,s) (((x) >> s) | ((x) << (32 - s)))
+#define        SHA_SIGMA0(x)  (SHA_Rot32(x,  2) ^ SHA_Rot32(x, 13) ^ SHA_Rot32(x, 22))
+#define        SHA_SIGMA1(x)  (SHA_Rot32(x,  6) ^ SHA_Rot32(x, 11) ^ SHA_Rot32(x, 25))
+#define        SHA_sigma0(x)  (SHA_Rot32(x,  7) ^ SHA_Rot32(x, 18) ^ ((x) >> 3))
+#define        SHA_sigma1(x)  (SHA_Rot32(x, 17) ^ SHA_Rot32(x, 19) ^ ((x) >> 10))
+
+
+static unsigned long sha256constants[64] =
+{
+0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+
+
+
+
+/**
+ *
+ */
+void Sha224Digest::reset()
+{
+    lenW   = 0;
+    size   = 0;
+
+    // Initialize H with the magic constants (see FIPS180 for constants)
+    H[0] = 0xc1059ed8L;
+    H[1] = 0x367cd507L;
+    H[2] = 0x3070dd17L;
+    H[3] = 0xf70e5939L;
+    H[4] = 0xffc00b31L;
+    H[5] = 0x68581511L;
+    H[6] = 0x64f98fa7L;
+    H[7] = 0xbefa4fa4L;
+
+    for (int i = 0 ; i < 64 ; i++)
+        W[i] = 0;
+}
+
+
+
+
+
+void Sha224Digest::hashblock()
+{
+    //for (int t = 0; t < 16 ; t++)
+    //    printf("%2d %08lx\n", t, W[t]);
+
+    //see 6.2.2
+    for (int t = 16; t < 64 ; t++)
+        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];
+
+    unsigned long a = H[0];
+    unsigned long b = H[1];
+    unsigned long c = H[2];
+    unsigned long d = H[3];
+    unsigned long e = H[4];
+    unsigned long f = H[5];
+    unsigned long g = H[6];
+    unsigned long h = H[7];
+
+    for (int t = 0 ; t < 64 ; t++)
+        {
+        //see 4.1.1 for the boolops
+        unsigned long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +
+            sha256constants[t] + W[t];
+        unsigned long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);
+        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;
+        //printf("%2d %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+               //         t, a, b, c, d, e, f, g, h);
+        }
+
+    H[0] += a;
+    H[1] += b;
+    H[2] += c;
+    H[3] += d;
+    H[4] += e;
+    H[5] += f;
+    H[6] += g;
+    H[7] += h;
+}
+
+
+/**
+ *
+ */
+void Sha224Digest::update(unsigned char val)
+{
+    int wordNr = lenW >> 2;
+    W[wordNr] <<= 8;
+    W[wordNr] |= (unsigned long)val;
+    size += 8;
+    lenW++;
+    if (lenW >= 64)
+        {
+        hashblock();
+        lenW = 0;
+        }
+}
+
+
+/**
+ *
+ */
+std::vector<unsigned char> Sha224Digest::finish()
+{
+    //save our size before padding
+    unsigned long long sizeOut = size;
+    
+    // Pad with a binary 1 (0x80)
+    update((unsigned char)0x80);
+    //append 0's to make a 56-byte buf.
+       //use mod, so that we will loop around once if already over 56
+    while (lenW != 56)
+        update((unsigned char)0x00);
+    //append 64-bit size
+    for (int shift = 56 ; shift>=0 ; shift-= 8)
+        {
+        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);
+        update(ch);
+        }
+
+    // Output hash
+    std::vector<unsigned char> ret;
+    for (int wordNr = 0 ; wordNr < 7 ; wordNr++)
+        {
+        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));
+        }
+
+    // Re-initialize the context (also zeroizes contents)
+    reset();
+
+    return ret;
+
+}
+
+//########################################################################
+//##  SHA256
+//########################################################################
+
+
+
+
+
+/**
+ *
+ */
+void Sha256Digest::reset()
+{
+    lenW   = 0;
+    size   = 0;
+
+    // Initialize H with the magic constants (see FIPS180 for constants)
+    H[0] = 0x6a09e667L;
+    H[1] = 0xbb67ae85L;
+    H[2] = 0x3c6ef372L;
+    H[3] = 0xa54ff53aL;
+    H[4] = 0x510e527fL;
+    H[5] = 0x9b05688cL;
+    H[6] = 0x1f83d9abL;
+    H[7] = 0x5be0cd19L;
+
+    for (int i = 0 ; i < 64 ; i++)
+        W[i] = 0;
+}
+
+
+
+
+
+void Sha256Digest::hashblock()
+{
+    //for (int t = 0; t < 16 ; t++)
+    //    printf("%2d %08lx\n", t, W[t]);
+
+    //see 6.2.2
+    for (int t = 16; t < 64 ; t++)
+        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];
+
+    unsigned long a = H[0];
+    unsigned long b = H[1];
+    unsigned long c = H[2];
+    unsigned long d = H[3];
+    unsigned long e = H[4];
+    unsigned long f = H[5];
+    unsigned long g = H[6];
+    unsigned long h = H[7];
+
+    for (int t = 0 ; t < 64 ; t++)
+        {
+        //see 4.1.1 for the boolops
+        unsigned long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +
+            sha256constants[t] + W[t];
+        unsigned long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);
+        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;
+        //printf("%2d %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+               //         t, a, b, c, d, e, f, g, h);
+        }
+
+    H[0] += a;
+    H[1] += b;
+    H[2] += c;
+    H[3] += d;
+    H[4] += e;
+    H[5] += f;
+    H[6] += g;
+    H[7] += h;
+}
+
+
+/**
+ *
+ */
+void Sha256Digest::update(unsigned char val)
+{
+    int wordNr = lenW >> 2;
+    W[wordNr] <<= 8;
+    W[wordNr] |= (unsigned long)val;
+    size += 8;
+    lenW++;
+    if (lenW >= 64)
+        {
+        hashblock();
+        lenW = 0;
+        }
+}
+
+
+/**
+ *
+ */
+std::vector<unsigned char> Sha256Digest::finish()
+{
+    //save our size before padding
+    unsigned long long sizeOut = size;
+    
+    // Pad with a binary 1 (0x80)
+    update((unsigned char)0x80);
+    //append 0's to make a 56-byte buf.
+       //use mod, so that we will loop around once if already over 56
+    while (lenW != 56)
+        update((unsigned char)0x00);
+    //append 64-bit size
+    for (int shift = 56 ; shift>=0 ; shift-= 8)
+        {
+        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);
+        update(ch);
+        }
+
+    // Output hash
+    std::vector<unsigned char> ret;
+    for (int wordNr = 0 ; wordNr < 8 ; wordNr++)
+        {
+        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));
+        }
+
+    // Re-initialize the context (also zeroizes contents)
+    reset();
+
+    return ret;
+
+}
+
+
+
+//########################################################################
+//##  SHA384
+//########################################################################
+
+/**
+ * SHA-384 and SHA-512 share the same operations and constants
+ */
+  
+#undef SHA_SIGMA0
+#undef SHA_SIGMA1
+#undef SHA_sigma0
+#undef SHA_sigma1
+
+#define        SHA_Rot64(x,s) (((x) >> s) | ((x) << (64 - s)))
+#define        SHA_SIGMA0(x)  (SHA_Rot64(x, 28) ^ SHA_Rot64(x, 34) ^ SHA_Rot64(x, 39))
+#define        SHA_SIGMA1(x)  (SHA_Rot64(x, 14) ^ SHA_Rot64(x, 18) ^ SHA_Rot64(x, 41))
+#define        SHA_sigma0(x)  (SHA_Rot64(x,  1) ^ SHA_Rot64(x,  8) ^ ((x) >> 7))
+#define        SHA_sigma1(x)  (SHA_Rot64(x, 19) ^ SHA_Rot64(x, 61) ^ ((x) >> 6))
+
+
+static unsigned long long sha512constants[80] =
+{
+0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+
+
+
+/**
+ *
+ */
+void Sha384Digest::reset()
+{
+    lenW   = 0;
+    size   = 0;
+
+    // SHA-384 differs from SHA-512 by these constants
+    H[0] = 0xcbbb9d5dc1059ed8ULL;
+    H[1] = 0x629a292a367cd507ULL;
+    H[2] = 0x9159015a3070dd17ULL;
+    H[3] = 0x152fecd8f70e5939ULL;
+    H[4] = 0x67332667ffc00b31ULL;
+    H[5] = 0x8eb44a8768581511ULL;
+    H[6] = 0xdb0c2e0d64f98fa7ULL;
+    H[7] = 0x47b5481dbefa4fa4ULL;
+
+    for (int i = 0 ; i < 80 ; i++)
+        W[i] = 0;
+}
+
+
+
+
+
+void Sha384Digest::hashblock()
+{
+    /*
+       for (int t = 0; t < 16 ; t++)
+        {
+        printf("%2d ", t);
+        pl(W[t]);
+        printf("\n");
+        }
+    */
+
+    //see 6.2.2
+    for (int t = 16; t < 80 ; t++)
+        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];
+
+    unsigned long long a = H[0];
+    unsigned long long b = H[1];
+    unsigned long long c = H[2];
+    unsigned long long d = H[3];
+    unsigned long long e = H[4];
+    unsigned long long f = H[5];
+    unsigned long long g = H[6];
+    unsigned long long h = H[7];
+
+    for (int t = 0 ; t < 80 ; t++)
+        {
+        //see 4.1.1 for the boolops
+        unsigned long long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +
+            sha512constants[t] + W[t];
+        unsigned long long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);
+        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;
+        }
+
+    H[0] += a;
+    H[1] += b;
+    H[2] += c;
+    H[3] += d;
+    H[4] += e;
+    H[5] += f;
+    H[6] += g;
+    H[7] += h;
+}
+
+
+/**
+ *
+ */
+void Sha384Digest::update(unsigned char val)
+{
+    int wordNr = lenW >> 3;
+    W[wordNr] <<= 8;
+    W[wordNr] |= (unsigned long)val;
+    size += 8;
+    lenW++;
+    if (lenW >= 128)
+        {
+        hashblock();
+        lenW = 0;
+        }
+}
+
+
+/**
+ *
+ */
+std::vector<unsigned char> Sha384Digest::finish()
+{
+    //save our size before padding
+    unsigned long long sizeOut = size;
+    
+    // Pad with a binary 1 (0x80)
+    update((unsigned char)0x80);
+    //append 0's to make a 112-byte buf.
+       //we will loop around once if already over 112
+    while (lenW != 112)
+        update((unsigned char)0x00);
+        
+    //append 128-bit size
+    for (int i = 0 ; i < 8 ; i++) //64 upper bits
+        update((unsigned char)0x00);
+    for (int shift = 56 ; shift>=0 ; shift-= 8) //64 lower length bits
+        {
+        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);
+        update(ch);
+        }
+
+    // Output hash
+    //for SHA-384, we use the left-most 6 64-bit words
+    std::vector<unsigned char> ret;
+    for (int wordNr = 0 ; wordNr < 6 ; wordNr++)
+        {
+        ret.push_back((unsigned char)((H[wordNr] >> 56) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 48) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 40) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 32) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));
+        }
+
+    // Re-initialize the context (also zeroizes contents)
+    reset();
+
+    return ret;
+
+}
+
+
+//########################################################################
+//##  SHA512
+//########################################################################
+
+
+
+
+
+/**
+ *
+ */
+void Sha512Digest::reset()
+{
+    lenW   = 0;
+    size   = 0;
+
+    // Initialize H with the magic constants (see FIPS180 for constants)
+    H[0] = 0x6a09e667f3bcc908ULL;
+    H[1] = 0xbb67ae8584caa73bULL;
+    H[2] = 0x3c6ef372fe94f82bULL;
+    H[3] = 0xa54ff53a5f1d36f1ULL;
+    H[4] = 0x510e527fade682d1ULL;
+    H[5] = 0x9b05688c2b3e6c1fULL;
+    H[6] = 0x1f83d9abfb41bd6bULL;
+    H[7] = 0x5be0cd19137e2179ULL;
+
+    for (int i = 0 ; i < 80 ; i++)
+        W[i] = 0;
+}
+
+
+
+
+
+void Sha512Digest::hashblock()
+{
+    /*
+       for (int t = 0; t < 16 ; t++)
+        {
+        printf("%2d ", t);
+        pl(W[t]);
+        printf("\n");
+        }
+    */
+
+    //see 6.2.2
+    for (int t = 16; t < 80 ; t++)
+        W[t] = SHA_sigma1(W[t-2]) + W[t-7] + SHA_sigma0(W[t-15]) + W[t-16];
+
+    unsigned long long a = H[0];
+    unsigned long long b = H[1];
+    unsigned long long c = H[2];
+    unsigned long long d = H[3];
+    unsigned long long e = H[4];
+    unsigned long long f = H[5];
+    unsigned long long g = H[6];
+    unsigned long long h = H[7];
+
+    for (int t = 0 ; t < 80 ; t++)
+        {
+        //see 4.1.1 for the boolops
+        unsigned long long T1 = h + SHA_SIGMA1(e) + SHA_Ch(e,f,g) +
+            sha512constants[t] + W[t];
+        unsigned long long T2 = SHA_SIGMA0(a) + SHA_Maj(a,b,c);
+        h = g; g = f; f = e; e = d  + T1 ; d = c; c = b; b = a; a = T1 + T2;
+        }
+
+    H[0] += a;
+    H[1] += b;
+    H[2] += c;
+    H[3] += d;
+    H[4] += e;
+    H[5] += f;
+    H[6] += g;
+    H[7] += h;
+}
+
+
+/**
+ *
+ */
+void Sha512Digest::update(unsigned char val)
+{
+    int wordNr = lenW >> 3;
+    W[wordNr] <<= 8;
+    W[wordNr] |= (unsigned long)val;
+    size += 8;
+    lenW++;
+    if (lenW >= 128)
+        {
+        hashblock();
+        lenW = 0;
+        }
+}
+
+
+/**
+ *
+ */
+std::vector<unsigned char> Sha512Digest::finish()
+{
+    //save our size before padding
+    unsigned long long sizeOut = size;
+    
+    // Pad with a binary 1 (0x80)
+    update((unsigned char)0x80);
+    //append 0's to make a 112-byte buf.
+       //we will loop around once if already over 112
+    while (lenW != 112)
+        update((unsigned char)0x00);
+        
+    //append 128-bit size
+    for (int i = 0 ; i < 8 ; i++) //64 upper bits
+        update((unsigned char)0x00);
+    for (int shift = 56 ; shift>=0 ; shift-= 8) //64 lower length bits
+        {
+        unsigned char ch = (unsigned char)((sizeOut >> shift) & 0xff);
+        update(ch);
+        }
+
+    // Output hash
+    std::vector<unsigned char> ret;
+    for (int wordNr = 0 ; wordNr < 8 ; wordNr++)
+        {
+        ret.push_back((unsigned char)((H[wordNr] >> 56) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 48) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 40) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 32) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 24) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >> 16) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr] >>  8) & 0xff));
+        ret.push_back((unsigned char)((H[wordNr]      ) & 0xff));
+        }
+
+    // Re-initialize the context (also zeroizes contents)
+    reset();
+
+    return ret;
+
+}
+
+
+
+//########################################################################
+//##  M D 5
+//########################################################################
+
+static int md5r[64] =
+{
+   7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22, 
+   5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
+   4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
+   6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21
+};
+
+static unsigned long md5k[64] =
+{
+0xd76aa478L, 0xe8c7b756L, 0x242070dbL, 0xc1bdceeeL, 
+0xf57c0fafL, 0x4787c62aL, 0xa8304613L, 0xfd469501L, 
+0x698098d8L, 0x8b44f7afL, 0xffff5bb1L, 0x895cd7beL, 
+0x6b901122L, 0xfd987193L, 0xa679438eL, 0x49b40821L, 
+0xf61e2562L, 0xc040b340L, 0x265e5a51L, 0xe9b6c7aaL, 
+0xd62f105dL, 0x02441453L, 0xd8a1e681L, 0xe7d3fbc8L, 
+0x21e1cde6L, 0xc33707d6L, 0xf4d50d87L, 0x455a14edL, 
+0xa9e3e905L, 0xfcefa3f8L, 0x676f02d9L, 0x8d2a4c8aL, 
+0xfffa3942L, 0x8771f681L, 0x6d9d6122L, 0xfde5380cL, 
+0xa4beea44L, 0x4bdecfa9L, 0xf6bb4b60L, 0xbebfbc70L, 
+0x289b7ec6L, 0xeaa127faL, 0xd4ef3085L, 0x04881d05L, 
+0xd9d4d039L, 0xe6db99e5L, 0x1fa27cf8L, 0xc4ac5665L, 
+0xf4292244L, 0x432aff97L, 0xab9423a7L, 0xfc93a039L, 
+0x655b59c3L, 0x8f0ccc92L, 0xffeff47dL, 0x85845dd1L, 
+0x6fa87e4fL, 0xfe2ce6e0L, 0xa3014314L, 0x4e0811a1L, 
+0xf7537e82L, 0xbd3af235L, 0x2ad7d2bbL, 0xeb86d391L
+};
+
+#define MD5_ROTL(X,n) (((X) << (n)) | ((X) >> (32-(n))))
+
+
+/**
+ *
+ */
+void Md5Digest::reset()
+{
+    size  = 0;
+    lenW  = 0;
+
+    hash[0]  = 0x67452301L;
+    hash[1]  = 0xefcdab89L;
+    hash[2]  = 0x98badcfeL;
+    hash[3]  = 0x10325476L;
+
+    for (int i = 0 ; i < 64 ; i++)
+        W[i] = 0;
+
+}
+
+
+
+
+
+
+/**
+ *
+ */
+void Md5Digest::hashblock()
+{
+    //for (int t = 0; t < 16 ; t++)
+    //    printf("%2d %08lx\n", t, W[t]);
+
+    unsigned long a = hash[0];
+    unsigned long b = hash[1];
+    unsigned long c = hash[2];
+    unsigned long d = hash[3];
+
+    int t = 0;
+    for ( ; t < 16 ; t++)
+        {
+        unsigned long f = d ^ ( b & ( c ^ d));
+        unsigned int g = t;
+        unsigned long temp = d; d = c; c = b;
+        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);
+        a = temp;
+        //printf("%2d %08lx %08lx %08lx %08lx\n", t, a, b, c, d);
+        }
+    for ( ; t < 32 ; t++)
+        {
+        unsigned long f = c ^ ( d & ( b ^ c));
+        unsigned int g = (5 * t + 1) & 0xf;
+        unsigned long temp = d; d = c; c = b;
+        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);
+        a = temp;
+        }
+    for ( ; t < 48 ; t++)
+        {
+        unsigned long f = b ^ c ^ d;
+        unsigned int g = (3 * t + 5) & 0xf;
+        unsigned long temp = d; d = c; c = b;
+        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);
+        a = temp;
+        }
+    for ( ; t < 64 ; t++)
+        {
+        unsigned long f = c ^ (b | ~d);
+        unsigned int g = (7 * t) & 0xf;
+        unsigned long temp = d; d = c; c = b;
+        b += MD5_ROTL(((a + f + md5k[t] + W[g])), md5r[t]);
+        a = temp;
+        }
+
+    hash[0] += a;
+    hash[1] += b;
+    hash[2] += c;
+    hash[3] += d;
+}
+
+
+/**
+ *
+ */
+void Md5Digest::update(unsigned char val)
+{
+    int wordNr = lenW >> 2;
+    /*
+       W[wordNr] <<= 8;
+    W[wordNr] |= (unsigned long)val;
+    */
+    W[wordNr] = ( (W[wordNr] >> 8) & 0x00ffffff ) |
+                ( ((unsigned long)val) << 24    );
+    size += 8;
+    lenW++;
+    if (lenW >= 64)
+        {
+        hashblock();
+        lenW = 0;
+        }
+}
+
+
+
+
+/**
+ *
+ */
+std::vector<unsigned char> Md5Digest::finish()
+{
+    //save our size before padding
+    unsigned long long sizeOut = size;
+    
+    // Pad with a binary 1 (0x80)
+    update((unsigned char)0x80);
+    //append 0's to make a 56-byte buf.
+       //use mod, so that we will loop around once if already over 56
+    while (lenW != 56)
+        update((unsigned char)0x00);
+
+
+    //Append the length.  Lower 32 bits first
+    update( (unsigned char) ((sizeOut    ) & 0xff));
+    update( (unsigned char) ((sizeOut>> 8) & 0xff));
+    update( (unsigned char) ((sizeOut>>16) & 0xff));
+    update( (unsigned char) ((sizeOut>>24) & 0xff));
+    update( (unsigned char) ((sizeOut>>32) & 0xff));
+    update( (unsigned char) ((sizeOut>>40) & 0xff));
+    update( (unsigned char) ((sizeOut>>48) & 0xff));
+    update( (unsigned char) ((sizeOut>>56) & 0xff));
+
+    //Output hash
+    std::vector<unsigned char> ret;
+    for (int wordNr = 0 ; wordNr<4 ; wordNr++)
+        {
+        unsigned long w = hash[wordNr];
+        ret.push_back( (unsigned char) ((w      ) & 0xff) );
+        ret.push_back( (unsigned char) ((w >>  8) & 0xff) );
+        ret.push_back( (unsigned char) ((w >> 16) & 0xff) );
+        ret.push_back( (unsigned char) ((w >> 24) & 0xff) );
+        }
+
+    // Re-initialize the context (also zeroizes contents)
+    reset();
+
+    return ret;
+}
+
+
+
+
+
+
+//########################################################################
+//## T E S T S
+//########################################################################
+
+/**
+ * Compile this file alone with -DDIGEST_TEST to run the
+ * tests below:
+ * > gcc -DDIGEST_TEST digest.cpp -o digest
+ * > digest   
+ */
+ #ifdef DIGEST_TEST
+
+
+typedef struct
+{
+    char *msg;
+    char *val;
+} TestPair;
+
+static TestPair md5tests[] =
+{
+  {
+  "",
+  "d41d8cd98f00b204e9800998ecf8427e"
+  },
+  {
+  "a",
+  "0cc175b9c0f1b6a831c399e269772661"
+  },
+  {
+  "abc",
+  "900150983cd24fb0d6963f7d28e17f72"
+  },
+  {
+  "message digest",
+  "f96b697d7cb7938d525a2f31aaf161d0"
+  },
+  {
+  "abcdefghijklmnopqrstuvwxyz",
+  "c3fcd3d76192e4007dfb496cca67e13b"
+  },
+  {
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+  "d174ab98d277d9f5a5611c2c9f419d9f"
+  },
+  {
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+  "57edf4a22be3c955ac49da2e2107b67a"
+  },
+  {
+  NULL,
+  NULL
+  }
+};
+
+
+
+static TestPair sha1tests[] =
+{
+  {
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+  "84983e441c3bd26ebaae4aa1f95129e5e54670f1"
+  },
+  {
+  NULL,
+  NULL
+  }
+};
+
+static TestPair sha224tests[] =
+{
+  {
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+  "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"
+  },
+  {
+  NULL,
+  NULL
+  }
+};
+
+static TestPair sha256tests[] =
+{
+  {
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+  "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
+  },
+  {
+  NULL,
+  NULL
+  }
+};
+
+static TestPair sha384tests[] =
+{
+  {
+  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+  "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
+       "fcc7c71a557e2db966c3e9fa91746039"
+  },
+  {
+  NULL,
+  NULL
+  }
+};
+
+static TestPair sha512tests[] =
+{
+  {
+  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+  "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+       "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
+  },
+  {
+  NULL,
+  NULL
+  }
+};
+
+
+bool hashTests(Digest &digest, TestPair *tp)
+{
+    for (TestPair *pair = tp ; pair->msg ; pair++)
+        {
+        digest.reset();
+        std::string msg = pair->msg;
+        std::string val = pair->val;
+        digest.append(msg);
+        std::string res = digest.finishHex();
+        printf("### Msg '%s':\n   hash '%s'\n   exp  '%s'\n",
+            msg.c_str(), res.c_str(), val.c_str());
+        if (res != val)
+            {
+            printf("ERROR: Hash mismatch\n");
+            return false;
+            }
+        }
+    return true;
+}
+
+
+bool millionATest(Digest &digest, const std::string &exp)
+{
+    digest.reset();
+       for (int i=0 ; i<1000000 ; i++)
+        digest.append('a');
+    std::string res = digest.finishHex();
+    printf("\nHash of 1,000,000 'a'\n   calc %s\n   exp  %s\n",
+            res.c_str(), exp.c_str());
+    if (res != exp)
+        {
+        printf("ERROR: Mismatch.\n");
+        return false;
+        }
+    return true;
+}
+
+static bool doTests()
+{
+    printf("##########################################\n");
+    printf("## MD5\n");
+    printf("##########################################\n");
+    Md5Digest md5;
+    if (!hashTests(md5, md5tests))
+        return false;
+    if (!millionATest(md5, "7707d6ae4e027c70eea2a935c2296f21"))
+        return false;
+    printf("\n\n\n");
+    printf("##########################################\n");
+    printf("## SHA1\n");
+    printf("##########################################\n");
+    Sha1Digest sha1;
+    if (!hashTests(sha1, sha1tests))
+        return false;
+    if (!millionATest(sha1, "34aa973cd4c4daa4f61eeb2bdbad27316534016f"))
+        return false;
+    printf("\n\n\n");
+    printf("##########################################\n");
+    printf("## SHA224\n");
+    printf("##########################################\n");
+    Sha224Digest sha224;
+    if (!hashTests(sha224, sha224tests))
+        return false;
+    if (!millionATest(sha224,
+            "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"))
+        return false;
+    printf("\n\n\n");
+    printf("##########################################\n");
+    printf("## SHA256\n");
+    printf("##########################################\n");
+    Sha256Digest sha256;
+    if (!hashTests(sha256, sha256tests))
+        return false;
+    if (!millionATest(sha256,
+            "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"))
+        return false;
+    printf("\n\n\n");
+    printf("##########################################\n");
+    printf("## SHA384\n");
+    printf("##########################################\n");
+    Sha384Digest sha384;
+    if (!hashTests(sha384, sha384tests))
+        return false;
+    /**/
+       if (!millionATest(sha384,
+                "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
+                "07b8b3dc38ecc4ebae97ddd87f3d8985"))
+        return false;
+    /**/
+    printf("\n\n\n");
+    printf("##########################################\n");
+    printf("## SHA512\n");
+    printf("##########################################\n");
+    Sha512Digest sha512;
+    if (!hashTests(sha512, sha512tests))
+        return false;
+    if (!millionATest(sha512,
+                "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
+             "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"))
+        return false;
+    return true;
+}
+
+
+int main(int argc, char **argv)
+{
+    doTests();
+    printf("####### done ########\n");
+    return 0;
+}
+
+
+#endif /* DIGEST_TEST */
+
+//########################################################################
+//## E N D    O F    F I L E
+//########################################################################
index 3667a25a912ea98f40e059aebc72fe60e3a234cf..46c60d2a3e5bd1b9b58e71f12103dd34a780aea6 100644 (file)
-#ifndef __DIGEST_H__\r
-#define __DIGEST_H__\r
-/**\r
- * Secure Hashing Tool\r
- * *\r
- * Authors:\r
- *   Bob Jamison\r
- *\r
- * Copyright (C) 2006 Bob Jamison\r
- *\r
- *  This library is free software; you can redistribute it and/or\r
- *  modify it under the terms of the GNU Lesser General Public\r
- *  License as published by the Free Software Foundation; either\r
- *  version 2.1 of the License, or (at your option) any later version.\r
- *\r
- *  This library is distributed in the hope that it will be useful,\r
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- *  Lesser General Public License for more details.\r
- *\r
- *  You should have received a copy of the GNU Lesser General Public\r
- *  License along with this library; if not, write to the Free Software\r
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
- */\r
-\r
-/**\r
- *\r
- *  This base class and its subclasses  provide an easy API for providing\r
- *  several different types of secure hashing functions for whatever use\r
- *  a developer might need.  This is not intended as a high-performance\r
- *  replacement for the fine implementations already available.  Rather, it\r
- *  is a small and simple (and maybe a bit slow?) tool for moderate common\r
- *  hashing requirements, like for communications and authentication.\r
- *  \r
- *  These hashes are intended to be simple to use.  For example:\r
- *  Sha256Digest digest;\r
- *  digest.append("The quick brown dog");\r
- *  std::string result = digest.finishHex();\r
- *  \r
- *  There are several forms of append() for convenience.\r
- *  finish() and finishHex() call reset() for both security and\r
- *  to prepare for the next use.\r
- *          \r
- */\r
-\r
-#include <vector>\r
-#include <string>\r
-\r
-\r
-/**\r
- *  Base class.  Do not use this class directly.  Rather, use of of the\r
- *  subclasses below.   \r
- *  For all subclasses, overload reset(), update(unsigned char), and finish()\r
- */\r
-class Digest\r
-{\r
-public:\r
-\r
-    /**\r
-     *  Different types of hash algorithms.\r
-     */\r
-    typedef enum\r
-        {\r
-        HASH_NONE,\r
-        HASH_SHA1,\r
-        HASH_SHA224,\r
-        HASH_SHA256,\r
-        HASH_SHA384,\r
-        HASH_SHA512,\r
-        HASH_MD5\r
-        } HashType;\r
-        \r
-    /**\r
-     *  Constructor, with no type\r
-     */\r
-    Digest() : hashType(HASH_NONE)\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Destructor\r
-     */\r
-    virtual ~Digest()\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Return one of the enumerated hash types above\r
-     */\r
-    virtual int getType()\r
-        { return hashType; }\r
-\r
-    /**\r
-     *  Append a single byte to the hash\r
-     */\r
-    void append(unsigned char ch)\r
-        { update(ch); }\r
-\r
-    /**\r
-     *  Append a string to the hash\r
-     */\r
-    virtual void append(const std::string &str)\r
-        {\r
-        for (unsigned int i=0 ; i<str.size() ; i++)\r
-            update((unsigned char)str[i]);\r
-        }\r
-\r
-    /**\r
-     *  Append a byte buffer to the hash\r
-     */\r
-    virtual void append(unsigned char *buf, int len)\r
-        {\r
-        for (int i=0 ; i<len ; i++)\r
-            update(buf[i]);\r
-        }\r
-\r
-    /**\r
-     *  Append a byte vector to the hash\r
-     */\r
-    virtual void append(const std::vector<unsigned char> buf)\r
-        {\r
-        for (unsigned int i=0 ; i<buf.size() ; i++)\r
-            update(buf[i]);\r
-        }\r
-\r
-    /**\r
-     *  Finish the hash and return a hexidecimal version of the computed\r
-     *  value     \r
-     */\r
-    virtual std::string finishHex();\r
-\r
-    /**\r
-     *  Initialize the fields of this hash engine to its starting values.    \r
-     *  Overload this in every subclass\r
-     */\r
-    virtual void reset()\r
-        {}\r
-\r
-    /**\r
-     *  Finish the hash and return its computed value    \r
-     *  Overload this in every subclass\r
-     */\r
-    virtual std::vector<unsigned char> finish()\r
-        {\r
-        std::vector<unsigned char> ret;\r
-        return ret;\r
-        }\r
-\r
-protected:\r
-\r
-    /**\r
-     *  Update the hash with a given byte    \r
-     *  Overload this in every subclass\r
-     */\r
-    virtual void update(unsigned char ch)\r
-        {}\r
-\r
-    /**\r
-     * The enumerated type of the hash\r
-     */             \r
-    int hashType;\r
-};\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- *  SHA-1,  \r
- *  Section 6.1, SECURE HASH STANDARD\r
- *  Federal Information Processing Standards Publication 180-2\r
- *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf\r
- */\r
-class Sha1Digest : public Digest\r
-{\r
-public:\r
-\r
-    /**\r
-     *  Constructor\r
-     */\r
-    Sha1Digest()\r
-        { hashType = HASH_SHA1; reset(); }\r
-\r
-    /**\r
-     *  Destructor\r
-     */\r
-    virtual ~Sha1Digest()\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void reset();\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual std::vector<unsigned char> finish();\r
-\r
-protected:\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void update(unsigned char val);\r
-\r
-private:\r
-\r
-    void hashblock();\r
-\r
-    unsigned long H[5];\r
-    unsigned long W[80];\r
-    unsigned long long size;\r
-    int lenW;\r
-\r
-};\r
-\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- *  SHA-224,  \r
- *  Section 6.1, SECURE HASH STANDARD\r
- *  Federal Information Processing Standards Publication 180-2\r
- *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf\r
- */\r
-class Sha224Digest : public Digest\r
-{\r
-public:\r
-\r
-    /**\r
-     *  Constructor\r
-     */\r
-    Sha224Digest()\r
-        { hashType = HASH_SHA224; reset(); }\r
-\r
-    /**\r
-     *  Destructor\r
-     */\r
-    virtual ~Sha224Digest()\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void reset();\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual std::vector<unsigned char> finish();\r
-\r
-protected:\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void update(unsigned char val);\r
-\r
-private:\r
-\r
-    void hashblock();\r
-\r
-    unsigned long H[8];\r
-    unsigned long W[64];\r
-    unsigned long long size;\r
-    int lenW;\r
-\r
-};\r
-\r
-\r
-\r
-/**\r
- *  SHA-256,  \r
- *  Section 6.1, SECURE HASH STANDARD\r
- *  Federal Information Processing Standards Publication 180-2\r
- *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf\r
- */\r
-class Sha256Digest : public Digest\r
-{\r
-public:\r
-\r
-    /**\r
-     *  Constructor\r
-     */\r
-    Sha256Digest()\r
-        { hashType = HASH_SHA256; reset(); }\r
-\r
-    /**\r
-     *  Destructor\r
-     */\r
-    virtual ~Sha256Digest()\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void reset();\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual std::vector<unsigned char> finish();\r
-\r
-protected:\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void update(unsigned char val);\r
-\r
-private:\r
-\r
-    void hashblock();\r
-\r
-    unsigned long H[8];\r
-    unsigned long W[64];\r
-    unsigned long long size;\r
-    int lenW;\r
-\r
-};\r
-\r
-\r
-/**\r
- *  SHA-384,\r
- *  Section 6.1, SECURE HASH STANDARD\r
- *  Federal Information Processing Standards Publication 180-2\r
- *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf\r
- */\r
-class Sha384Digest : public Digest\r
-{\r
-public:\r
-\r
-    /**\r
-     *  Constructor\r
-     */\r
-    Sha384Digest()\r
-        { hashType = HASH_SHA384; reset(); }\r
-\r
-    /**\r
-     *  Destructor\r
-     */\r
-    virtual ~Sha384Digest()\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void reset();\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual std::vector<unsigned char> finish();\r
-\r
-protected:\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void update(unsigned char val);\r
-\r
-private:\r
-\r
-    void hashblock();\r
-\r
-    unsigned long long H[8];\r
-    unsigned long long W[80];\r
-    unsigned long long size;\r
-    int lenW;\r
-\r
-};\r
-\r
-\r
-\r
-\r
-/**\r
- *  SHA-512,  \r
- *  Section 6.1, SECURE HASH STANDARD\r
- *  Federal Information Processing Standards Publication 180-2\r
- *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf\r
- */\r
-class Sha512Digest : public Digest\r
-{\r
-public:\r
-\r
-    /**\r
-     *  Constructor\r
-     */\r
-    Sha512Digest()\r
-        { hashType = HASH_SHA512; reset(); }\r
-\r
-    /**\r
-     *  Destructor\r
-     */\r
-    virtual ~Sha512Digest()\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void reset();\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual std::vector<unsigned char> finish();\r
-\r
-protected:\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void update(unsigned char val);\r
-\r
-private:\r
-\r
-    void hashblock();\r
-\r
-    unsigned long long H[8];\r
-    unsigned long long W[80];\r
-    unsigned long long size;\r
-    int lenW;\r
-\r
-};\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- * IETF RFC 1321, MD5 Specification\r
- * http://www.ietf.org/rfc/rfc1321.txt \r
- */\r
-class Md5Digest :  public Digest\r
-{\r
-public:\r
-\r
-    /**\r
-     *  Constructor\r
-     */\r
-    Md5Digest()\r
-        { hashType = HASH_MD5; reset(); }\r
-\r
-    /**\r
-     *  Destructor\r
-     */\r
-    virtual ~Md5Digest()\r
-        { reset(); }\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void reset();\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual std::vector<unsigned char> finish();\r
-\r
-protected:\r
-\r
-    /**\r
-     *  Overloaded from Digest\r
-     */\r
-    virtual void update(unsigned char val);\r
-\r
-private:\r
-\r
-    void hashblock();\r
-\r
-    unsigned long hash[8];\r
-    unsigned long W[64];\r
-    unsigned long long size;\r
-    int lenW;\r
-\r
-};\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-#endif /*  __DIGEST_H__ */\r
-\r
-\r
+#ifndef __DIGEST_H__
+#define __DIGEST_H__
+/**
+ * Secure Hashing Tool
+ * *
+ * Authors:
+ *   Bob Jamison
+ *
+ * Copyright (C) 2006 Bob Jamison
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ *
+ *  This base class and its subclasses  provide an easy API for providing
+ *  several different types of secure hashing functions for whatever use
+ *  a developer might need.  This is not intended as a high-performance
+ *  replacement for the fine implementations already available.  Rather, it
+ *  is a small and simple (and maybe a bit slow?) tool for moderate common
+ *  hashing requirements, like for communications and authentication.
+ *  
+ *  These hashes are intended to be simple to use.  For example:
+ *  Sha256Digest digest;
+ *  digest.append("The quick brown dog");
+ *  std::string result = digest.finishHex();
+ *  
+ *  There are several forms of append() for convenience.
+ *  finish() and finishHex() call reset() for both security and
+ *  to prepare for the next use.
+ *          
+ */
+
+#include <vector>
+#include <string>
+
+
+/**
+ *  Base class.  Do not use this class directly.  Rather, use of of the
+ *  subclasses below.   
+ *  For all subclasses, overload reset(), update(unsigned char), and finish()
+ */
+class Digest
+{
+public:
+
+    /**
+     *  Different types of hash algorithms.
+     */
+    typedef enum
+        {
+        HASH_NONE,
+        HASH_SHA1,
+        HASH_SHA224,
+        HASH_SHA256,
+        HASH_SHA384,
+        HASH_SHA512,
+        HASH_MD5
+        } HashType;
+        
+    /**
+     *  Constructor, with no type
+     */
+    Digest() : hashType(HASH_NONE)
+        { reset(); }
+
+    /**
+     *  Destructor
+     */
+    virtual ~Digest()
+        { reset(); }
+
+    /**
+     *  Return one of the enumerated hash types above
+     */
+    virtual int getType()
+        { return hashType; }
+
+    /**
+     *  Append a single byte to the hash
+     */
+    void append(unsigned char ch)
+        { update(ch); }
+
+    /**
+     *  Append a string to the hash
+     */
+    virtual void append(const std::string &str)
+        {
+        for (unsigned int i=0 ; i<str.size() ; i++)
+            update((unsigned char)str[i]);
+        }
+
+    /**
+     *  Append a byte buffer to the hash
+     */
+    virtual void append(unsigned char *buf, int len)
+        {
+        for (int i=0 ; i<len ; i++)
+            update(buf[i]);
+        }
+
+    /**
+     *  Append a byte vector to the hash
+     */
+    virtual void append(const std::vector<unsigned char> buf)
+        {
+        for (unsigned int i=0 ; i<buf.size() ; i++)
+            update(buf[i]);
+        }
+
+    /**
+     *  Finish the hash and return a hexidecimal version of the computed
+     *  value     
+     */
+    virtual std::string finishHex();
+
+    /**
+     *  Initialize the fields of this hash engine to its starting values.    
+     *  Overload this in every subclass
+     */
+    virtual void reset()
+        {}
+
+    /**
+     *  Finish the hash and return its computed value    
+     *  Overload this in every subclass
+     */
+    virtual std::vector<unsigned char> finish()
+        {
+        std::vector<unsigned char> ret;
+        return ret;
+        }
+
+protected:
+
+    /**
+     *  Update the hash with a given byte    
+     *  Overload this in every subclass
+     */
+    virtual void update(unsigned char ch)
+        {}
+
+    /**
+     * The enumerated type of the hash
+     */             
+    int hashType;
+};
+
+
+
+
+
+/**
+ *  SHA-1,  
+ *  Section 6.1, SECURE HASH STANDARD
+ *  Federal Information Processing Standards Publication 180-2
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
+ */
+class Sha1Digest : public Digest
+{
+public:
+
+    /**
+     *  Constructor
+     */
+    Sha1Digest()
+        { hashType = HASH_SHA1; reset(); }
+
+    /**
+     *  Destructor
+     */
+    virtual ~Sha1Digest()
+        { reset(); }
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void reset();
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual std::vector<unsigned char> finish();
+
+protected:
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void update(unsigned char val);
+
+private:
+
+    void hashblock();
+
+    unsigned long H[5];
+    unsigned long W[80];
+    unsigned long long size;
+    int lenW;
+
+};
+
+
+
+
+
+
+/**
+ *  SHA-224,  
+ *  Section 6.1, SECURE HASH STANDARD
+ *  Federal Information Processing Standards Publication 180-2
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
+ */
+class Sha224Digest : public Digest
+{
+public:
+
+    /**
+     *  Constructor
+     */
+    Sha224Digest()
+        { hashType = HASH_SHA224; reset(); }
+
+    /**
+     *  Destructor
+     */
+    virtual ~Sha224Digest()
+        { reset(); }
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void reset();
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual std::vector<unsigned char> finish();
+
+protected:
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void update(unsigned char val);
+
+private:
+
+    void hashblock();
+
+    unsigned long H[8];
+    unsigned long W[64];
+    unsigned long long size;
+    int lenW;
+
+};
+
+
+
+/**
+ *  SHA-256,  
+ *  Section 6.1, SECURE HASH STANDARD
+ *  Federal Information Processing Standards Publication 180-2
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
+ */
+class Sha256Digest : public Digest
+{
+public:
+
+    /**
+     *  Constructor
+     */
+    Sha256Digest()
+        { hashType = HASH_SHA256; reset(); }
+
+    /**
+     *  Destructor
+     */
+    virtual ~Sha256Digest()
+        { reset(); }
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void reset();
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual std::vector<unsigned char> finish();
+
+protected:
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void update(unsigned char val);
+
+private:
+
+    void hashblock();
+
+    unsigned long H[8];
+    unsigned long W[64];
+    unsigned long long size;
+    int lenW;
+
+};
+
+
+/**
+ *  SHA-384,
+ *  Section 6.1, SECURE HASH STANDARD
+ *  Federal Information Processing Standards Publication 180-2
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
+ */
+class Sha384Digest : public Digest
+{
+public:
+
+    /**
+     *  Constructor
+     */
+    Sha384Digest()
+        { hashType = HASH_SHA384; reset(); }
+
+    /**
+     *  Destructor
+     */
+    virtual ~Sha384Digest()
+        { reset(); }
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void reset();
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual std::vector<unsigned char> finish();
+
+protected:
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void update(unsigned char val);
+
+private:
+
+    void hashblock();
+
+    unsigned long long H[8];
+    unsigned long long W[80];
+    unsigned long long size;
+    int lenW;
+
+};
+
+
+
+
+/**
+ *  SHA-512,  
+ *  Section 6.1, SECURE HASH STANDARD
+ *  Federal Information Processing Standards Publication 180-2
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
+ */
+class Sha512Digest : public Digest
+{
+public:
+
+    /**
+     *  Constructor
+     */
+    Sha512Digest()
+        { hashType = HASH_SHA512; reset(); }
+
+    /**
+     *  Destructor
+     */
+    virtual ~Sha512Digest()
+        { reset(); }
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void reset();
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual std::vector<unsigned char> finish();
+
+protected:
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void update(unsigned char val);
+
+private:
+
+    void hashblock();
+
+    unsigned long long H[8];
+    unsigned long long W[80];
+    unsigned long long size;
+    int lenW;
+
+};
+
+
+
+
+
+
+
+
+
+/**
+ * IETF RFC 1321, MD5 Specification
+ * http://www.ietf.org/rfc/rfc1321.txt 
+ */
+class Md5Digest :  public Digest
+{
+public:
+
+    /**
+     *  Constructor
+     */
+    Md5Digest()
+        { hashType = HASH_MD5; reset(); }
+
+    /**
+     *  Destructor
+     */
+    virtual ~Md5Digest()
+        { reset(); }
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void reset();
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual std::vector<unsigned char> finish();
+
+protected:
+
+    /**
+     *  Overloaded from Digest
+     */
+    virtual void update(unsigned char val);
+
+private:
+
+    void hashblock();
+
+    unsigned long hash[8];
+    unsigned long W[64];
+    unsigned long long size;
+    int lenW;
+
+};
+
+
+
+
+
+
+
+
+
+#endif /*  __DIGEST_H__ */
+
+
index 9ee1ae32ff1fb98a659fe918839c76cbc332fbc7..88010e686a7e0c1110384c65a3765026a7e20ed9 100644 (file)
-/*\r
- * A quick hack to use the print output to write out a file.  This\r
- * then makes 'save as...' PDF.\r
- *\r
- * Authors:\r
- *   Ted Gould <ted@gould.cx>\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2004-2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include <config.h>\r
-#endif\r
-\r
-#ifdef HAVE_CAIRO_PDF\r
-\r
-#include "cairo-pdf-out.h"\r
-#include <print.h>\r
-#include "extension/system.h"\r
-#include "extension/print.h"\r
-#include "extension/db.h"\r
-#include "extension/output.h"\r
-#include "display/nr-arena.h"\r
-#include "display/nr-arena-item.h"\r
-#include "sp-path.h"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-bool\r
-CairoPdfOutput::check (Inkscape::Extension::Extension * module)\r
-{\r
-       if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PDF))\r
-               return FALSE;\r
-\r
-       return TRUE;\r
-}\r
-\r
-\r
-static unsigned int\r
-pdf_print_document_to_file(SPDocument *doc, gchar const *filename)\r
-{\r
-    Inkscape::Extension::Print *mod;\r
-    SPPrintContext context;\r
-    gchar const *oldconst;\r
-    gchar *oldoutput;\r
-    unsigned int ret;\r
-\r
-    sp_document_ensure_up_to_date(doc);\r
-\r
-    mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_CAIRO_PDF);\r
-    oldconst = mod->get_param_string("destination");\r
-    oldoutput = g_strdup(oldconst);\r
-    mod->set_param_string("destination", (gchar *)filename);\r
-\r
-/* Start */\r
-    context.module = mod;\r
-    /* fixme: This has to go into module constructor somehow */\r
-    /* Create new arena */\r
-    mod->base = SP_ITEM(sp_document_root(doc));\r
-    mod->arena = NRArena::create();\r
-    mod->dkey = sp_item_display_key_new(1);\r
-    mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);\r
-    \r
-    /* Print document */\r
-    ret = mod->begin(doc);\r
-    if (ret) {\r
-        sp_item_invoke_print(mod->base, &context);\r
-        ret = mod->finish();\r
-    }\r
-    \r
-    /* Release arena */\r
-    sp_item_invoke_hide(mod->base, mod->dkey);\r
-    mod->base = NULL;\r
-    nr_arena_item_unref(mod->root);\r
-    mod->root = NULL;\r
-    nr_object_unref((NRObject *) mod->arena);\r
-    mod->arena = NULL;\r
-/* end */\r
-\r
-    mod->set_param_string("destination", oldoutput);\r
-    g_free(oldoutput);\r
-\r
-    return ret;\r
-}\r
-\r
-\r
-/**\r
-    \brief  This function calls the print system with the filename\r
-       \param  mod   unused\r
-       \param  doc   Document to be saved\r
-    \param  uri   Filename to save to (probably will end in .pdf)\r
-\r
-       The most interesting thing that this function does is just attach\r
-       an '>' on the front of the filename.  This is the syntax used to\r
-       tell the printing system to save to file.\r
-*/\r
-void\r
-CairoPdfOutput::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)\r
-{\r
-    Inkscape::Extension::Extension * ext;\r
-    unsigned int ret;\r
-\r
-    ext = Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PDF);\r
-    if (ext == NULL)\r
-        return;\r
-\r
-       gchar * final_name;\r
-       final_name = g_strdup_printf("> %s", uri);\r
-       ret = pdf_print_document_to_file(doc, final_name);\r
-       g_free(final_name);\r
-        \r
-       if (!ret)\r
-           throw Inkscape::Extension::Output::save_failed();\r
-\r
-       return;\r
-}\r
-\r
-/**\r
-       \brief   A function allocate a copy of this function.\r
-\r
-       This is the definition of PDF out.  This function just\r
-       calls the extension system with the memory allocated XML that\r
-       describes the data.\r
-*/\r
-void\r
-CairoPdfOutput::init (void)\r
-{\r
-       Inkscape::Extension::build_from_mem(\r
-               "<inkscape-extension>\n"\r
-                       "<name>Cairo PDF Output</name>\n"\r
-                       "<id>org.inkscape.output.pdf.cairo</id>\n"\r
-                       "<output>\n"\r
-                               "<extension>.pdf</extension>\n"\r
-                               "<mimetype>application/pdf</mimetype>\n"\r
-                               "<filetypename>Cairo PDF (*.pdf)</filetypename>\n"\r
-                               "<filetypetooltip>PDF File</filetypetooltip>\n"\r
-                       "</output>\n"\r
-               "</inkscape-extension>", new CairoPdfOutput());\r
-\r
-       return;\r
-}\r
-\r
-} } }  /* namespace Inkscape, Extension, Implementation */\r
-\r
-#endif /* HAVE_CAIRO_PDF */\r
+/*
+ * A quick hack to use the print output to write out a file.  This
+ * then makes 'save as...' PDF.
+ *
+ * Authors:
+ *   Ted Gould <ted@gould.cx>
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2004-2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_CAIRO_PDF
+
+#include "cairo-pdf-out.h"
+#include <print.h>
+#include "extension/system.h"
+#include "extension/print.h"
+#include "extension/db.h"
+#include "extension/output.h"
+#include "display/nr-arena.h"
+#include "display/nr-arena-item.h"
+#include "sp-path.h"
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+bool
+CairoPdfOutput::check (Inkscape::Extension::Extension * module)
+{
+       if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PDF))
+               return FALSE;
+
+       return TRUE;
+}
+
+
+static unsigned int
+pdf_print_document_to_file(SPDocument *doc, gchar const *filename)
+{
+    Inkscape::Extension::Print *mod;
+    SPPrintContext context;
+    gchar const *oldconst;
+    gchar *oldoutput;
+    unsigned int ret;
+
+    sp_document_ensure_up_to_date(doc);
+
+    mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_CAIRO_PDF);
+    oldconst = mod->get_param_string("destination");
+    oldoutput = g_strdup(oldconst);
+    mod->set_param_string("destination", (gchar *)filename);
+
+/* Start */
+    context.module = mod;
+    /* fixme: This has to go into module constructor somehow */
+    /* Create new arena */
+    mod->base = SP_ITEM(sp_document_root(doc));
+    mod->arena = NRArena::create();
+    mod->dkey = sp_item_display_key_new(1);
+    mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+    
+    /* Print document */
+    ret = mod->begin(doc);
+    if (ret) {
+        sp_item_invoke_print(mod->base, &context);
+        ret = mod->finish();
+    }
+    
+    /* Release arena */
+    sp_item_invoke_hide(mod->base, mod->dkey);
+    mod->base = NULL;
+    nr_arena_item_unref(mod->root);
+    mod->root = NULL;
+    nr_object_unref((NRObject *) mod->arena);
+    mod->arena = NULL;
+/* end */
+
+    mod->set_param_string("destination", oldoutput);
+    g_free(oldoutput);
+
+    return ret;
+}
+
+
+/**
+    \brief  This function calls the print system with the filename
+       \param  mod   unused
+       \param  doc   Document to be saved
+    \param  uri   Filename to save to (probably will end in .pdf)
+
+       The most interesting thing that this function does is just attach
+       an '>' on the front of the filename.  This is the syntax used to
+       tell the printing system to save to file.
+*/
+void
+CairoPdfOutput::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)
+{
+    Inkscape::Extension::Extension * ext;
+    unsigned int ret;
+
+    ext = Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PDF);
+    if (ext == NULL)
+        return;
+
+       gchar * final_name;
+       final_name = g_strdup_printf("> %s", uri);
+       ret = pdf_print_document_to_file(doc, final_name);
+       g_free(final_name);
+        
+       if (!ret)
+           throw Inkscape::Extension::Output::save_failed();
+
+       return;
+}
+
+/**
+       \brief   A function allocate a copy of this function.
+
+       This is the definition of PDF out.  This function just
+       calls the extension system with the memory allocated XML that
+       describes the data.
+*/
+void
+CairoPdfOutput::init (void)
+{
+       Inkscape::Extension::build_from_mem(
+               "<inkscape-extension>\n"
+                       "<name>Cairo PDF Output</name>\n"
+                       "<id>org.inkscape.output.pdf.cairo</id>\n"
+                       "<output>\n"
+                               "<extension>.pdf</extension>\n"
+                               "<mimetype>application/pdf</mimetype>\n"
+                               "<filetypename>Cairo PDF (*.pdf)</filetypename>\n"
+                               "<filetypetooltip>PDF File</filetypetooltip>\n"
+                       "</output>\n"
+               "</inkscape-extension>", new CairoPdfOutput());
+
+       return;
+}
+
+} } }  /* namespace Inkscape, Extension, Implementation */
+
+#endif /* HAVE_CAIRO_PDF */
index f0e67f165d4ca0a8c9ddd7524b53a8f5520e05f7..42cd9365c2d4545a0a2d3a86dc30c15c083ed2a0 100644 (file)
@@ -1,50 +1,50 @@
-/*\r
- * A quick hack to use the print output to write out a file.  This\r
- * then makes 'save as...' PDF.\r
- *\r
- * Authors:\r
- *   Ted Gould <ted@gould.cx>\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2004-2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifndef EXTENSION_INTERNAL_CAIRO_PDF_OUT_H\r
-#define EXTENSION_INTERNAL_CAIRO_PDF_OUT_H\r
-\r
-#include "extension/implementation/implementation.h"\r
-\r
-#ifdef HAVE_CAIRO_PDF\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-class CairoPdfOutput : Inkscape::Extension::Implementation::Implementation {\r
-\r
-public:\r
-    bool check(Inkscape::Extension::Extension *module);\r
-    void save(Inkscape::Extension::Output *mod,\r
-              SPDocument *doc,\r
-              gchar const *uri);\r
-    static void init();\r
-};\r
-\r
-} } }  /* namespace Inkscape, Extension, Implementation */\r
-\r
-#endif /* HAVE_CAIRO_PDF */\r
-\r
-#endif /* !EXTENSION_INTERNAL_CAIRO_PDF_OUT_H */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
+/*
+ * A quick hack to use the print output to write out a file.  This
+ * then makes 'save as...' PDF.
+ *
+ * Authors:
+ *   Ted Gould <ted@gould.cx>
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2004-2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef EXTENSION_INTERNAL_CAIRO_PDF_OUT_H
+#define EXTENSION_INTERNAL_CAIRO_PDF_OUT_H
+
+#include "extension/implementation/implementation.h"
+
+#ifdef HAVE_CAIRO_PDF
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class CairoPdfOutput : Inkscape::Extension::Implementation::Implementation {
+
+public:
+    bool check(Inkscape::Extension::Extension *module);
+    void save(Inkscape::Extension::Output *mod,
+              SPDocument *doc,
+              gchar const *uri);
+    static void init();
+};
+
+} } }  /* namespace Inkscape, Extension, Implementation */
+
+#endif /* HAVE_CAIRO_PDF */
+
+#endif /* !EXTENSION_INTERNAL_CAIRO_PDF_OUT_H */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index f34a90b226960874617b12544e060ef21f47c644..6fd45d0d5a7afbcb31bda2f7eb90bdcfadad77c8 100644 (file)
-/*\r
- * A quick hack to use the Cairo renderer to write out a file.  This\r
- * then makes 'save as...' PNG.\r
- *\r
- * Authors:\r
- *   Ted Gould <ted@gould.cx>\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2004-2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include <config.h>\r
-#endif\r
-\r
-#ifdef HAVE_CAIRO_PDF\r
-\r
-#include "cairo-png-out.h"\r
-#include "cairo-render-context.h"\r
-#include "cairo-renderer.h"\r
-#include <print.h>\r
-#include "extension/system.h"\r
-#include "extension/print.h"\r
-#include "extension/db.h"\r
-#include "extension/output.h"\r
-#include "display/nr-arena.h"\r
-#include "display/nr-arena-item.h"\r
-\r
-#include <libnr/n-art-bpath.h>\r
-\r
-#include "display/curve.h"\r
-#include "display/canvas-bpath.h"\r
-#include "sp-item.h"\r
-#include "style.h"\r
-#include "sp-root.h"\r
-#include "sp-shape.h"\r
-\r
-#include "io/sys.h"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-bool\r
-CairoRendererOutput::check (Inkscape::Extension::Extension * module)\r
-{\r
-       return TRUE;\r
-}\r
-\r
-static bool\r
-png_render_document_to_file(SPDocument *doc, gchar const *filename)\r
-{\r
-    CairoRenderer *renderer;\r
-    CairoRenderContext *ctx;\r
-\r
-    sp_document_ensure_up_to_date(doc);\r
-\r
-/* Start */\r
-    /* Create new arena */\r
-    SPItem *base = SP_ITEM(sp_document_root(doc));\r
-    NRArena *arena = NRArena::create();\r
-    unsigned dkey = sp_item_display_key_new(1);\r
-    NRArenaItem *root = sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);\r
-    \r
-    /* Create renderer and context */\r
-    renderer = new CairoRenderer();\r
-    ctx = renderer->createContext();\r
-\r
-    /* Render document */\r
-    bool ret = renderer->setupDocument(ctx, doc);\r
-    if (ret) {\r
-        renderer->renderItem(ctx, base);\r
-        ctx->saveAsPng(filename);\r
-        ret = ctx->finish();\r
-    }\r
-    renderer->destroyContext(ctx);\r
-\r
-    /* Release arena */\r
-    sp_item_invoke_hide(base, dkey);\r
-    nr_arena_item_unref(root);\r
-    nr_object_unref((NRObject *) arena);\r
-/* end */\r
-    delete renderer;\r
-\r
-    return ret;\r
-}\r
-\r
-\r
-/**\r
-    \brief  This function calls the output module with the filename\r
-       \param  mod   unused\r
-       \param  doc   Document to be saved\r
-    \param  uri   Filename to save to (probably will end in .png)\r
-*/\r
-void\r
-CairoRendererOutput::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)\r
-{\r
-    if (!png_render_document_to_file(doc, uri))\r
-        throw Inkscape::Extension::Output::save_failed();\r
-\r
-       return;\r
-}\r
-\r
-/**\r
-       \brief   A function allocate a copy of this function.\r
-\r
-       This is the definition of Cairo PNG out.  This function just\r
-       calls the extension system with the memory allocated XML that\r
-       describes the data.\r
-*/\r
-void\r
-CairoRendererOutput::init (void)\r
-{\r
-       Inkscape::Extension::build_from_mem(\r
-               "<inkscape-extension>\n"\r
-                       "<name>Cairo PNG Output</name>\n"\r
-                       "<id>org.inkscape.output.png.cairo</id>\n"\r
-                       "<output>\n"\r
-                               "<extension>.png</extension>\n"\r
-                "<mimetype>image/png</mimetype>\n"\r
-                               "<filetypename>Cairo PNG (*.png)</filetypename>\n"\r
-                               "<filetypetooltip>PNG File</filetypetooltip>\n"\r
-                       "</output>\n"\r
-               "</inkscape-extension>", new CairoRendererOutput());\r
-\r
-       return;\r
-}\r
-\r
-} } }  /* namespace Inkscape, Extension, Implementation */\r
-\r
-#endif /* HAVE_CAIRO_PDF */\r
+/*
+ * A quick hack to use the Cairo renderer to write out a file.  This
+ * then makes 'save as...' PNG.
+ *
+ * Authors:
+ *   Ted Gould <ted@gould.cx>
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2004-2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_CAIRO_PDF
+
+#include "cairo-png-out.h"
+#include "cairo-render-context.h"
+#include "cairo-renderer.h"
+#include <print.h>
+#include "extension/system.h"
+#include "extension/print.h"
+#include "extension/db.h"
+#include "extension/output.h"
+#include "display/nr-arena.h"
+#include "display/nr-arena-item.h"
+
+#include <libnr/n-art-bpath.h>
+
+#include "display/curve.h"
+#include "display/canvas-bpath.h"
+#include "sp-item.h"
+#include "style.h"
+#include "sp-root.h"
+#include "sp-shape.h"
+
+#include "io/sys.h"
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+bool
+CairoRendererOutput::check (Inkscape::Extension::Extension * module)
+{
+       return TRUE;
+}
+
+static bool
+png_render_document_to_file(SPDocument *doc, gchar const *filename)
+{
+    CairoRenderer *renderer;
+    CairoRenderContext *ctx;
+
+    sp_document_ensure_up_to_date(doc);
+
+/* Start */
+    /* Create new arena */
+    SPItem *base = SP_ITEM(sp_document_root(doc));
+    NRArena *arena = NRArena::create();
+    unsigned dkey = sp_item_display_key_new(1);
+    NRArenaItem *root = sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);
+    
+    /* Create renderer and context */
+    renderer = new CairoRenderer();
+    ctx = renderer->createContext();
+
+    /* Render document */
+    bool ret = renderer->setupDocument(ctx, doc);
+    if (ret) {
+        renderer->renderItem(ctx, base);
+        ctx->saveAsPng(filename);
+        ret = ctx->finish();
+    }
+    renderer->destroyContext(ctx);
+
+    /* Release arena */
+    sp_item_invoke_hide(base, dkey);
+    nr_arena_item_unref(root);
+    nr_object_unref((NRObject *) arena);
+/* end */
+    delete renderer;
+
+    return ret;
+}
+
+
+/**
+    \brief  This function calls the output module with the filename
+       \param  mod   unused
+       \param  doc   Document to be saved
+    \param  uri   Filename to save to (probably will end in .png)
+*/
+void
+CairoRendererOutput::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)
+{
+    if (!png_render_document_to_file(doc, uri))
+        throw Inkscape::Extension::Output::save_failed();
+
+       return;
+}
+
+/**
+       \brief   A function allocate a copy of this function.
+
+       This is the definition of Cairo PNG out.  This function just
+       calls the extension system with the memory allocated XML that
+       describes the data.
+*/
+void
+CairoRendererOutput::init (void)
+{
+       Inkscape::Extension::build_from_mem(
+               "<inkscape-extension>\n"
+                       "<name>Cairo PNG Output</name>\n"
+                       "<id>org.inkscape.output.png.cairo</id>\n"
+                       "<output>\n"
+                               "<extension>.png</extension>\n"
+                "<mimetype>image/png</mimetype>\n"
+                               "<filetypename>Cairo PNG (*.png)</filetypename>\n"
+                               "<filetypetooltip>PNG File</filetypetooltip>\n"
+                       "</output>\n"
+               "</inkscape-extension>", new CairoRendererOutput());
+
+       return;
+}
+
+} } }  /* namespace Inkscape, Extension, Implementation */
+
+#endif /* HAVE_CAIRO_PDF */
index 207786c88c765ce4c57eb612052299cde76a2eba..625c53ffcf36dc91f9578cef489e0e26ed56f43b 100644 (file)
@@ -1,50 +1,50 @@
-/*\r
- * A quick hack to use the print output to write out a file.  This\r
- * then makes 'save as...' PNG.\r
- *\r
- * Authors:\r
- *   Ted Gould <ted@gould.cx>\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2004-2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifndef EXTENSION_INTERNAL_CAIRO_PNG_OUT_H\r
-#define EXTENSION_INTERNAL_CAIRO_PNG_OUT_H\r
-\r
-#include "extension/implementation/implementation.h"\r
-\r
-#ifdef HAVE_CAIRO_PDF\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-class CairoRendererOutput : Inkscape::Extension::Implementation::Implementation {\r
-\r
-public:\r
-    bool check(Inkscape::Extension::Extension *module);\r
-    void save(Inkscape::Extension::Output *mod,\r
-              SPDocument *doc,\r
-              gchar const *uri);\r
-    static void init();\r
-};\r
-\r
-} } }  /* namespace Inkscape, Extension, Implementation */\r
-\r
-#endif /* HAVE_CAIRO_PDF */\r
-\r
-#endif /* !EXTENSION_INTERNAL_CAIRO_PNG_OUT_H */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
+/*
+ * A quick hack to use the print output to write out a file.  This
+ * then makes 'save as...' PNG.
+ *
+ * Authors:
+ *   Ted Gould <ted@gould.cx>
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2004-2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef EXTENSION_INTERNAL_CAIRO_PNG_OUT_H
+#define EXTENSION_INTERNAL_CAIRO_PNG_OUT_H
+
+#include "extension/implementation/implementation.h"
+
+#ifdef HAVE_CAIRO_PDF
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class CairoRendererOutput : Inkscape::Extension::Implementation::Implementation {
+
+public:
+    bool check(Inkscape::Extension::Extension *module);
+    void save(Inkscape::Extension::Output *mod,
+              SPDocument *doc,
+              gchar const *uri);
+    static void init();
+};
+
+} } }  /* namespace Inkscape, Extension, Implementation */
+
+#endif /* HAVE_CAIRO_PDF */
+
+#endif /* !EXTENSION_INTERNAL_CAIRO_PNG_OUT_H */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 5d27656609ab8bcfe34acf8261d1ddfc425691e3..82b736ad26f58b6abe82b5f4409569e9af55e483 100644 (file)
-/*\r
- * A quick hack to use the Cairo renderer to write out a file.  This\r
- * then makes 'save as...' PDF.\r
- *\r
- * Authors:\r
- *   Ted Gould <ted@gould.cx>\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2004-2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include <config.h>\r
-#endif\r
-\r
-#ifdef HAVE_CAIRO_PDF\r
-\r
-#include "cairo-renderer-pdf-out.h"\r
-#include "cairo-render-context.h"\r
-#include "cairo-renderer.h"\r
-#include <print.h>\r
-#include "extension/system.h"\r
-#include "extension/print.h"\r
-#include "extension/db.h"\r
-#include "extension/output.h"\r
-#include "display/nr-arena.h"\r
-#include "display/nr-arena-item.h"\r
-\r
-#include <libnr/n-art-bpath.h>\r
-\r
-#include "display/curve.h"\r
-#include "display/canvas-bpath.h"\r
-#include "sp-item.h"\r
-#include "sp-root.h"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-bool\r
-CairoRendererPdfOutput::check (Inkscape::Extension::Extension * module)\r
-{\r
-       return TRUE;\r
-}\r
-\r
-static bool\r
-pdf_render_document_to_file(SPDocument *doc, gchar const *filename)\r
-{\r
-    sp_document_ensure_up_to_date(doc);\r
-\r
-/* Start */\r
-    /* Create new arena */\r
-    SPItem *base = SP_ITEM(sp_document_root(doc));\r
-    NRArena *arena = NRArena::create();\r
-    unsigned dkey = sp_item_display_key_new(1);\r
-    NRArenaItem *root = sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);\r
-    \r
-    /* Create renderer and context */\r
-    CairoRenderer *renderer = new CairoRenderer();\r
-    CairoRenderContext *ctx = renderer->createContext();\r
-    ctx->setPdfTarget (filename);\r
-    bool ret = renderer->setupDocument(ctx, doc);\r
-    if (ret) {\r
-        renderer->renderItem(ctx, base);\r
-        ret = ctx->finish();\r
-    }\r
-\r
-    /* Release arena */\r
-    sp_item_invoke_hide(base, dkey);\r
-    nr_arena_item_unref(root);\r
-    nr_object_unref((NRObject *) arena);\r
-/* end */\r
-    renderer->destroyContext(ctx);\r
-    delete renderer;\r
-\r
-    return ret;\r
-}\r
-\r
-\r
-/**\r
-    \brief  This function calls the output module with the filename\r
-       \param  mod   unused\r
-       \param  doc   Document to be saved\r
-    \param  uri   Filename to save to (probably will end in .png)\r
-\r
-       The most interesting thing that this function does is just attach\r
-       an '>' on the front of the filename.  This is the syntax used to\r
-       tell the printing system to save to file.\r
-*/\r
-void\r
-CairoRendererPdfOutput::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)\r
-{\r
-    gchar * final_name;\r
-    final_name = g_strdup_printf("> %s", uri);\r
-    bool ret = pdf_render_document_to_file(doc, final_name);\r
-    g_free(final_name);\r
-\r
-    if (!ret)\r
-        throw Inkscape::Extension::Output::save_failed();\r
-\r
-       return;\r
-}\r
-\r
-/**\r
-       \brief   A function allocate a copy of this function.\r
-\r
-       This is the definition of Cairo PDF out.  This function just\r
-       calls the extension system with the memory allocated XML that\r
-       describes the data.\r
-*/\r
-void\r
-CairoRendererPdfOutput::init (void)\r
-{\r
-       Inkscape::Extension::build_from_mem(\r
-               "<inkscape-extension>\n"\r
-            "<name>Cairo PDF Output (experimental)</name>\n"\r
-                       "<id>org.inkscape.output.pdf.cairorenderer</id>\n"\r
-                       "<output>\n"\r
-                               "<extension>.pdf</extension>\n"\r
-                               "<mimetype>application/pdf</mimetype>\n"\r
-                               "<filetypename>Cairo PDF experimental (*.pdf)</filetypename>\n"\r
-                               "<filetypetooltip>PDF File</filetypetooltip>\n"\r
-                       "</output>\n"\r
-               "</inkscape-extension>", new CairoRendererPdfOutput());\r
-\r
-       return;\r
-}\r
-\r
-} } }  /* namespace Inkscape, Extension, Internal */\r
-\r
-#endif /* HAVE_CAIRO_PDF */\r
+/*
+ * A quick hack to use the Cairo renderer to write out a file.  This
+ * then makes 'save as...' PDF.
+ *
+ * Authors:
+ *   Ted Gould <ted@gould.cx>
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2004-2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_CAIRO_PDF
+
+#include "cairo-renderer-pdf-out.h"
+#include "cairo-render-context.h"
+#include "cairo-renderer.h"
+#include <print.h>
+#include "extension/system.h"
+#include "extension/print.h"
+#include "extension/db.h"
+#include "extension/output.h"
+#include "display/nr-arena.h"
+#include "display/nr-arena-item.h"
+
+#include <libnr/n-art-bpath.h>
+
+#include "display/curve.h"
+#include "display/canvas-bpath.h"
+#include "sp-item.h"
+#include "sp-root.h"
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+bool
+CairoRendererPdfOutput::check (Inkscape::Extension::Extension * module)
+{
+       return TRUE;
+}
+
+static bool
+pdf_render_document_to_file(SPDocument *doc, gchar const *filename)
+{
+    sp_document_ensure_up_to_date(doc);
+
+/* Start */
+    /* Create new arena */
+    SPItem *base = SP_ITEM(sp_document_root(doc));
+    NRArena *arena = NRArena::create();
+    unsigned dkey = sp_item_display_key_new(1);
+    NRArenaItem *root = sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);
+    
+    /* Create renderer and context */
+    CairoRenderer *renderer = new CairoRenderer();
+    CairoRenderContext *ctx = renderer->createContext();
+    ctx->setPdfTarget (filename);
+    bool ret = renderer->setupDocument(ctx, doc);
+    if (ret) {
+        renderer->renderItem(ctx, base);
+        ret = ctx->finish();
+    }
+
+    /* Release arena */
+    sp_item_invoke_hide(base, dkey);
+    nr_arena_item_unref(root);
+    nr_object_unref((NRObject *) arena);
+/* end */
+    renderer->destroyContext(ctx);
+    delete renderer;
+
+    return ret;
+}
+
+
+/**
+    \brief  This function calls the output module with the filename
+       \param  mod   unused
+       \param  doc   Document to be saved
+    \param  uri   Filename to save to (probably will end in .png)
+
+       The most interesting thing that this function does is just attach
+       an '>' on the front of the filename.  This is the syntax used to
+       tell the printing system to save to file.
+*/
+void
+CairoRendererPdfOutput::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)
+{
+    gchar * final_name;
+    final_name = g_strdup_printf("> %s", uri);
+    bool ret = pdf_render_document_to_file(doc, final_name);
+    g_free(final_name);
+
+    if (!ret)
+        throw Inkscape::Extension::Output::save_failed();
+
+       return;
+}
+
+/**
+       \brief   A function allocate a copy of this function.
+
+       This is the definition of Cairo PDF out.  This function just
+       calls the extension system with the memory allocated XML that
+       describes the data.
+*/
+void
+CairoRendererPdfOutput::init (void)
+{
+       Inkscape::Extension::build_from_mem(
+               "<inkscape-extension>\n"
+            "<name>Cairo PDF Output (experimental)</name>\n"
+                       "<id>org.inkscape.output.pdf.cairorenderer</id>\n"
+                       "<output>\n"
+                               "<extension>.pdf</extension>\n"
+                               "<mimetype>application/pdf</mimetype>\n"
+                               "<filetypename>Cairo PDF experimental (*.pdf)</filetypename>\n"
+                               "<filetypetooltip>PDF File</filetypetooltip>\n"
+                       "</output>\n"
+               "</inkscape-extension>", new CairoRendererPdfOutput());
+
+       return;
+}
+
+} } }  /* namespace Inkscape, Extension, Internal */
+
+#endif /* HAVE_CAIRO_PDF */
index d7d5a6681349e76ead8effbba4ec8cd11e44d062..1c18519a0a63ec135330e924b96c167872749874 100644 (file)
@@ -1,50 +1,50 @@
-/*\r
- * A quick hack to use the Cairo renderer to write out a file.  This\r
- * then makes 'save as...' PDF.\r
- *\r
- * Authors:\r
- *   Ted Gould <ted@gould.cx>\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2004-2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifndef EXTENSION_INTERNAL_CAIRO_RENDERER_PDF_OUT_H\r
-#define EXTENSION_INTERNAL_CAIRO_RENDERER_PDF_OUT_H\r
-\r
-#include "extension/implementation/implementation.h"\r
-\r
-#ifdef HAVE_CAIRO_PDF\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-class CairoRendererPdfOutput : Inkscape::Extension::Implementation::Implementation {\r
-\r
-public:\r
-    bool check(Inkscape::Extension::Extension *module);\r
-    void save(Inkscape::Extension::Output *mod,\r
-              SPDocument *doc,\r
-              gchar const *uri);\r
-    static void init();\r
-};\r
-\r
-} } }  /* namespace Inkscape, Extension, Internal */\r
-\r
-#endif /* HAVE_CAIRO_PDF */\r
-\r
-#endif /* !EXTENSION_INTERNAL_CAIRO_RENDERER_PDF_OUT_H */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
+/*
+ * A quick hack to use the Cairo renderer to write out a file.  This
+ * then makes 'save as...' PDF.
+ *
+ * Authors:
+ *   Ted Gould <ted@gould.cx>
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2004-2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef EXTENSION_INTERNAL_CAIRO_RENDERER_PDF_OUT_H
+#define EXTENSION_INTERNAL_CAIRO_RENDERER_PDF_OUT_H
+
+#include "extension/implementation/implementation.h"
+
+#ifdef HAVE_CAIRO_PDF
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class CairoRendererPdfOutput : Inkscape::Extension::Implementation::Implementation {
+
+public:
+    bool check(Inkscape::Extension::Extension *module);
+    void save(Inkscape::Extension::Output *mod,
+              SPDocument *doc,
+              gchar const *uri);
+    static void init();
+};
+
+} } }  /* namespace Inkscape, Extension, Internal */
+
+#endif /* HAVE_CAIRO_PDF */
+
+#endif /* !EXTENSION_INTERNAL_CAIRO_RENDERER_PDF_OUT_H */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index a39d1fb1dffe6dcf14baaf0b8bd8d96c85414560..b9d65f50cd80409f11549dc44f2dac777b70dd7b 100644 (file)
-/** \file\r
- * Enhanced Metafile Input and Output.\r
- */\r
-/*\r
- * Authors:\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-/*\r
- * References:\r
- *  - How to Create & Play Enhanced Metafiles in Win32\r
- *      http://support.microsoft.com/kb/q145999/\r
- *  - INFO: Windows Metafile Functions & Aldus Placeable Metafiles\r
- *      http://support.microsoft.com/kb/q66949/\r
- *  - Metafile Functions\r
- *      http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp\r
- *  - Metafile Structures\r
- *      http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp\r
- */\r
-\r
-#ifdef WIN32\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-#include "win32.h"\r
-#include "emf-win32-print.h"\r
-#include "emf-win32-inout.h"\r
-#include "inkscape.h"\r
-#include "sp-path.h"\r
-#include "style.h"\r
-#include "color.h"\r
-#include "display/curve.h"\r
-#include "libnr/n-art-bpath.h"\r
-#include "libnr/nr-point-matrix-ops.h"\r
-#include "gtk/gtk.h"\r
-#include "print.h"\r
-#include "glibmm/i18n.h"\r
-#include "extension/extension.h"\r
-#include "extension/system.h"\r
-#include "extension/print.h"\r
-#include "extension/db.h"\r
-#include "extension/output.h"\r
-#include "document.h"\r
-#include "display/nr-arena.h"\r
-#include "display/nr-arena-item.h"\r
-\r
-#include "libnr/nr-rect.h"\r
-#include "libnr/nr-matrix.h"\r
-#include "libnr/nr-pixblock.h"\r
-\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#include <vector>\r
-#include <string>\r
-\r
-#include "io/sys.h"\r
-\r
-#include "unit-constants.h"\r
-\r
-#include "clear-n_.h"\r
-\r
-\r
-#define PRINT_EMF_WIN32 "org.inkscape.print.emf.win32"\r
-\r
-#ifndef PS_JOIN_MASK\r
-#define PS_JOIN_MASK (PS_JOIN_BEVEL|PS_JOIN_MITER|PS_JOIN_ROUND)\r
-#endif\r
-\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-\r
-EmfWin32::EmfWin32 (void) // The null constructor\r
-{\r
-    return;\r
-}\r
-\r
-\r
-EmfWin32::~EmfWin32 (void) //The destructor\r
-{\r
-    return;\r
-}\r
-\r
-\r
-bool\r
-EmfWin32::check (Inkscape::Extension::Extension * module)\r
-{\r
-    if (NULL == Inkscape::Extension::db.get(PRINT_EMF_WIN32))\r
-        return FALSE;\r
-    return TRUE;\r
-}\r
-\r
-\r
-static void\r
-emf_print_document_to_file(SPDocument *doc, gchar const *filename)\r
-{\r
-    Inkscape::Extension::Print *mod;\r
-    SPPrintContext context;\r
-    gchar const *oldconst;\r
-    gchar *oldoutput;\r
-    unsigned int ret;\r
-\r
-    sp_document_ensure_up_to_date(doc);\r
-\r
-    mod = Inkscape::Extension::get_print(PRINT_EMF_WIN32);\r
-    oldconst = mod->get_param_string("destination");\r
-    oldoutput = g_strdup(oldconst);\r
-    mod->set_param_string("destination", (gchar *)filename);\r
-\r
-/* Start */\r
-    context.module = mod;\r
-    /* fixme: This has to go into module constructor somehow */\r
-    /* Create new arena */\r
-    mod->base = SP_ITEM(sp_document_root(doc));\r
-    mod->arena = NRArena::create();\r
-    mod->dkey = sp_item_display_key_new(1);\r
-    mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);\r
-    /* Print document */\r
-    ret = mod->begin(doc);\r
-    if (ret) {\r
-        throw Inkscape::Extension::Output::save_failed();\r
-    }\r
-    sp_item_invoke_print(mod->base, &context);\r
-    ret = mod->finish();\r
-    /* Release arena */\r
-    sp_item_invoke_hide(mod->base, mod->dkey);\r
-    mod->base = NULL;\r
-    nr_arena_item_unref(mod->root);\r
-    mod->root = NULL;\r
-    nr_object_unref((NRObject *) mod->arena);\r
-    mod->arena = NULL;\r
-/* end */\r
-\r
-    mod->set_param_string("destination", oldoutput);\r
-    g_free(oldoutput);\r
-\r
-    return;\r
-}\r
-\r
-\r
-void\r
-EmfWin32::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)\r
-{\r
-    Inkscape::Extension::Extension * ext;\r
-\r
-    ext = Inkscape::Extension::db.get(PRINT_EMF_WIN32);\r
-    if (ext == NULL)\r
-        return;\r
-\r
-//    bool old_textToPath  = ext->get_param_bool("textToPath");\r
-//    bool new_val         = mod->get_param_bool("textToPath");\r
-//    ext->set_param_bool("textToPath", new_val);\r
-\r
-    gchar * final_name;\r
-    final_name = g_strdup_printf("%s", uri);\r
-    emf_print_document_to_file(doc, final_name);\r
-    g_free(final_name);\r
-\r
-//    ext->set_param_bool("textToPath", old_textToPath);\r
-\r
-    return;\r
-}\r
-\r
-\r
-\r
-typedef struct {\r
-    int type;\r
-    ENHMETARECORD *lpEMFR;\r
-} EMF_OBJECT, *PEMF_OBJECT;\r
-\r
-typedef struct emf_callback_data {\r
-    Glib::ustring *outsvg;\r
-    Glib::ustring *path;\r
-    struct SPStyle style;\r
-    bool stroke_set;\r
-    bool fill_set;\r
-    double xDPI, yDPI;\r
-\r
-    SIZEL sizeWnd;\r
-    SIZEL sizeView;\r
-    float PixelsX;\r
-    float PixelsY;\r
-    float MMX;\r
-    float MMY;\r
-    float dwInchesX;\r
-    float dwInchesY;\r
-    POINTL winorg;\r
-    POINTL vieworg;\r
-    double ScaleX, ScaleY;\r
-\r
-    int n_obj;\r
-    PEMF_OBJECT emf_obj;\r
-} EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;\r
-\r
-\r
-static void\r
-output_style(PEMF_CALLBACK_DATA d, int iType)\r
-{\r
-    SVGOStringStream tmp_style;\r
-    char tmp[1024] = {0};\r
-\r
-    *(d->outsvg) += "\n\tstyle=\"";\r
-    if (iType == EMR_STROKEPATH || !d->fill_set) {\r
-        tmp_style << "fill:none;";\r
-    } else {\r
-        float rgb[3];\r
-        sp_color_get_rgb_floatv( &(d->style.fill.value.color), rgb );\r
-        snprintf(tmp, 1023,\r
-                 "fill:#%02x%02x%02x;",\r
-                 SP_COLOR_F_TO_U(rgb[0]),\r
-                 SP_COLOR_F_TO_U(rgb[1]),\r
-                 SP_COLOR_F_TO_U(rgb[2]));\r
-        tmp_style << tmp;\r
-        snprintf(tmp, 1023,\r
-                 "fill-rule:%s;",\r
-                 d->style.fill_rule.value != 0 ? "evenodd" : "nonzero");\r
-        tmp_style << tmp;\r
-        tmp_style << "fill-opacity:1;";\r
-    }\r
-\r
-    if (iType == EMR_FILLPATH || !d->stroke_set) {\r
-        tmp_style << "stroke:none;";\r
-    } else {\r
-        float rgb[3];\r
-        sp_color_get_rgb_floatv(&(d->style.stroke.value.color), rgb);\r
-        snprintf(tmp, 1023,\r
-                 "stroke:#%02x%02x%02x;",\r
-                 SP_COLOR_F_TO_U(rgb[0]),\r
-                 SP_COLOR_F_TO_U(rgb[1]),\r
-                 SP_COLOR_F_TO_U(rgb[2]));\r
-        tmp_style << tmp;\r
-\r
-        tmp_style << "stroke-width:" <<\r
-            MAX( 0.001, d->style.stroke_width.value ) << "px;";\r
-\r
-        tmp_style << "stroke-linejoin:" <<\r
-            (d->style.stroke_linejoin.computed == 0 ? "miter" :\r
-             d->style.stroke_linejoin.computed == 1 ? "round" :\r
-             d->style.stroke_linejoin.computed == 2 ? "bevel" :\r
-             "unknown") << ";";\r
-\r
-        if (d->style.stroke_linejoin.computed == 0) {\r
-            tmp_style << "stroke-miterlimit:" <<\r
-                MAX( 0.01, d->style.stroke_miterlimit.value ) << ";";\r
-        }\r
-\r
-        if (d->style.stroke_dasharray_set &&\r
-            d->style.stroke_dash.n_dash && d->style.stroke_dash.dash)\r
-        {\r
-            tmp_style << "stroke-dasharray:";\r
-            for (int i=0; i<d->style.stroke_dash.n_dash; i++) {\r
-                if (i)\r
-                    tmp_style << ",";\r
-                tmp_style << d->style.stroke_dash.dash[i];\r
-            }\r
-            tmp_style << ";";\r
-            tmp_style << "stroke-dashoffset:0;";\r
-        } else {\r
-            tmp_style << "stroke-dasharray:none;";\r
-        }\r
-        tmp_style << "stroke-opacity:1;";\r
-    }\r
-    tmp_style << "\" ";\r
-\r
-    *(d->outsvg) += tmp_style.str().c_str();\r
-}\r
-\r
-\r
-static double\r
-pix_x_to_point(PEMF_CALLBACK_DATA d, double px)\r
-{\r
-    double tmp = px - d->winorg.x;\r
-    tmp *= (double) PX_PER_IN / d->ScaleX;\r
-    tmp += d->vieworg.x;\r
-    return tmp;\r
-}\r
-\r
-\r
-static double\r
-pix_y_to_point(PEMF_CALLBACK_DATA d, double px)\r
-{\r
-    double tmp = px - d->winorg.y;\r
-    tmp *= (double) PX_PER_IN / d->ScaleY;\r
-    tmp += d->vieworg.y;\r
-    return tmp;\r
-}\r
-\r
-\r
-static double\r
-pix_size_to_point(PEMF_CALLBACK_DATA d, double px)\r
-{\r
-    double tmp = px;\r
-    tmp *= (double) PX_PER_IN / d->ScaleX;\r
-    return tmp;\r
-}\r
-\r
-\r
-static void\r
-select_pen(PEMF_CALLBACK_DATA d, int index)\r
-{\r
-    PEMRCREATEPEN pEmr = NULL;\r
-\r
-    if (index >= 0 && index < d->n_obj)\r
-        pEmr = (PEMRCREATEPEN) d->emf_obj[index].lpEMFR;\r
-\r
-    if (!pEmr)\r
-        return;\r
-\r
-    switch (pEmr->lopn.lopnStyle) {\r
-        default:\r
-        {\r
-            d->style.stroke_dasharray_set = 0;\r
-            break;\r
-        }\r
-    }\r
-\r
-    if (pEmr->lopn.lopnWidth.x) {\r
-        d->style.stroke_width.value = pix_size_to_point( d, pEmr->lopn.lopnWidth.x );\r
-    } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)\r
-        d->style.stroke_width.value = 1.0;\r
-    }\r
-\r
-    double r, g, b;\r
-    r = SP_COLOR_U_TO_F( GetRValue(pEmr->lopn.lopnColor) );\r
-    g = SP_COLOR_U_TO_F( GetGValue(pEmr->lopn.lopnColor) );\r
-    b = SP_COLOR_U_TO_F( GetBValue(pEmr->lopn.lopnColor) );\r
-    sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );\r
-\r
-    d->style.stroke_linejoin.computed = 1;\r
-\r
-    d->stroke_set = true;\r
-}\r
-\r
-\r
-static void\r
-select_extpen(PEMF_CALLBACK_DATA d, int index)\r
-{\r
-    PEMREXTCREATEPEN pEmr = NULL;\r
-\r
-    if (index >= 0 && index < d->n_obj)\r
-        pEmr = (PEMREXTCREATEPEN) d->emf_obj[index].lpEMFR;\r
-\r
-    if (!pEmr)\r
-        return;\r
-\r
-    switch (pEmr->elp.elpPenStyle & PS_STYLE_MASK) {\r
-        case PS_USERSTYLE:\r
-        {\r
-            if (pEmr->elp.elpNumEntries) {\r
-                d->style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;\r
-                if (d->style.stroke_dash.dash)\r
-                    delete[] d->style.stroke_dash.dash;\r
-                d->style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];\r
-                for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {\r
-                    d->style.stroke_dash.dash[i] = pix_size_to_point( d, pEmr->elp.elpStyleEntry[i] );\r
-                }\r
-                d->style.stroke_dasharray_set = 1;\r
-            } else {\r
-                d->style.stroke_dasharray_set = 0;\r
-            }\r
-            break;\r
-        }\r
-        default:\r
-        {\r
-            d->style.stroke_dasharray_set = 0;\r
-            break;\r
-        }\r
-    }\r
-\r
-    switch (pEmr->elp.elpPenStyle & PS_ENDCAP_MASK) {\r
-        case PS_ENDCAP_ROUND:\r
-        {\r
-            d->style.stroke_linecap.computed = 1;\r
-            break;\r
-        }\r
-        case PS_ENDCAP_SQUARE:\r
-        {\r
-            d->style.stroke_linecap.computed = 2;\r
-            break;\r
-        }\r
-        case PS_ENDCAP_FLAT:\r
-        default:\r
-        {\r
-            d->style.stroke_linecap.computed = 0;\r
-            break;\r
-        }\r
-    }\r
-\r
-    switch (pEmr->elp.elpPenStyle & PS_JOIN_MASK) {\r
-        case PS_JOIN_BEVEL:\r
-        {\r
-            d->style.stroke_linejoin.computed = 2;\r
-            break;\r
-        }\r
-        case PS_JOIN_MITER:\r
-        {\r
-            d->style.stroke_linejoin.computed = 0;\r
-            break;\r
-        }\r
-        case PS_JOIN_ROUND:\r
-        default:\r
-        {\r
-            d->style.stroke_linejoin.computed = 1;\r
-            break;\r
-        }\r
-    }\r
-\r
-    d->style.stroke_width.value = pix_size_to_point( d, pEmr->elp.elpWidth );\r
-\r
-    double r, g, b;\r
-    r = SP_COLOR_U_TO_F( GetRValue(pEmr->elp.elpColor) );\r
-    g = SP_COLOR_U_TO_F( GetGValue(pEmr->elp.elpColor) );\r
-    b = SP_COLOR_U_TO_F( GetBValue(pEmr->elp.elpColor) );\r
-\r
-    sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );\r
-\r
-    d->stroke_set = true;\r
-}\r
-\r
-\r
-static void\r
-select_brush(PEMF_CALLBACK_DATA d, int index)\r
-{\r
-    PEMRCREATEBRUSHINDIRECT pEmr = NULL;\r
-\r
-    if (index >= 0 && index < d->n_obj)\r
-        pEmr = (PEMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;\r
-\r
-    if (!pEmr)\r
-        return;\r
-\r
-    if (pEmr->lb.lbStyle == BS_SOLID) {\r
-        double r, g, b;\r
-        r = SP_COLOR_U_TO_F( GetRValue(pEmr->lb.lbColor) );\r
-        g = SP_COLOR_U_TO_F( GetGValue(pEmr->lb.lbColor) );\r
-        b = SP_COLOR_U_TO_F( GetBValue(pEmr->lb.lbColor) );\r
-        sp_color_set_rgb_float( &(d->style.fill.value.color), r,g,b );\r
-    }\r
-\r
-    d->fill_set = true;\r
-}\r
-\r
-\r
-static void\r
-delete_object(PEMF_CALLBACK_DATA d, int index)\r
-{\r
-    if (index >= 0 && index < d->n_obj) {\r
-        d->emf_obj[index].type = 0;\r
-        if (d->emf_obj[index].lpEMFR)\r
-            free(d->emf_obj[index].lpEMFR);\r
-        d->emf_obj[index].lpEMFR = NULL;\r
-    }\r
-}\r
-\r
-\r
-static void\r
-insert_object(PEMF_CALLBACK_DATA d, int index, int type, ENHMETARECORD *pObj)\r
-{\r
-    if (index >= 0 && index < d->n_obj) {\r
-        delete_object(d, index);\r
-        d->emf_obj[index].type = type;\r
-        d->emf_obj[index].lpEMFR = pObj;\r
-    }\r
-}\r
-\r
-\r
-static int CALLBACK\r
-myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData)\r
-{\r
-    PEMF_CALLBACK_DATA d;\r
-    SVGOStringStream tmp_outsvg;\r
-    SVGOStringStream tmp_path;\r
-    SVGOStringStream tmp_str;\r
-\r
-    d = (PEMF_CALLBACK_DATA) lpData;\r
-\r
-    switch (lpEMFR->iType)\r
-    {\r
-        case EMR_HEADER:\r
-        {\r
-            ENHMETAHEADER *pEmr = (ENHMETAHEADER *) lpEMFR;\r
-            tmp_outsvg << "<svg\n";\r
-\r
-            d->xDPI = 2540;\r
-            d->yDPI = 2540;\r
-\r
-            d->PixelsX = pEmr->rclFrame.right - pEmr->rclFrame.left;\r
-            d->PixelsY = pEmr->rclFrame.bottom - pEmr->rclFrame.top;\r
-\r
-            d->MMX = d->PixelsX / 100.0;\r
-            d->MMY = d->PixelsY / 100.0;\r
-\r
-            tmp_outsvg <<\r
-                "  width=\"" << d->MMX << "mm\"\n" <<\r
-                "  height=\"" << d->MMY << "mm\">\n";\r
-\r
-            if (pEmr->nHandles) {\r
-                d->n_obj = pEmr->nHandles;\r
-                d->emf_obj = new EMF_OBJECT[d->n_obj];\r
-            } else {\r
-                d->emf_obj = NULL;\r
-            }\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYBEZIER:\r
-        {\r
-            PEMRPOLYBEZIER pEmr = (PEMRPOLYBEZIER) lpEMFR;\r
-            DWORD i,j;\r
-\r
-            if (pEmr->cptl<4)\r
-                break;\r
-\r
-            *(d->outsvg) += "    <path ";\r
-            output_style(d, EMR_STROKEPATH);\r
-            *(d->outsvg) += "\n\td=\"";\r
-\r
-            tmp_str <<\r
-                "\n\tM " <<\r
-                pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
-                pix_x_to_point( d, pEmr->aptl[0].y) << " ";\r
-\r
-            for (i=1; i<pEmr->cptl; ) {\r
-                tmp_str << "\n\tC ";\r
-                for (j=0; j<3 && i<pEmr->cptl; j++,i++) {\r
-                    tmp_str <<\r
-                        pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
-                        pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
-                }\r
-            }\r
-\r
-            *(d->outsvg) += tmp_str.str().c_str();\r
-            *(d->outsvg) += " \" /> \n";\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYGON:\r
-        {\r
-            EMRPOLYGON *pEmr = (EMRPOLYGON *) lpEMFR;\r
-            DWORD i;\r
-\r
-            if (pEmr->cptl < 2)\r
-                break;\r
-\r
-            *(d->outsvg) += "    <path ";\r
-            output_style(d, EMR_STROKEANDFILLPATH);\r
-            *(d->outsvg) += "\n\td=\"";\r
-\r
-            tmp_str <<\r
-                "\n\tM " <<\r
-                pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
-                pix_y_to_point( d, pEmr->aptl[0].y ) << " ";\r
-\r
-            for (i=1; i<pEmr->cptl; i++) {\r
-                tmp_str <<\r
-                    "\n\tL " <<\r
-                    pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
-                    pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
-            }\r
-\r
-            *(d->outsvg) += tmp_str.str().c_str();\r
-            *(d->outsvg) += " z \" /> \n";\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYLINE:\r
-        {\r
-            EMRPOLYLINE *pEmr = (EMRPOLYLINE *) lpEMFR;\r
-            DWORD i;\r
-\r
-            if (pEmr->cptl<2)\r
-                break;\r
-\r
-            *(d->outsvg) += "    <path ";\r
-            output_style(d, EMR_STROKEPATH);\r
-            *(d->outsvg) += "\n\td=\"";\r
-\r
-            tmp_str <<\r
-                "\n\tM " <<\r
-                pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<\r
-                pix_y_to_point( d, pEmr->aptl[0].y ) << " ";\r
-\r
-            for (i=1; i<pEmr->cptl; i++) {\r
-                tmp_str <<\r
-                    "\n\tL " <<\r
-                    pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
-                    pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
-            }\r
-\r
-            *(d->outsvg) += tmp_str.str().c_str();\r
-            *(d->outsvg) += " \" /> \n";\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYBEZIERTO:\r
-        {\r
-            PEMRPOLYBEZIERTO pEmr = (PEMRPOLYBEZIERTO) lpEMFR;\r
-            DWORD i,j;\r
-\r
-            for (i=0; i<pEmr->cptl;) {\r
-                tmp_path << "\n\tC ";\r
-                for (j=0; j<3 && i<pEmr->cptl; j++,i++) {\r
-                    tmp_path <<\r
-                        pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
-                        pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
-                }\r
-            }\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYLINETO:\r
-        {\r
-            PEMRPOLYLINETO pEmr = (PEMRPOLYLINETO) lpEMFR;\r
-            DWORD i;\r
-\r
-            for (i=0; i<pEmr->cptl;i++) {\r
-                tmp_path <<\r
-                    "\n\tL " <<\r
-                    pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<\r
-                    pix_y_to_point( d, pEmr->aptl[i].y ) << " ";\r
-            }\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYPOLYLINE:\r
-            break;\r
-        case EMR_POLYPOLYGON:\r
-            break;\r
-        case EMR_SETWINDOWEXTEX:\r
-        {\r
-            PEMRSETWINDOWEXTEX pEmr = (PEMRSETWINDOWEXTEX) lpEMFR;\r
-\r
-            d->sizeWnd = pEmr->szlExtent;\r
-            d->PixelsX = d->sizeWnd.cx;\r
-            d->PixelsY = d->sizeWnd.cy;\r
-\r
-            d->ScaleX = d->xDPI / (100*d->MMX / d->PixelsX);\r
-            d->ScaleY = d->yDPI / (100*d->MMY / d->PixelsY);\r
-\r
-            break;\r
-        }\r
-        case EMR_SETWINDOWORGEX:\r
-        {\r
-            PEMRSETWINDOWORGEX pEmr = (PEMRSETWINDOWORGEX) lpEMFR;\r
-            d->winorg = pEmr->ptlOrigin;\r
-            break;\r
-        }\r
-        case EMR_SETVIEWPORTEXTEX:\r
-        {\r
-            PEMRSETVIEWPORTEXTEX pEmr = (PEMRSETVIEWPORTEXTEX) lpEMFR;\r
-\r
-            d->sizeView = pEmr->szlExtent;\r
-\r
-            if (d->sizeWnd.cx && d->sizeWnd.cy) {\r
-                HDC hScreenDC = GetDC( NULL );\r
-\r
-                float scrPixelsX = (float)GetDeviceCaps( hScreenDC, HORZRES );\r
-                float scrPixelsY = (float)GetDeviceCaps( hScreenDC, VERTRES );\r
-                float scrMMX = (float)GetDeviceCaps( hScreenDC, HORZSIZE );\r
-                float scrMMY = (float)GetDeviceCaps( hScreenDC, VERTSIZE );\r
-\r
-                ReleaseDC( NULL, hScreenDC );\r
-\r
-                d->dwInchesX = d->sizeView.cx / (25.4f*scrPixelsX/scrMMX);\r
-                d->dwInchesY = d->sizeView.cy / (25.4f*scrPixelsY/scrMMY);\r
-                d->xDPI = d->sizeWnd.cx / d->dwInchesX;\r
-                d->yDPI = d->sizeWnd.cy / d->dwInchesY;\r
-\r
-                if (1) {\r
-                    d->xDPI = 2540;\r
-                    d->yDPI = 2540;\r
-                    d->dwInchesX = d->PixelsX / d->xDPI;\r
-                    d->dwInchesY = d->PixelsY / d->yDPI;\r
-                    d->ScaleX = d->xDPI;\r
-                    d->ScaleY = d->yDPI;\r
-                }\r
-\r
-                d->MMX = d->dwInchesX * MM_PER_IN;\r
-                d->MMY = d->dwInchesY * MM_PER_IN;\r
-            }\r
-\r
-            break;\r
-        }\r
-        case EMR_SETVIEWPORTORGEX:\r
-        {\r
-            PEMRSETVIEWPORTORGEX pEmr = (PEMRSETVIEWPORTORGEX) lpEMFR;\r
-            d->vieworg = pEmr->ptlOrigin;\r
-            break;\r
-        }\r
-        case EMR_SETBRUSHORGEX:\r
-            break;\r
-        case EMR_EOF:\r
-        {\r
-            tmp_outsvg << "</svg>\n";\r
-            break;\r
-        }\r
-        case EMR_SETPIXELV:\r
-            break;\r
-        case EMR_SETMAPPERFLAGS:\r
-            break;\r
-        case EMR_SETMAPMODE:\r
-            break;\r
-        case EMR_SETBKMODE:\r
-            break;\r
-        case EMR_SETPOLYFILLMODE:\r
-        {\r
-            PEMRSETPOLYFILLMODE pEmr = (PEMRSETPOLYFILLMODE) lpEMFR;\r
-            d->style.fill_rule.value =\r
-                (pEmr->iMode == WINDING ? 0 :\r
-                 pEmr->iMode == ALTERNATE ? 1 : 0);\r
-            break;\r
-        }\r
-        case EMR_SETROP2:\r
-            break;\r
-        case EMR_SETSTRETCHBLTMODE:\r
-            break;\r
-        case EMR_SETTEXTALIGN:\r
-            break;\r
-        case EMR_SETCOLORADJUSTMENT:\r
-            break;\r
-        case EMR_SETTEXTCOLOR:\r
-            break;\r
-        case EMR_SETBKCOLOR:\r
-            break;\r
-        case EMR_OFFSETCLIPRGN:\r
-            break;\r
-        case EMR_MOVETOEX:\r
-        {\r
-            PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR;\r
-            tmp_path <<\r
-                "\n\tM " <<\r
-                pix_x_to_point( d, pEmr->ptl.x ) << " " <<\r
-                pix_y_to_point( d, pEmr->ptl.y ) << " ";\r
-            break;\r
-        }\r
-        case EMR_SETMETARGN:\r
-            break;\r
-        case EMR_EXCLUDECLIPRECT:\r
-            break;\r
-        case EMR_INTERSECTCLIPRECT:\r
-            break;\r
-        case EMR_SCALEVIEWPORTEXTEX:\r
-            break;\r
-        case EMR_SCALEWINDOWEXTEX:\r
-            break;\r
-        case EMR_SAVEDC:\r
-            break;\r
-        case EMR_RESTOREDC:\r
-            break;\r
-        case EMR_SETWORLDTRANSFORM:\r
-            break;\r
-        case EMR_MODIFYWORLDTRANSFORM:\r
-            break;\r
-        case EMR_SELECTOBJECT:\r
-        {\r
-            PEMRSELECTOBJECT pEmr = (PEMRSELECTOBJECT) lpEMFR;\r
-            unsigned int index = pEmr->ihObject;\r
-\r
-            if (index >= ENHMETA_STOCK_OBJECT) {\r
-                index -= ENHMETA_STOCK_OBJECT;\r
-                switch (index) {\r
-                    case NULL_BRUSH:\r
-                        d->fill_set = false;\r
-                        break;\r
-                    case BLACK_BRUSH:\r
-                    case DKGRAY_BRUSH:\r
-                    case GRAY_BRUSH:\r
-                    case LTGRAY_BRUSH:\r
-                    case WHITE_BRUSH:\r
-                    {\r
-                        float val = 0;\r
-                        switch (index) {\r
-                            case BLACK_BRUSH:\r
-                                val = 0.0 / 255.0;\r
-                                break;\r
-                            case DKGRAY_BRUSH:\r
-                                val = 64.0 / 255.0;\r
-                                break;\r
-                            case GRAY_BRUSH:\r
-                                val = 128.0 / 255.0;\r
-                                break;\r
-                            case LTGRAY_BRUSH:\r
-                                val = 192.0 / 255.0;\r
-                                break;\r
-                            case WHITE_BRUSH:\r
-                                val = 255.0 / 255.0;\r
-                                break;\r
-                        }\r
-                        sp_color_set_rgb_float( &(d->style.fill.value.color), val,val,val );\r
-\r
-                        d->fill_set = true;\r
-                        break;\r
-                    }\r
-                    case NULL_PEN:\r
-                        d->stroke_set = false;\r
-                        break;\r
-                    case BLACK_PEN:\r
-                    case WHITE_PEN:\r
-                    {\r
-                        float val = index == BLACK_PEN ? 0 : 1;\r
-                        d->style.stroke_dasharray_set = 0;\r
-                        d->style.stroke_width.value = 1.0;\r
-                        sp_color_set_rgb_float( &(d->style.stroke.value.color), val,val,val );\r
-\r
-                        d->stroke_set = true;\r
-\r
-                        break;\r
-                    }\r
-                }\r
-            } else {\r
-                if (index >= 0 && index < d->n_obj) {\r
-                    switch (d->emf_obj[index].type)\r
-                    {\r
-                        case EMR_CREATEPEN:\r
-                            select_pen(d, index);\r
-                            break;\r
-                        case EMR_CREATEBRUSHINDIRECT:\r
-                            select_brush(d, index);\r
-                            break;\r
-                        case EMR_EXTCREATEPEN:\r
-                            select_extpen(d, index);\r
-                            break;\r
-                    }\r
-                }\r
-            }\r
-            break;\r
-        }\r
-        case EMR_CREATEPEN:\r
-        {\r
-            PEMRCREATEPEN pEmr = (PEMRCREATEPEN) lpEMFR;\r
-            int index = pEmr->ihPen;\r
-\r
-            EMRCREATEPEN *pPen =\r
-                (EMRCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) );\r
-            pPen->lopn = pEmr->lopn;\r
-            insert_object(d, index, EMR_CREATEPEN, (ENHMETARECORD *) pPen);\r
-\r
-            break;\r
-        }\r
-        case EMR_CREATEBRUSHINDIRECT:\r
-        {\r
-            PEMRCREATEBRUSHINDIRECT pEmr = (PEMRCREATEBRUSHINDIRECT) lpEMFR;\r
-            int index = pEmr->ihBrush;\r
-\r
-            EMRCREATEBRUSHINDIRECT *pBrush =\r
-                (EMRCREATEBRUSHINDIRECT *) malloc( sizeof(EMRCREATEBRUSHINDIRECT) );\r
-            pBrush->lb = pEmr->lb;\r
-            insert_object(d, index, EMR_CREATEBRUSHINDIRECT, (ENHMETARECORD *) pBrush);\r
-\r
-            break;\r
-        }\r
-        case EMR_DELETEOBJECT:\r
-            break;\r
-        case EMR_ANGLEARC:\r
-            break;\r
-        case EMR_ELLIPSE:\r
-            break;\r
-        case EMR_RECTANGLE:\r
-            break;\r
-        case EMR_ROUNDRECT:\r
-            break;\r
-        case EMR_ARC:\r
-            break;\r
-        case EMR_CHORD:\r
-            break;\r
-        case EMR_PIE:\r
-            break;\r
-        case EMR_SELECTPALETTE:\r
-            break;\r
-        case EMR_CREATEPALETTE:\r
-            break;\r
-        case EMR_SETPALETTEENTRIES:\r
-            break;\r
-        case EMR_RESIZEPALETTE:\r
-            break;\r
-        case EMR_REALIZEPALETTE:\r
-            break;\r
-        case EMR_EXTFLOODFILL:\r
-            break;\r
-        case EMR_LINETO:\r
-        {\r
-            PEMRLINETO pEmr = (PEMRLINETO) lpEMFR;\r
-            tmp_path <<\r
-                "\n\tL " <<\r
-                pix_x_to_point( d, pEmr->ptl.x ) << " " <<\r
-                pix_y_to_point( d, pEmr->ptl.y ) << " ";\r
-            break;\r
-        }\r
-        case EMR_ARCTO:\r
-            break;\r
-        case EMR_POLYDRAW:\r
-            break;\r
-        case EMR_SETARCDIRECTION:\r
-            break;\r
-        case EMR_SETMITERLIMIT:\r
-        {\r
-            PEMRSETMITERLIMIT pEmr = (PEMRSETMITERLIMIT) lpEMFR;\r
-            d->style.stroke_miterlimit.value = pix_size_to_point( d, pEmr->eMiterLimit );\r
-\r
-            if (d->style.stroke_miterlimit.value < 1)\r
-                d->style.stroke_miterlimit.value = 1.0;\r
-\r
-            break;\r
-        }\r
-        case EMR_BEGINPATH:\r
-        {\r
-            tmp_path << " d=\"";\r
-            *(d->path) = "";\r
-            break;\r
-        }\r
-        case EMR_ENDPATH:\r
-        {\r
-            tmp_path << "\"";\r
-            break;\r
-        }\r
-        case EMR_CLOSEFIGURE:\r
-        {\r
-            tmp_path << "\n\tz";\r
-            break;\r
-        }\r
-        case EMR_FILLPATH:\r
-        case EMR_STROKEANDFILLPATH:\r
-        case EMR_STROKEPATH:\r
-        {\r
-            *(d->outsvg) += "    <path ";\r
-            output_style(d, lpEMFR->iType);\r
-            *(d->outsvg) += "\n\t";\r
-            *(d->outsvg) += *(d->path);\r
-            *(d->outsvg) += " /> \n";\r
-            break;\r
-        }\r
-        case EMR_FLATTENPATH:\r
-            break;\r
-        case EMR_WIDENPATH:\r
-            break;\r
-        case EMR_SELECTCLIPPATH:\r
-            break;\r
-        case EMR_ABORTPATH:\r
-            break;\r
-        case EMR_GDICOMMENT:\r
-            break;\r
-        case EMR_FILLRGN:\r
-            break;\r
-        case EMR_FRAMERGN:\r
-            break;\r
-        case EMR_INVERTRGN:\r
-            break;\r
-        case EMR_PAINTRGN:\r
-            break;\r
-        case EMR_EXTSELECTCLIPRGN:\r
-            break;\r
-        case EMR_BITBLT:\r
-            break;\r
-        case EMR_STRETCHBLT:\r
-            break;\r
-        case EMR_MASKBLT:\r
-            break;\r
-        case EMR_PLGBLT:\r
-            break;\r
-        case EMR_SETDIBITSTODEVICE:\r
-            break;\r
-        case EMR_STRETCHDIBITS:\r
-            break;\r
-        case EMR_EXTCREATEFONTINDIRECTW:\r
-            break;\r
-        case EMR_EXTTEXTOUTA:\r
-            break;\r
-        case EMR_EXTTEXTOUTW:\r
-            break;\r
-        case EMR_POLYBEZIER16:\r
-        {\r
-            PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR;\r
-            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
-            DWORD i,j;\r
-\r
-            if (pEmr->cpts<4)\r
-                break;\r
-\r
-            *(d->outsvg) += "    <path ";\r
-            output_style(d, EMR_STROKEPATH);\r
-            *(d->outsvg) += "\n\td=\"";\r
-\r
-            tmp_str <<\r
-                "\n\tM " <<\r
-                pix_x_to_point( d, apts[0].x ) << " " <<\r
-                pix_y_to_point( d, apts[0].y ) << " ";\r
-\r
-            for (i=1; i<pEmr->cpts; ) {\r
-                tmp_str << "\n\tC ";\r
-                for (j=0; j<3 && i<pEmr->cpts; j++,i++) {\r
-                    tmp_str <<\r
-                        pix_x_to_point( d, apts[i].x ) << " " <<\r
-                        pix_y_to_point( d, apts[i].y ) << " ";\r
-                }\r
-            }\r
-\r
-            *(d->outsvg) += tmp_str.str().c_str();\r
-            *(d->outsvg) += " \" /> \n";\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYGON16:\r
-        {\r
-            PEMRPOLYGON16 pEmr = (PEMRPOLYGON16) lpEMFR;\r
-            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
-            unsigned int i;\r
-\r
-            *(d->outsvg) += "<path ";\r
-            output_style(d, EMR_STROKEANDFILLPATH);\r
-            *(d->outsvg) += "\n\td=\"";\r
-\r
-            // skip the first point?\r
-            tmp_path << "\n\tM " <<\r
-                pix_x_to_point( d, apts[1].x ) << " " <<\r
-                pix_y_to_point( d, apts[1].y ) << " ";\r
-\r
-            for (i=2; i<pEmr->cpts; i++) {\r
-                tmp_path << "\n\tL " <<\r
-                    pix_x_to_point( d, apts[i].x ) << " " <<\r
-                    pix_y_to_point( d, apts[i].y ) << " ";\r
-            }\r
-\r
-            *(d->outsvg) += tmp_path.str().c_str();\r
-            *(d->outsvg) += " z \" /> \n";\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYLINE16:\r
-        {\r
-            EMRPOLYLINE16 *pEmr = (EMRPOLYLINE16 *) lpEMFR;\r
-            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
-            DWORD i;\r
-\r
-            if (pEmr->cpts<2)\r
-                break;\r
-\r
-            *(d->outsvg) += "    <path ";\r
-            output_style(d, EMR_STROKEPATH);\r
-            *(d->outsvg) += "\n\td=\"";\r
-\r
-            tmp_str <<\r
-                "\n\tM " <<\r
-                pix_x_to_point( d, apts[0].x ) << " " <<\r
-                pix_y_to_point( d, apts[0].y ) << " ";\r
-\r
-            for (i=1; i<pEmr->cpts; i++) {\r
-                tmp_str <<\r
-                    "\n\tL " <<\r
-                    pix_x_to_point( d, apts[i].x ) << " " <<\r
-                    pix_y_to_point( d, apts[i].y ) << " ";\r
-            }\r
-\r
-            *(d->outsvg) += tmp_str.str().c_str();\r
-            *(d->outsvg) += " \" /> \n";\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYBEZIERTO16:\r
-        {\r
-            PEMRPOLYBEZIERTO16 pEmr = (PEMRPOLYBEZIERTO16) lpEMFR;\r
-            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
-            DWORD i,j;\r
-\r
-            for (i=0; i<pEmr->cpts;) {\r
-                tmp_path << "\n\tC ";\r
-                for (j=0; j<3 && i<pEmr->cpts; j++,i++) {\r
-                    tmp_path <<\r
-                        pix_x_to_point( d, apts[i].x ) << " " <<\r
-                        pix_y_to_point( d, apts[i].y ) << " ";\r
-                }\r
-            }\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYLINETO16:\r
-        {\r
-            PEMRPOLYLINETO16 pEmr = (PEMRPOLYLINETO16) lpEMFR;\r
-            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?\r
-            DWORD i;\r
-\r
-            for (i=0; i<pEmr->cpts;i++) {\r
-                tmp_path <<\r
-                    "\n\tL " <<\r
-                    pix_x_to_point( d, apts[i].x ) << " " <<\r
-                    pix_y_to_point( d, apts[i].y ) << " ";\r
-            }\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYPOLYLINE16:\r
-            break;\r
-        case EMR_POLYPOLYGON16:\r
-        {\r
-            PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR;\r
-            unsigned int n, i, j;\r
-\r
-            *(d->outsvg) += "<path ";\r
-            output_style(d, EMR_STROKEANDFILLPATH);\r
-            *(d->outsvg) += "\n\td=\"";\r
-\r
-            i = pEmr->nPolys-1; // ???\r
-            for (n=0; n<pEmr->nPolys /*&& i<pEmr->cpts*/; n++) {\r
-                SVGOStringStream poly_path;\r
-\r
-                poly_path << "\n\tM " <<\r
-                    pix_x_to_point( d, pEmr->apts[i].x ) << " " <<\r
-                    pix_y_to_point( d, pEmr->apts[i].y ) << " ";\r
-                i++;\r
-\r
-                for (j=1; j<pEmr->aPolyCounts[n] /*&& i<pEmr->cpts*/; j++) {\r
-                    poly_path << "\n\tL " <<\r
-                        pix_x_to_point( d, pEmr->apts[i].x ) << " " <<\r
-                        pix_y_to_point( d, pEmr->apts[i].y ) << " ";\r
-                    i++;\r
-                }\r
-\r
-                *(d->outsvg) += poly_path.str().c_str();\r
-                *(d->outsvg) += " z \n";\r
-            }\r
-\r
-            *(d->outsvg) += " \" /> \n";\r
-            break;\r
-        }\r
-        case EMR_POLYDRAW16:\r
-            break;\r
-        case EMR_CREATEMONOBRUSH:\r
-            break;\r
-        case EMR_CREATEDIBPATTERNBRUSHPT:\r
-            break;\r
-        case EMR_EXTCREATEPEN:\r
-        {\r
-            PEMREXTCREATEPEN pEmr = (PEMREXTCREATEPEN) lpEMFR;\r
-            int index = pEmr->ihPen;\r
-\r
-            EMREXTCREATEPEN *pPen =\r
-                (EMREXTCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) +\r
-                                            sizeof(DWORD) * pEmr->elp.elpNumEntries );\r
-            pPen->ihPen = pEmr->ihPen;\r
-            pPen->offBmi = pEmr->offBmi;\r
-            pPen->cbBmi = pEmr->cbBmi;\r
-            pPen->offBits = pEmr->offBits;\r
-            pPen->cbBits = pEmr->cbBits;\r
-            pPen->elp = pEmr->elp;\r
-            for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {\r
-                pPen->elp.elpStyleEntry[i] = pEmr->elp.elpStyleEntry[i];\r
-            }\r
-            insert_object(d, index, EMR_EXTCREATEPEN, (ENHMETARECORD *) pPen);\r
-\r
-            break;\r
-        }\r
-        case EMR_POLYTEXTOUTA:\r
-            break;\r
-        case EMR_POLYTEXTOUTW:\r
-            break;\r
-        case EMR_SETICMMODE:\r
-            break;\r
-        case EMR_CREATECOLORSPACE:\r
-            break;\r
-        case EMR_SETCOLORSPACE:\r
-            break;\r
-        case EMR_DELETECOLORSPACE:\r
-            break;\r
-        case EMR_GLSRECORD:\r
-            break;\r
-        case EMR_GLSBOUNDEDRECORD:\r
-            break;\r
-        case EMR_PIXELFORMAT:\r
-            break;\r
-    }\r
-\r
-    *(d->outsvg) += tmp_outsvg.str().c_str();\r
-    *(d->path) += tmp_path.str().c_str();\r
-\r
-    return 1;\r
-}\r
-\r
-\r
-// Aldus Placeable Header ===================================================\r
-// Since we are a 32bit app, we have to be sure this structure compiles to\r
-// be identical to a 16 bit app's version. To do this, we use the #pragma\r
-// to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT\r
-// for the bbox rectangle.\r
-#pragma pack( push )\r
-#pragma pack( 2 )\r
-typedef struct\r
-{\r
-       DWORD           dwKey;\r
-       WORD            hmf;\r
-       SMALL_RECT      bbox;\r
-       WORD            wInch;\r
-       DWORD           dwReserved;\r
-       WORD            wCheckSum;\r
-} APMHEADER, *PAPMHEADER;\r
-#pragma pack( pop )\r
-\r
-\r
-SPDocument *\r
-EmfWin32::open( Inkscape::Extension::Input *mod, const gchar *uri )\r
-{\r
-    EMF_CALLBACK_DATA d = {0};\r
-\r
-    gsize bytesRead = 0;\r
-    gsize bytesWritten = 0;\r
-    GError* error = NULL;\r
-    gchar *local_fn =\r
-        g_filename_from_utf8( uri, -1,  &bytesRead,  &bytesWritten, &error );\r
-\r
-    if (local_fn == NULL) {\r
-        return NULL;\r
-    }\r
-\r
-    d.outsvg = new Glib::ustring("");\r
-    d.path = new Glib::ustring("");\r
-\r
-    CHAR *ansi_uri = (CHAR *) local_fn;\r
-    gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );\r
-    WCHAR *unicode_uri = (WCHAR *) unicode_fn;\r
-\r
-    // Try open as Enhanced Metafile\r
-    HENHMETAFILE hemf;\r
-    if (PrintWin32::is_os_wide())\r
-        hemf = GetEnhMetaFileW(unicode_uri);\r
-    else\r
-        hemf = GetEnhMetaFileA(ansi_uri);\r
-\r
-    if (!hemf) {\r
-        // Try open as Windows Metafile\r
-        HMETAFILE hmf;\r
-        if (PrintWin32::is_os_wide())\r
-            hmf = GetMetaFileW(unicode_uri);\r
-        else\r
-            hmf = GetMetaFileA(ansi_uri);\r
-\r
-       METAFILEPICT mp;\r
-       HDC hDC;\r
-\r
-        if (!hmf) {\r
-            if (PrintWin32::is_os_wide()) {\r
-                WCHAR szTemp[MAX_PATH];\r
-\r
-                DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );\r
-                if (dw) {\r
-                    hmf = GetMetaFileW( szTemp );\r
-                }\r
-            } else {\r
-                CHAR szTemp[MAX_PATH];\r
-\r
-                DWORD dw = GetShortPathNameA( ansi_uri, szTemp, MAX_PATH );\r
-                if (dw) {\r
-                    hmf = GetMetaFileA( szTemp );\r
-                }\r
-            }\r
-        }\r
-\r
-        if (hmf) {\r
-            DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL );\r
-            if (nSize) {\r
-                BYTE *lpvData = new BYTE[nSize];\r
-                if (lpvData) {\r
-                    DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData );\r
-                    if (dw) {\r
-                        // Fill out a METAFILEPICT structure\r
-                        mp.mm = MM_ANISOTROPIC;\r
-                        mp.xExt = 1000;\r
-                        mp.yExt = 1000;\r
-                        mp.hMF = NULL;\r
-                        // Get a reference DC\r
-                        hDC = GetDC( NULL );\r
-                        // Make an enhanced metafile from the windows metafile\r
-                        hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp );\r
-                        // Clean up\r
-                        ReleaseDC( NULL, hDC );\r
-                    }\r
-                    delete[] lpvData;\r
-                }\r
-                DeleteMetaFile( hmf );\r
-            }\r
-        } else {\r
-            // Try open as Aldus Placeable Metafile\r
-            HANDLE hFile;\r
-            if (PrintWin32::is_os_wide())\r
-                hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
-            else\r
-                hFile = CreateFileA( ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
-            if (hFile != INVALID_HANDLE_VALUE) {\r
-                DWORD nSize = GetFileSize( hFile, NULL );\r
-                if (nSize) {\r
-                    BYTE *lpvData = new BYTE[nSize];\r
-                    if (lpvData) {\r
-                        DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL );\r
-                        if (dw) {\r
-                            if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) {\r
-                                // Fill out a METAFILEPICT structure\r
-                                mp.mm = MM_ANISOTROPIC;\r
-                                mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left;\r
-                                mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);\r
-                                mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top;\r
-                                mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);\r
-                                mp.hMF = NULL;\r
-                                // Get a reference DC\r
-                                hDC = GetDC( NULL );\r
-                                // Create an enhanced metafile from the bits\r
-                                hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp );\r
-                                // Clean up\r
-                                ReleaseDC( NULL, hDC );\r
-                            }\r
-                        }\r
-                        delete[] lpvData;\r
-                    }\r
-                }\r
-                CloseHandle( hFile );\r
-            }\r
-        }\r
-    }\r
-\r
-    if (!hemf || !d.outsvg || !d.path) {\r
-        if (d.outsvg)\r
-            delete d.outsvg;\r
-        if (d.path)\r
-            delete d.path;\r
-        if  (local_fn)\r
-            g_free(local_fn);\r
-        if  (unicode_fn)\r
-            g_free(unicode_fn);\r
-        return NULL;\r
-    }\r
-\r
-    EnumEnhMetaFile(NULL, hemf, myEnhMetaFileProc, (LPVOID) &d, NULL);\r
-    DeleteEnhMetaFile(hemf);\r
-\r
-//    std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;\r
-\r
-    SPDocument *doc = sp_document_new_from_mem(d.outsvg->c_str(), d.outsvg->length(), TRUE);\r
-\r
-    delete d.outsvg;\r
-    delete d.path;\r
-\r
-    if (d.emf_obj) {\r
-        int i;\r
-        for (i=0; i<d.n_obj; i++)\r
-            delete_object(&d, i);\r
-        delete[] d.emf_obj;\r
-    }\r
-    \r
-    if (d.style.stroke_dash.dash)\r
-        delete[] d.style.stroke_dash.dash;\r
-\r
-    if  (local_fn)\r
-        g_free(local_fn);\r
-    if  (unicode_fn)\r
-        g_free(unicode_fn);\r
-\r
-    return doc;\r
-}\r
-\r
-\r
-void\r
-EmfWin32::init (void)\r
-{\r
-    Inkscape::Extension::Extension * ext;\r
-\r
-    /* EMF in */\r
-    ext = Inkscape::Extension::build_from_mem(\r
-        "<inkscape-extension>\n"\r
-            "<name>" N_("EMF Input") "</name>\n"\r
-            "<id>org.inkscape.input.emf.win32</id>\n"\r
-            "<input>\n"\r
-                "<extension>.emf</extension>\n"\r
-                "<mimetype>image/x-emf</mimetype>\n"\r
-                "<filetypename>" N_("Enhanced Metafiles (*.emf)") "</filetypename>\n"\r
-                "<filetypetooltip>" N_("Enhanced Metafiles") "</filetypetooltip>\n"\r
-                "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"\r
-            "</input>\n"\r
-        "</inkscape-extension>", new EmfWin32());\r
-\r
-    /* WMF in */\r
-    ext = Inkscape::Extension::build_from_mem(\r
-        "<inkscape-extension>\n"\r
-            "<name>" N_("WMF Input") "</name>\n"\r
-            "<id>org.inkscape.input.wmf.win32</id>\n"\r
-            "<input>\n"\r
-                "<extension>.wmf</extension>\n"\r
-                "<mimetype>image/x-wmf</mimetype>\n"\r
-                "<filetypename>" N_("Windows Metafiles (*.wmf)") "</filetypename>\n"\r
-                "<filetypetooltip>" N_("Windows Metafiles") "</filetypetooltip>\n"\r
-                "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"\r
-            "</input>\n"\r
-        "</inkscape-extension>", new EmfWin32());\r
-\r
-    /* EMF out */\r
-    ext = Inkscape::Extension::build_from_mem(\r
-        "<inkscape-extension>\n"\r
-            "<name>" N_("EMF Output") "</name>\n"\r
-            "<id>org.inkscape.output.emf.win32</id>\n"\r
-            "<output>\n"\r
-                "<extension>.emf</extension>\n"\r
-                "<mimetype>image/x-emf</mimetype>\n"\r
-                "<filetypename>" N_("Enhanced Metafile (*.emf)") "</filetypename>\n"\r
-                "<filetypetooltip>" N_("Enhanced Metafile") "</filetypetooltip>\n"\r
-            "</output>\n"\r
-        "</inkscape-extension>", new EmfWin32());\r
-\r
-    return;\r
-}\r
-\r
-\r
-} } }  /* namespace Inkscape, Extension, Implementation */\r
-\r
-\r
-#endif /* WIN32 */\r
-\r
-\r
-/*\r
-  Local Variables:\r
-  mode:cpp\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+/** \file
+ * Enhanced Metafile Input and Output.
+ */
+/*
+ * Authors:
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+/*
+ * References:
+ *  - How to Create & Play Enhanced Metafiles in Win32
+ *      http://support.microsoft.com/kb/q145999/
+ *  - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
+ *      http://support.microsoft.com/kb/q66949/
+ *  - Metafile Functions
+ *      http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
+ *  - Metafile Structures
+ *      http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
+ */
+
+#ifdef WIN32
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "win32.h"
+#include "emf-win32-print.h"
+#include "emf-win32-inout.h"
+#include "inkscape.h"
+#include "sp-path.h"
+#include "style.h"
+#include "color.h"
+#include "display/curve.h"
+#include "libnr/n-art-bpath.h"
+#include "libnr/nr-point-matrix-ops.h"
+#include "gtk/gtk.h"
+#include "print.h"
+#include "glibmm/i18n.h"
+#include "extension/extension.h"
+#include "extension/system.h"
+#include "extension/print.h"
+#include "extension/db.h"
+#include "extension/output.h"
+#include "document.h"
+#include "display/nr-arena.h"
+#include "display/nr-arena-item.h"
+
+#include "libnr/nr-rect.h"
+#include "libnr/nr-matrix.h"
+#include "libnr/nr-pixblock.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <vector>
+#include <string>
+
+#include "io/sys.h"
+
+#include "unit-constants.h"
+
+#include "clear-n_.h"
+
+
+#define PRINT_EMF_WIN32 "org.inkscape.print.emf.win32"
+
+#ifndef PS_JOIN_MASK
+#define PS_JOIN_MASK (PS_JOIN_BEVEL|PS_JOIN_MITER|PS_JOIN_ROUND)
+#endif
+
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+
+EmfWin32::EmfWin32 (void) // The null constructor
+{
+    return;
+}
+
+
+EmfWin32::~EmfWin32 (void) //The destructor
+{
+    return;
+}
+
+
+bool
+EmfWin32::check (Inkscape::Extension::Extension * module)
+{
+    if (NULL == Inkscape::Extension::db.get(PRINT_EMF_WIN32))
+        return FALSE;
+    return TRUE;
+}
+
+
+static void
+emf_print_document_to_file(SPDocument *doc, gchar const *filename)
+{
+    Inkscape::Extension::Print *mod;
+    SPPrintContext context;
+    gchar const *oldconst;
+    gchar *oldoutput;
+    unsigned int ret;
+
+    sp_document_ensure_up_to_date(doc);
+
+    mod = Inkscape::Extension::get_print(PRINT_EMF_WIN32);
+    oldconst = mod->get_param_string("destination");
+    oldoutput = g_strdup(oldconst);
+    mod->set_param_string("destination", (gchar *)filename);
+
+/* Start */
+    context.module = mod;
+    /* fixme: This has to go into module constructor somehow */
+    /* Create new arena */
+    mod->base = SP_ITEM(sp_document_root(doc));
+    mod->arena = NRArena::create();
+    mod->dkey = sp_item_display_key_new(1);
+    mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+    /* Print document */
+    ret = mod->begin(doc);
+    if (ret) {
+        throw Inkscape::Extension::Output::save_failed();
+    }
+    sp_item_invoke_print(mod->base, &context);
+    ret = mod->finish();
+    /* Release arena */
+    sp_item_invoke_hide(mod->base, mod->dkey);
+    mod->base = NULL;
+    nr_arena_item_unref(mod->root);
+    mod->root = NULL;
+    nr_object_unref((NRObject *) mod->arena);
+    mod->arena = NULL;
+/* end */
+
+    mod->set_param_string("destination", oldoutput);
+    g_free(oldoutput);
+
+    return;
+}
+
+
+void
+EmfWin32::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)
+{
+    Inkscape::Extension::Extension * ext;
+
+    ext = Inkscape::Extension::db.get(PRINT_EMF_WIN32);
+    if (ext == NULL)
+        return;
+
+//    bool old_textToPath  = ext->get_param_bool("textToPath");
+//    bool new_val         = mod->get_param_bool("textToPath");
+//    ext->set_param_bool("textToPath", new_val);
+
+    gchar * final_name;
+    final_name = g_strdup_printf("%s", uri);
+    emf_print_document_to_file(doc, final_name);
+    g_free(final_name);
+
+//    ext->set_param_bool("textToPath", old_textToPath);
+
+    return;
+}
+
+
+
+typedef struct {
+    int type;
+    ENHMETARECORD *lpEMFR;
+} EMF_OBJECT, *PEMF_OBJECT;
+
+typedef struct emf_callback_data {
+    Glib::ustring *outsvg;
+    Glib::ustring *path;
+    struct SPStyle style;
+    bool stroke_set;
+    bool fill_set;
+    double xDPI, yDPI;
+
+    SIZEL sizeWnd;
+    SIZEL sizeView;
+    float PixelsX;
+    float PixelsY;
+    float MMX;
+    float MMY;
+    float dwInchesX;
+    float dwInchesY;
+    POINTL winorg;
+    POINTL vieworg;
+    double ScaleX, ScaleY;
+
+    int n_obj;
+    PEMF_OBJECT emf_obj;
+} EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA;
+
+
+static void
+output_style(PEMF_CALLBACK_DATA d, int iType)
+{
+    SVGOStringStream tmp_style;
+    char tmp[1024] = {0};
+
+    *(d->outsvg) += "\n\tstyle=\"";
+    if (iType == EMR_STROKEPATH || !d->fill_set) {
+        tmp_style << "fill:none;";
+    } else {
+        float rgb[3];
+        sp_color_get_rgb_floatv( &(d->style.fill.value.color), rgb );
+        snprintf(tmp, 1023,
+                 "fill:#%02x%02x%02x;",
+                 SP_COLOR_F_TO_U(rgb[0]),
+                 SP_COLOR_F_TO_U(rgb[1]),
+                 SP_COLOR_F_TO_U(rgb[2]));
+        tmp_style << tmp;
+        snprintf(tmp, 1023,
+                 "fill-rule:%s;",
+                 d->style.fill_rule.value != 0 ? "evenodd" : "nonzero");
+        tmp_style << tmp;
+        tmp_style << "fill-opacity:1;";
+    }
+
+    if (iType == EMR_FILLPATH || !d->stroke_set) {
+        tmp_style << "stroke:none;";
+    } else {
+        float rgb[3];
+        sp_color_get_rgb_floatv(&(d->style.stroke.value.color), rgb);
+        snprintf(tmp, 1023,
+                 "stroke:#%02x%02x%02x;",
+                 SP_COLOR_F_TO_U(rgb[0]),
+                 SP_COLOR_F_TO_U(rgb[1]),
+                 SP_COLOR_F_TO_U(rgb[2]));
+        tmp_style << tmp;
+
+        tmp_style << "stroke-width:" <<
+            MAX( 0.001, d->style.stroke_width.value ) << "px;";
+
+        tmp_style << "stroke-linejoin:" <<
+            (d->style.stroke_linejoin.computed == 0 ? "miter" :
+             d->style.stroke_linejoin.computed == 1 ? "round" :
+             d->style.stroke_linejoin.computed == 2 ? "bevel" :
+             "unknown") << ";";
+
+        if (d->style.stroke_linejoin.computed == 0) {
+            tmp_style << "stroke-miterlimit:" <<
+                MAX( 0.01, d->style.stroke_miterlimit.value ) << ";";
+        }
+
+        if (d->style.stroke_dasharray_set &&
+            d->style.stroke_dash.n_dash && d->style.stroke_dash.dash)
+        {
+            tmp_style << "stroke-dasharray:";
+            for (int i=0; i<d->style.stroke_dash.n_dash; i++) {
+                if (i)
+                    tmp_style << ",";
+                tmp_style << d->style.stroke_dash.dash[i];
+            }
+            tmp_style << ";";
+            tmp_style << "stroke-dashoffset:0;";
+        } else {
+            tmp_style << "stroke-dasharray:none;";
+        }
+        tmp_style << "stroke-opacity:1;";
+    }
+    tmp_style << "\" ";
+
+    *(d->outsvg) += tmp_style.str().c_str();
+}
+
+
+static double
+pix_x_to_point(PEMF_CALLBACK_DATA d, double px)
+{
+    double tmp = px - d->winorg.x;
+    tmp *= (double) PX_PER_IN / d->ScaleX;
+    tmp += d->vieworg.x;
+    return tmp;
+}
+
+
+static double
+pix_y_to_point(PEMF_CALLBACK_DATA d, double px)
+{
+    double tmp = px - d->winorg.y;
+    tmp *= (double) PX_PER_IN / d->ScaleY;
+    tmp += d->vieworg.y;
+    return tmp;
+}
+
+
+static double
+pix_size_to_point(PEMF_CALLBACK_DATA d, double px)
+{
+    double tmp = px;
+    tmp *= (double) PX_PER_IN / d->ScaleX;
+    return tmp;
+}
+
+
+static void
+select_pen(PEMF_CALLBACK_DATA d, int index)
+{
+    PEMRCREATEPEN pEmr = NULL;
+
+    if (index >= 0 && index < d->n_obj)
+        pEmr = (PEMRCREATEPEN) d->emf_obj[index].lpEMFR;
+
+    if (!pEmr)
+        return;
+
+    switch (pEmr->lopn.lopnStyle) {
+        default:
+        {
+            d->style.stroke_dasharray_set = 0;
+            break;
+        }
+    }
+
+    if (pEmr->lopn.lopnWidth.x) {
+        d->style.stroke_width.value = pix_size_to_point( d, pEmr->lopn.lopnWidth.x );
+    } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
+        d->style.stroke_width.value = 1.0;
+    }
+
+    double r, g, b;
+    r = SP_COLOR_U_TO_F( GetRValue(pEmr->lopn.lopnColor) );
+    g = SP_COLOR_U_TO_F( GetGValue(pEmr->lopn.lopnColor) );
+    b = SP_COLOR_U_TO_F( GetBValue(pEmr->lopn.lopnColor) );
+    sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );
+
+    d->style.stroke_linejoin.computed = 1;
+
+    d->stroke_set = true;
+}
+
+
+static void
+select_extpen(PEMF_CALLBACK_DATA d, int index)
+{
+    PEMREXTCREATEPEN pEmr = NULL;
+
+    if (index >= 0 && index < d->n_obj)
+        pEmr = (PEMREXTCREATEPEN) d->emf_obj[index].lpEMFR;
+
+    if (!pEmr)
+        return;
+
+    switch (pEmr->elp.elpPenStyle & PS_STYLE_MASK) {
+        case PS_USERSTYLE:
+        {
+            if (pEmr->elp.elpNumEntries) {
+                d->style.stroke_dash.n_dash = pEmr->elp.elpNumEntries;
+                if (d->style.stroke_dash.dash)
+                    delete[] d->style.stroke_dash.dash;
+                d->style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries];
+                for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
+                    d->style.stroke_dash.dash[i] = pix_size_to_point( d, pEmr->elp.elpStyleEntry[i] );
+                }
+                d->style.stroke_dasharray_set = 1;
+            } else {
+                d->style.stroke_dasharray_set = 0;
+            }
+            break;
+        }
+        default:
+        {
+            d->style.stroke_dasharray_set = 0;
+            break;
+        }
+    }
+
+    switch (pEmr->elp.elpPenStyle & PS_ENDCAP_MASK) {
+        case PS_ENDCAP_ROUND:
+        {
+            d->style.stroke_linecap.computed = 1;
+            break;
+        }
+        case PS_ENDCAP_SQUARE:
+        {
+            d->style.stroke_linecap.computed = 2;
+            break;
+        }
+        case PS_ENDCAP_FLAT:
+        default:
+        {
+            d->style.stroke_linecap.computed = 0;
+            break;
+        }
+    }
+
+    switch (pEmr->elp.elpPenStyle & PS_JOIN_MASK) {
+        case PS_JOIN_BEVEL:
+        {
+            d->style.stroke_linejoin.computed = 2;
+            break;
+        }
+        case PS_JOIN_MITER:
+        {
+            d->style.stroke_linejoin.computed = 0;
+            break;
+        }
+        case PS_JOIN_ROUND:
+        default:
+        {
+            d->style.stroke_linejoin.computed = 1;
+            break;
+        }
+    }
+
+    d->style.stroke_width.value = pix_size_to_point( d, pEmr->elp.elpWidth );
+
+    double r, g, b;
+    r = SP_COLOR_U_TO_F( GetRValue(pEmr->elp.elpColor) );
+    g = SP_COLOR_U_TO_F( GetGValue(pEmr->elp.elpColor) );
+    b = SP_COLOR_U_TO_F( GetBValue(pEmr->elp.elpColor) );
+
+    sp_color_set_rgb_float( &(d->style.stroke.value.color), r,g,b );
+
+    d->stroke_set = true;
+}
+
+
+static void
+select_brush(PEMF_CALLBACK_DATA d, int index)
+{
+    PEMRCREATEBRUSHINDIRECT pEmr = NULL;
+
+    if (index >= 0 && index < d->n_obj)
+        pEmr = (PEMRCREATEBRUSHINDIRECT) d->emf_obj[index].lpEMFR;
+
+    if (!pEmr)
+        return;
+
+    if (pEmr->lb.lbStyle == BS_SOLID) {
+        double r, g, b;
+        r = SP_COLOR_U_TO_F( GetRValue(pEmr->lb.lbColor) );
+        g = SP_COLOR_U_TO_F( GetGValue(pEmr->lb.lbColor) );
+        b = SP_COLOR_U_TO_F( GetBValue(pEmr->lb.lbColor) );
+        sp_color_set_rgb_float( &(d->style.fill.value.color), r,g,b );
+    }
+
+    d->fill_set = true;
+}
+
+
+static void
+delete_object(PEMF_CALLBACK_DATA d, int index)
+{
+    if (index >= 0 && index < d->n_obj) {
+        d->emf_obj[index].type = 0;
+        if (d->emf_obj[index].lpEMFR)
+            free(d->emf_obj[index].lpEMFR);
+        d->emf_obj[index].lpEMFR = NULL;
+    }
+}
+
+
+static void
+insert_object(PEMF_CALLBACK_DATA d, int index, int type, ENHMETARECORD *pObj)
+{
+    if (index >= 0 && index < d->n_obj) {
+        delete_object(d, index);
+        d->emf_obj[index].type = type;
+        d->emf_obj[index].lpEMFR = pObj;
+    }
+}
+
+
+static int CALLBACK
+myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData)
+{
+    PEMF_CALLBACK_DATA d;
+    SVGOStringStream tmp_outsvg;
+    SVGOStringStream tmp_path;
+    SVGOStringStream tmp_str;
+
+    d = (PEMF_CALLBACK_DATA) lpData;
+
+    switch (lpEMFR->iType)
+    {
+        case EMR_HEADER:
+        {
+            ENHMETAHEADER *pEmr = (ENHMETAHEADER *) lpEMFR;
+            tmp_outsvg << "<svg\n";
+
+            d->xDPI = 2540;
+            d->yDPI = 2540;
+
+            d->PixelsX = pEmr->rclFrame.right - pEmr->rclFrame.left;
+            d->PixelsY = pEmr->rclFrame.bottom - pEmr->rclFrame.top;
+
+            d->MMX = d->PixelsX / 100.0;
+            d->MMY = d->PixelsY / 100.0;
+
+            tmp_outsvg <<
+                "  width=\"" << d->MMX << "mm\"\n" <<
+                "  height=\"" << d->MMY << "mm\">\n";
+
+            if (pEmr->nHandles) {
+                d->n_obj = pEmr->nHandles;
+                d->emf_obj = new EMF_OBJECT[d->n_obj];
+            } else {
+                d->emf_obj = NULL;
+            }
+
+            break;
+        }
+        case EMR_POLYBEZIER:
+        {
+            PEMRPOLYBEZIER pEmr = (PEMRPOLYBEZIER) lpEMFR;
+            DWORD i,j;
+
+            if (pEmr->cptl<4)
+                break;
+
+            *(d->outsvg) += "    <path ";
+            output_style(d, EMR_STROKEPATH);
+            *(d->outsvg) += "\n\td=\"";
+
+            tmp_str <<
+                "\n\tM " <<
+                pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<
+                pix_x_to_point( d, pEmr->aptl[0].y) << " ";
+
+            for (i=1; i<pEmr->cptl; ) {
+                tmp_str << "\n\tC ";
+                for (j=0; j<3 && i<pEmr->cptl; j++,i++) {
+                    tmp_str <<
+                        pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<
+                        pix_y_to_point( d, pEmr->aptl[i].y ) << " ";
+                }
+            }
+
+            *(d->outsvg) += tmp_str.str().c_str();
+            *(d->outsvg) += " \" /> \n";
+
+            break;
+        }
+        case EMR_POLYGON:
+        {
+            EMRPOLYGON *pEmr = (EMRPOLYGON *) lpEMFR;
+            DWORD i;
+
+            if (pEmr->cptl < 2)
+                break;
+
+            *(d->outsvg) += "    <path ";
+            output_style(d, EMR_STROKEANDFILLPATH);
+            *(d->outsvg) += "\n\td=\"";
+
+            tmp_str <<
+                "\n\tM " <<
+                pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<
+                pix_y_to_point( d, pEmr->aptl[0].y ) << " ";
+
+            for (i=1; i<pEmr->cptl; i++) {
+                tmp_str <<
+                    "\n\tL " <<
+                    pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<
+                    pix_y_to_point( d, pEmr->aptl[i].y ) << " ";
+            }
+
+            *(d->outsvg) += tmp_str.str().c_str();
+            *(d->outsvg) += " z \" /> \n";
+
+            break;
+        }
+        case EMR_POLYLINE:
+        {
+            EMRPOLYLINE *pEmr = (EMRPOLYLINE *) lpEMFR;
+            DWORD i;
+
+            if (pEmr->cptl<2)
+                break;
+
+            *(d->outsvg) += "    <path ";
+            output_style(d, EMR_STROKEPATH);
+            *(d->outsvg) += "\n\td=\"";
+
+            tmp_str <<
+                "\n\tM " <<
+                pix_x_to_point( d, pEmr->aptl[0].x ) << " " <<
+                pix_y_to_point( d, pEmr->aptl[0].y ) << " ";
+
+            for (i=1; i<pEmr->cptl; i++) {
+                tmp_str <<
+                    "\n\tL " <<
+                    pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<
+                    pix_y_to_point( d, pEmr->aptl[i].y ) << " ";
+            }
+
+            *(d->outsvg) += tmp_str.str().c_str();
+            *(d->outsvg) += " \" /> \n";
+
+            break;
+        }
+        case EMR_POLYBEZIERTO:
+        {
+            PEMRPOLYBEZIERTO pEmr = (PEMRPOLYBEZIERTO) lpEMFR;
+            DWORD i,j;
+
+            for (i=0; i<pEmr->cptl;) {
+                tmp_path << "\n\tC ";
+                for (j=0; j<3 && i<pEmr->cptl; j++,i++) {
+                    tmp_path <<
+                        pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<
+                        pix_y_to_point( d, pEmr->aptl[i].y ) << " ";
+                }
+            }
+
+            break;
+        }
+        case EMR_POLYLINETO:
+        {
+            PEMRPOLYLINETO pEmr = (PEMRPOLYLINETO) lpEMFR;
+            DWORD i;
+
+            for (i=0; i<pEmr->cptl;i++) {
+                tmp_path <<
+                    "\n\tL " <<
+                    pix_x_to_point( d, pEmr->aptl[i].x ) << " " <<
+                    pix_y_to_point( d, pEmr->aptl[i].y ) << " ";
+            }
+
+            break;
+        }
+        case EMR_POLYPOLYLINE:
+            break;
+        case EMR_POLYPOLYGON:
+            break;
+        case EMR_SETWINDOWEXTEX:
+        {
+            PEMRSETWINDOWEXTEX pEmr = (PEMRSETWINDOWEXTEX) lpEMFR;
+
+            d->sizeWnd = pEmr->szlExtent;
+            d->PixelsX = d->sizeWnd.cx;
+            d->PixelsY = d->sizeWnd.cy;
+
+            d->ScaleX = d->xDPI / (100*d->MMX / d->PixelsX);
+            d->ScaleY = d->yDPI / (100*d->MMY / d->PixelsY);
+
+            break;
+        }
+        case EMR_SETWINDOWORGEX:
+        {
+            PEMRSETWINDOWORGEX pEmr = (PEMRSETWINDOWORGEX) lpEMFR;
+            d->winorg = pEmr->ptlOrigin;
+            break;
+        }
+        case EMR_SETVIEWPORTEXTEX:
+        {
+            PEMRSETVIEWPORTEXTEX pEmr = (PEMRSETVIEWPORTEXTEX) lpEMFR;
+
+            d->sizeView = pEmr->szlExtent;
+
+            if (d->sizeWnd.cx && d->sizeWnd.cy) {
+                HDC hScreenDC = GetDC( NULL );
+
+                float scrPixelsX = (float)GetDeviceCaps( hScreenDC, HORZRES );
+                float scrPixelsY = (float)GetDeviceCaps( hScreenDC, VERTRES );
+                float scrMMX = (float)GetDeviceCaps( hScreenDC, HORZSIZE );
+                float scrMMY = (float)GetDeviceCaps( hScreenDC, VERTSIZE );
+
+                ReleaseDC( NULL, hScreenDC );
+
+                d->dwInchesX = d->sizeView.cx / (25.4f*scrPixelsX/scrMMX);
+                d->dwInchesY = d->sizeView.cy / (25.4f*scrPixelsY/scrMMY);
+                d->xDPI = d->sizeWnd.cx / d->dwInchesX;
+                d->yDPI = d->sizeWnd.cy / d->dwInchesY;
+
+                if (1) {
+                    d->xDPI = 2540;
+                    d->yDPI = 2540;
+                    d->dwInchesX = d->PixelsX / d->xDPI;
+                    d->dwInchesY = d->PixelsY / d->yDPI;
+                    d->ScaleX = d->xDPI;
+                    d->ScaleY = d->yDPI;
+                }
+
+                d->MMX = d->dwInchesX * MM_PER_IN;
+                d->MMY = d->dwInchesY * MM_PER_IN;
+            }
+
+            break;
+        }
+        case EMR_SETVIEWPORTORGEX:
+        {
+            PEMRSETVIEWPORTORGEX pEmr = (PEMRSETVIEWPORTORGEX) lpEMFR;
+            d->vieworg = pEmr->ptlOrigin;
+            break;
+        }
+        case EMR_SETBRUSHORGEX:
+            break;
+        case EMR_EOF:
+        {
+            tmp_outsvg << "</svg>\n";
+            break;
+        }
+        case EMR_SETPIXELV:
+            break;
+        case EMR_SETMAPPERFLAGS:
+            break;
+        case EMR_SETMAPMODE:
+            break;
+        case EMR_SETBKMODE:
+            break;
+        case EMR_SETPOLYFILLMODE:
+        {
+            PEMRSETPOLYFILLMODE pEmr = (PEMRSETPOLYFILLMODE) lpEMFR;
+            d->style.fill_rule.value =
+                (pEmr->iMode == WINDING ? 0 :
+                 pEmr->iMode == ALTERNATE ? 1 : 0);
+            break;
+        }
+        case EMR_SETROP2:
+            break;
+        case EMR_SETSTRETCHBLTMODE:
+            break;
+        case EMR_SETTEXTALIGN:
+            break;
+        case EMR_SETCOLORADJUSTMENT:
+            break;
+        case EMR_SETTEXTCOLOR:
+            break;
+        case EMR_SETBKCOLOR:
+            break;
+        case EMR_OFFSETCLIPRGN:
+            break;
+        case EMR_MOVETOEX:
+        {
+            PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR;
+            tmp_path <<
+                "\n\tM " <<
+                pix_x_to_point( d, pEmr->ptl.x ) << " " <<
+                pix_y_to_point( d, pEmr->ptl.y ) << " ";
+            break;
+        }
+        case EMR_SETMETARGN:
+            break;
+        case EMR_EXCLUDECLIPRECT:
+            break;
+        case EMR_INTERSECTCLIPRECT:
+            break;
+        case EMR_SCALEVIEWPORTEXTEX:
+            break;
+        case EMR_SCALEWINDOWEXTEX:
+            break;
+        case EMR_SAVEDC:
+            break;
+        case EMR_RESTOREDC:
+            break;
+        case EMR_SETWORLDTRANSFORM:
+            break;
+        case EMR_MODIFYWORLDTRANSFORM:
+            break;
+        case EMR_SELECTOBJECT:
+        {
+            PEMRSELECTOBJECT pEmr = (PEMRSELECTOBJECT) lpEMFR;
+            unsigned int index = pEmr->ihObject;
+
+            if (index >= ENHMETA_STOCK_OBJECT) {
+                index -= ENHMETA_STOCK_OBJECT;
+                switch (index) {
+                    case NULL_BRUSH:
+                        d->fill_set = false;
+                        break;
+                    case BLACK_BRUSH:
+                    case DKGRAY_BRUSH:
+                    case GRAY_BRUSH:
+                    case LTGRAY_BRUSH:
+                    case WHITE_BRUSH:
+                    {
+                        float val = 0;
+                        switch (index) {
+                            case BLACK_BRUSH:
+                                val = 0.0 / 255.0;
+                                break;
+                            case DKGRAY_BRUSH:
+                                val = 64.0 / 255.0;
+                                break;
+                            case GRAY_BRUSH:
+                                val = 128.0 / 255.0;
+                                break;
+                            case LTGRAY_BRUSH:
+                                val = 192.0 / 255.0;
+                                break;
+                            case WHITE_BRUSH:
+                                val = 255.0 / 255.0;
+                                break;
+                        }
+                        sp_color_set_rgb_float( &(d->style.fill.value.color), val,val,val );
+
+                        d->fill_set = true;
+                        break;
+                    }
+                    case NULL_PEN:
+                        d->stroke_set = false;
+                        break;
+                    case BLACK_PEN:
+                    case WHITE_PEN:
+                    {
+                        float val = index == BLACK_PEN ? 0 : 1;
+                        d->style.stroke_dasharray_set = 0;
+                        d->style.stroke_width.value = 1.0;
+                        sp_color_set_rgb_float( &(d->style.stroke.value.color), val,val,val );
+
+                        d->stroke_set = true;
+
+                        break;
+                    }
+                }
+            } else {
+                if (index >= 0 && index < d->n_obj) {
+                    switch (d->emf_obj[index].type)
+                    {
+                        case EMR_CREATEPEN:
+                            select_pen(d, index);
+                            break;
+                        case EMR_CREATEBRUSHINDIRECT:
+                            select_brush(d, index);
+                            break;
+                        case EMR_EXTCREATEPEN:
+                            select_extpen(d, index);
+                            break;
+                    }
+                }
+            }
+            break;
+        }
+        case EMR_CREATEPEN:
+        {
+            PEMRCREATEPEN pEmr = (PEMRCREATEPEN) lpEMFR;
+            int index = pEmr->ihPen;
+
+            EMRCREATEPEN *pPen =
+                (EMRCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) );
+            pPen->lopn = pEmr->lopn;
+            insert_object(d, index, EMR_CREATEPEN, (ENHMETARECORD *) pPen);
+
+            break;
+        }
+        case EMR_CREATEBRUSHINDIRECT:
+        {
+            PEMRCREATEBRUSHINDIRECT pEmr = (PEMRCREATEBRUSHINDIRECT) lpEMFR;
+            int index = pEmr->ihBrush;
+
+            EMRCREATEBRUSHINDIRECT *pBrush =
+                (EMRCREATEBRUSHINDIRECT *) malloc( sizeof(EMRCREATEBRUSHINDIRECT) );
+            pBrush->lb = pEmr->lb;
+            insert_object(d, index, EMR_CREATEBRUSHINDIRECT, (ENHMETARECORD *) pBrush);
+
+            break;
+        }
+        case EMR_DELETEOBJECT:
+            break;
+        case EMR_ANGLEARC:
+            break;
+        case EMR_ELLIPSE:
+            break;
+        case EMR_RECTANGLE:
+            break;
+        case EMR_ROUNDRECT:
+            break;
+        case EMR_ARC:
+            break;
+        case EMR_CHORD:
+            break;
+        case EMR_PIE:
+            break;
+        case EMR_SELECTPALETTE:
+            break;
+        case EMR_CREATEPALETTE:
+            break;
+        case EMR_SETPALETTEENTRIES:
+            break;
+        case EMR_RESIZEPALETTE:
+            break;
+        case EMR_REALIZEPALETTE:
+            break;
+        case EMR_EXTFLOODFILL:
+            break;
+        case EMR_LINETO:
+        {
+            PEMRLINETO pEmr = (PEMRLINETO) lpEMFR;
+            tmp_path <<
+                "\n\tL " <<
+                pix_x_to_point( d, pEmr->ptl.x ) << " " <<
+                pix_y_to_point( d, pEmr->ptl.y ) << " ";
+            break;
+        }
+        case EMR_ARCTO:
+            break;
+        case EMR_POLYDRAW:
+            break;
+        case EMR_SETARCDIRECTION:
+            break;
+        case EMR_SETMITERLIMIT:
+        {
+            PEMRSETMITERLIMIT pEmr = (PEMRSETMITERLIMIT) lpEMFR;
+            d->style.stroke_miterlimit.value = pix_size_to_point( d, pEmr->eMiterLimit );
+
+            if (d->style.stroke_miterlimit.value < 1)
+                d->style.stroke_miterlimit.value = 1.0;
+
+            break;
+        }
+        case EMR_BEGINPATH:
+        {
+            tmp_path << " d=\"";
+            *(d->path) = "";
+            break;
+        }
+        case EMR_ENDPATH:
+        {
+            tmp_path << "\"";
+            break;
+        }
+        case EMR_CLOSEFIGURE:
+        {
+            tmp_path << "\n\tz";
+            break;
+        }
+        case EMR_FILLPATH:
+        case EMR_STROKEANDFILLPATH:
+        case EMR_STROKEPATH:
+        {
+            *(d->outsvg) += "    <path ";
+            output_style(d, lpEMFR->iType);
+            *(d->outsvg) += "\n\t";
+            *(d->outsvg) += *(d->path);
+            *(d->outsvg) += " /> \n";
+            break;
+        }
+        case EMR_FLATTENPATH:
+            break;
+        case EMR_WIDENPATH:
+            break;
+        case EMR_SELECTCLIPPATH:
+            break;
+        case EMR_ABORTPATH:
+            break;
+        case EMR_GDICOMMENT:
+            break;
+        case EMR_FILLRGN:
+            break;
+        case EMR_FRAMERGN:
+            break;
+        case EMR_INVERTRGN:
+            break;
+        case EMR_PAINTRGN:
+            break;
+        case EMR_EXTSELECTCLIPRGN:
+            break;
+        case EMR_BITBLT:
+            break;
+        case EMR_STRETCHBLT:
+            break;
+        case EMR_MASKBLT:
+            break;
+        case EMR_PLGBLT:
+            break;
+        case EMR_SETDIBITSTODEVICE:
+            break;
+        case EMR_STRETCHDIBITS:
+            break;
+        case EMR_EXTCREATEFONTINDIRECTW:
+            break;
+        case EMR_EXTTEXTOUTA:
+            break;
+        case EMR_EXTTEXTOUTW:
+            break;
+        case EMR_POLYBEZIER16:
+        {
+            PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR;
+            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
+            DWORD i,j;
+
+            if (pEmr->cpts<4)
+                break;
+
+            *(d->outsvg) += "    <path ";
+            output_style(d, EMR_STROKEPATH);
+            *(d->outsvg) += "\n\td=\"";
+
+            tmp_str <<
+                "\n\tM " <<
+                pix_x_to_point( d, apts[0].x ) << " " <<
+                pix_y_to_point( d, apts[0].y ) << " ";
+
+            for (i=1; i<pEmr->cpts; ) {
+                tmp_str << "\n\tC ";
+                for (j=0; j<3 && i<pEmr->cpts; j++,i++) {
+                    tmp_str <<
+                        pix_x_to_point( d, apts[i].x ) << " " <<
+                        pix_y_to_point( d, apts[i].y ) << " ";
+                }
+            }
+
+            *(d->outsvg) += tmp_str.str().c_str();
+            *(d->outsvg) += " \" /> \n";
+
+            break;
+        }
+        case EMR_POLYGON16:
+        {
+            PEMRPOLYGON16 pEmr = (PEMRPOLYGON16) lpEMFR;
+            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
+            unsigned int i;
+
+            *(d->outsvg) += "<path ";
+            output_style(d, EMR_STROKEANDFILLPATH);
+            *(d->outsvg) += "\n\td=\"";
+
+            // skip the first point?
+            tmp_path << "\n\tM " <<
+                pix_x_to_point( d, apts[1].x ) << " " <<
+                pix_y_to_point( d, apts[1].y ) << " ";
+
+            for (i=2; i<pEmr->cpts; i++) {
+                tmp_path << "\n\tL " <<
+                    pix_x_to_point( d, apts[i].x ) << " " <<
+                    pix_y_to_point( d, apts[i].y ) << " ";
+            }
+
+            *(d->outsvg) += tmp_path.str().c_str();
+            *(d->outsvg) += " z \" /> \n";
+
+            break;
+        }
+        case EMR_POLYLINE16:
+        {
+            EMRPOLYLINE16 *pEmr = (EMRPOLYLINE16 *) lpEMFR;
+            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
+            DWORD i;
+
+            if (pEmr->cpts<2)
+                break;
+
+            *(d->outsvg) += "    <path ";
+            output_style(d, EMR_STROKEPATH);
+            *(d->outsvg) += "\n\td=\"";
+
+            tmp_str <<
+                "\n\tM " <<
+                pix_x_to_point( d, apts[0].x ) << " " <<
+                pix_y_to_point( d, apts[0].y ) << " ";
+
+            for (i=1; i<pEmr->cpts; i++) {
+                tmp_str <<
+                    "\n\tL " <<
+                    pix_x_to_point( d, apts[i].x ) << " " <<
+                    pix_y_to_point( d, apts[i].y ) << " ";
+            }
+
+            *(d->outsvg) += tmp_str.str().c_str();
+            *(d->outsvg) += " \" /> \n";
+
+            break;
+        }
+        case EMR_POLYBEZIERTO16:
+        {
+            PEMRPOLYBEZIERTO16 pEmr = (PEMRPOLYBEZIERTO16) lpEMFR;
+            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
+            DWORD i,j;
+
+            for (i=0; i<pEmr->cpts;) {
+                tmp_path << "\n\tC ";
+                for (j=0; j<3 && i<pEmr->cpts; j++,i++) {
+                    tmp_path <<
+                        pix_x_to_point( d, apts[i].x ) << " " <<
+                        pix_y_to_point( d, apts[i].y ) << " ";
+                }
+            }
+
+            break;
+        }
+        case EMR_POLYLINETO16:
+        {
+            PEMRPOLYLINETO16 pEmr = (PEMRPOLYLINETO16) lpEMFR;
+            POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ?
+            DWORD i;
+
+            for (i=0; i<pEmr->cpts;i++) {
+                tmp_path <<
+                    "\n\tL " <<
+                    pix_x_to_point( d, apts[i].x ) << " " <<
+                    pix_y_to_point( d, apts[i].y ) << " ";
+            }
+
+            break;
+        }
+        case EMR_POLYPOLYLINE16:
+            break;
+        case EMR_POLYPOLYGON16:
+        {
+            PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR;
+            unsigned int n, i, j;
+
+            *(d->outsvg) += "<path ";
+            output_style(d, EMR_STROKEANDFILLPATH);
+            *(d->outsvg) += "\n\td=\"";
+
+            i = pEmr->nPolys-1; // ???
+            for (n=0; n<pEmr->nPolys /*&& i<pEmr->cpts*/; n++) {
+                SVGOStringStream poly_path;
+
+                poly_path << "\n\tM " <<
+                    pix_x_to_point( d, pEmr->apts[i].x ) << " " <<
+                    pix_y_to_point( d, pEmr->apts[i].y ) << " ";
+                i++;
+
+                for (j=1; j<pEmr->aPolyCounts[n] /*&& i<pEmr->cpts*/; j++) {
+                    poly_path << "\n\tL " <<
+                        pix_x_to_point( d, pEmr->apts[i].x ) << " " <<
+                        pix_y_to_point( d, pEmr->apts[i].y ) << " ";
+                    i++;
+                }
+
+                *(d->outsvg) += poly_path.str().c_str();
+                *(d->outsvg) += " z \n";
+            }
+
+            *(d->outsvg) += " \" /> \n";
+            break;
+        }
+        case EMR_POLYDRAW16:
+            break;
+        case EMR_CREATEMONOBRUSH:
+            break;
+        case EMR_CREATEDIBPATTERNBRUSHPT:
+            break;
+        case EMR_EXTCREATEPEN:
+        {
+            PEMREXTCREATEPEN pEmr = (PEMREXTCREATEPEN) lpEMFR;
+            int index = pEmr->ihPen;
+
+            EMREXTCREATEPEN *pPen =
+                (EMREXTCREATEPEN *) malloc( sizeof(EMREXTCREATEPEN) +
+                                            sizeof(DWORD) * pEmr->elp.elpNumEntries );
+            pPen->ihPen = pEmr->ihPen;
+            pPen->offBmi = pEmr->offBmi;
+            pPen->cbBmi = pEmr->cbBmi;
+            pPen->offBits = pEmr->offBits;
+            pPen->cbBits = pEmr->cbBits;
+            pPen->elp = pEmr->elp;
+            for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
+                pPen->elp.elpStyleEntry[i] = pEmr->elp.elpStyleEntry[i];
+            }
+            insert_object(d, index, EMR_EXTCREATEPEN, (ENHMETARECORD *) pPen);
+
+            break;
+        }
+        case EMR_POLYTEXTOUTA:
+            break;
+        case EMR_POLYTEXTOUTW:
+            break;
+        case EMR_SETICMMODE:
+            break;
+        case EMR_CREATECOLORSPACE:
+            break;
+        case EMR_SETCOLORSPACE:
+            break;
+        case EMR_DELETECOLORSPACE:
+            break;
+        case EMR_GLSRECORD:
+            break;
+        case EMR_GLSBOUNDEDRECORD:
+            break;
+        case EMR_PIXELFORMAT:
+            break;
+    }
+
+    *(d->outsvg) += tmp_outsvg.str().c_str();
+    *(d->path) += tmp_path.str().c_str();
+
+    return 1;
+}
+
+
+// Aldus Placeable Header ===================================================
+// Since we are a 32bit app, we have to be sure this structure compiles to
+// be identical to a 16 bit app's version. To do this, we use the #pragma
+// to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT
+// for the bbox rectangle.
+#pragma pack( push )
+#pragma pack( 2 )
+typedef struct
+{
+       DWORD           dwKey;
+       WORD            hmf;
+       SMALL_RECT      bbox;
+       WORD            wInch;
+       DWORD           dwReserved;
+       WORD            wCheckSum;
+} APMHEADER, *PAPMHEADER;
+#pragma pack( pop )
+
+
+SPDocument *
+EmfWin32::open( Inkscape::Extension::Input *mod, const gchar *uri )
+{
+    EMF_CALLBACK_DATA d = {0};
+
+    gsize bytesRead = 0;
+    gsize bytesWritten = 0;
+    GError* error = NULL;
+    gchar *local_fn =
+        g_filename_from_utf8( uri, -1,  &bytesRead,  &bytesWritten, &error );
+
+    if (local_fn == NULL) {
+        return NULL;
+    }
+
+    d.outsvg = new Glib::ustring("");
+    d.path = new Glib::ustring("");
+
+    CHAR *ansi_uri = (CHAR *) local_fn;
+    gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
+    WCHAR *unicode_uri = (WCHAR *) unicode_fn;
+
+    // Try open as Enhanced Metafile
+    HENHMETAFILE hemf;
+    if (PrintWin32::is_os_wide())
+        hemf = GetEnhMetaFileW(unicode_uri);
+    else
+        hemf = GetEnhMetaFileA(ansi_uri);
+
+    if (!hemf) {
+        // Try open as Windows Metafile
+        HMETAFILE hmf;
+        if (PrintWin32::is_os_wide())
+            hmf = GetMetaFileW(unicode_uri);
+        else
+            hmf = GetMetaFileA(ansi_uri);
+
+       METAFILEPICT mp;
+       HDC hDC;
+
+        if (!hmf) {
+            if (PrintWin32::is_os_wide()) {
+                WCHAR szTemp[MAX_PATH];
+
+                DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );
+                if (dw) {
+                    hmf = GetMetaFileW( szTemp );
+                }
+            } else {
+                CHAR szTemp[MAX_PATH];
+
+                DWORD dw = GetShortPathNameA( ansi_uri, szTemp, MAX_PATH );
+                if (dw) {
+                    hmf = GetMetaFileA( szTemp );
+                }
+            }
+        }
+
+        if (hmf) {
+            DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL );
+            if (nSize) {
+                BYTE *lpvData = new BYTE[nSize];
+                if (lpvData) {
+                    DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData );
+                    if (dw) {
+                        // Fill out a METAFILEPICT structure
+                        mp.mm = MM_ANISOTROPIC;
+                        mp.xExt = 1000;
+                        mp.yExt = 1000;
+                        mp.hMF = NULL;
+                        // Get a reference DC
+                        hDC = GetDC( NULL );
+                        // Make an enhanced metafile from the windows metafile
+                        hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp );
+                        // Clean up
+                        ReleaseDC( NULL, hDC );
+                    }
+                    delete[] lpvData;
+                }
+                DeleteMetaFile( hmf );
+            }
+        } else {
+            // Try open as Aldus Placeable Metafile
+            HANDLE hFile;
+            if (PrintWin32::is_os_wide())
+                hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+            else
+                hFile = CreateFileA( ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+            if (hFile != INVALID_HANDLE_VALUE) {
+                DWORD nSize = GetFileSize( hFile, NULL );
+                if (nSize) {
+                    BYTE *lpvData = new BYTE[nSize];
+                    if (lpvData) {
+                        DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL );
+                        if (dw) {
+                            if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) {
+                                // Fill out a METAFILEPICT structure
+                                mp.mm = MM_ANISOTROPIC;
+                                mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left;
+                                mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
+                                mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top;
+                                mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch);
+                                mp.hMF = NULL;
+                                // Get a reference DC
+                                hDC = GetDC( NULL );
+                                // Create an enhanced metafile from the bits
+                                hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp );
+                                // Clean up
+                                ReleaseDC( NULL, hDC );
+                            }
+                        }
+                        delete[] lpvData;
+                    }
+                }
+                CloseHandle( hFile );
+            }
+        }
+    }
+
+    if (!hemf || !d.outsvg || !d.path) {
+        if (d.outsvg)
+            delete d.outsvg;
+        if (d.path)
+            delete d.path;
+        if  (local_fn)
+            g_free(local_fn);
+        if  (unicode_fn)
+            g_free(unicode_fn);
+        return NULL;
+    }
+
+    EnumEnhMetaFile(NULL, hemf, myEnhMetaFileProc, (LPVOID) &d, NULL);
+    DeleteEnhMetaFile(hemf);
+
+//    std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
+
+    SPDocument *doc = sp_document_new_from_mem(d.outsvg->c_str(), d.outsvg->length(), TRUE);
+
+    delete d.outsvg;
+    delete d.path;
+
+    if (d.emf_obj) {
+        int i;
+        for (i=0; i<d.n_obj; i++)
+            delete_object(&d, i);
+        delete[] d.emf_obj;
+    }
+    
+    if (d.style.stroke_dash.dash)
+        delete[] d.style.stroke_dash.dash;
+
+    if  (local_fn)
+        g_free(local_fn);
+    if  (unicode_fn)
+        g_free(unicode_fn);
+
+    return doc;
+}
+
+
+void
+EmfWin32::init (void)
+{
+    Inkscape::Extension::Extension * ext;
+
+    /* EMF in */
+    ext = Inkscape::Extension::build_from_mem(
+        "<inkscape-extension>\n"
+            "<name>" N_("EMF Input") "</name>\n"
+            "<id>org.inkscape.input.emf.win32</id>\n"
+            "<input>\n"
+                "<extension>.emf</extension>\n"
+                "<mimetype>image/x-emf</mimetype>\n"
+                "<filetypename>" N_("Enhanced Metafiles (*.emf)") "</filetypename>\n"
+                "<filetypetooltip>" N_("Enhanced Metafiles") "</filetypetooltip>\n"
+                "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"
+            "</input>\n"
+        "</inkscape-extension>", new EmfWin32());
+
+    /* WMF in */
+    ext = Inkscape::Extension::build_from_mem(
+        "<inkscape-extension>\n"
+            "<name>" N_("WMF Input") "</name>\n"
+            "<id>org.inkscape.input.wmf.win32</id>\n"
+            "<input>\n"
+                "<extension>.wmf</extension>\n"
+                "<mimetype>image/x-wmf</mimetype>\n"
+                "<filetypename>" N_("Windows Metafiles (*.wmf)") "</filetypename>\n"
+                "<filetypetooltip>" N_("Windows Metafiles") "</filetypetooltip>\n"
+                "<output_extension>org.inkscape.output.emf.win32</output_extension>\n"
+            "</input>\n"
+        "</inkscape-extension>", new EmfWin32());
+
+    /* EMF out */
+    ext = Inkscape::Extension::build_from_mem(
+        "<inkscape-extension>\n"
+            "<name>" N_("EMF Output") "</name>\n"
+            "<id>org.inkscape.output.emf.win32</id>\n"
+            "<output>\n"
+                "<extension>.emf</extension>\n"
+                "<mimetype>image/x-emf</mimetype>\n"
+                "<filetypename>" N_("Enhanced Metafile (*.emf)") "</filetypename>\n"
+                "<filetypetooltip>" N_("Enhanced Metafile") "</filetypetooltip>\n"
+            "</output>\n"
+        "</inkscape-extension>", new EmfWin32());
+
+    return;
+}
+
+
+} } }  /* namespace Inkscape, Extension, Implementation */
+
+
+#endif /* WIN32 */
+
+
+/*
+  Local Variables:
+  mode:cpp
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index eff8500493ef97ef1dda3cd8f9d3312fdb4b9094..3ec81b6b542019d597ad7c2ae41e2f5bb41786e0 100644 (file)
@@ -1,60 +1,60 @@
-/*\r
- * Enhanced Metafile Input/Output.\r
- *\r
- * Authors:\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifndef EXTENSION_INTERNAL_EMF_WIN32_H\r
-#define EXTENSION_INTERNAL_EMF_WIN32_H\r
-\r
-#ifdef WIN32\r
-\r
-#include "extension/implementation/implementation.h"\r
-#include "style.h"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-class EmfWin32 : Inkscape::Extension::Implementation::Implementation { //This is a derived class\r
-\r
-public:\r
-    EmfWin32(); // Empty constructor\r
-\r
-    virtual ~EmfWin32();//Destructor\r
-\r
-    bool check(Inkscape::Extension::Extension *module); //Can this module load (always yes for now)\r
-\r
-    void save(Inkscape::Extension::Output *mod, // Save the given document to the given filename\r
-              SPDocument *doc,\r
-              gchar const *uri);\r
-\r
-    virtual SPDocument *open( Inkscape::Extension::Input *mod,\r
-                                const gchar *uri );\r
-\r
-    static void init(void);//Initialize the class\r
-\r
-private:\r
-};\r
-\r
-} } }  /* namespace Inkscape, Extension, Implementation */\r
-\r
-#endif /* WIN32 */\r
-\r
-#endif /* EXTENSION_INTERNAL_EMF_WIN32_H */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+/*
+ * Enhanced Metafile Input/Output.
+ *
+ * Authors:
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef EXTENSION_INTERNAL_EMF_WIN32_H
+#define EXTENSION_INTERNAL_EMF_WIN32_H
+
+#ifdef WIN32
+
+#include "extension/implementation/implementation.h"
+#include "style.h"
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class EmfWin32 : Inkscape::Extension::Implementation::Implementation { //This is a derived class
+
+public:
+    EmfWin32(); // Empty constructor
+
+    virtual ~EmfWin32();//Destructor
+
+    bool check(Inkscape::Extension::Extension *module); //Can this module load (always yes for now)
+
+    void save(Inkscape::Extension::Output *mod, // Save the given document to the given filename
+              SPDocument *doc,
+              gchar const *uri);
+
+    virtual SPDocument *open( Inkscape::Extension::Input *mod,
+                                const gchar *uri );
+
+    static void init(void);//Initialize the class
+
+private:
+};
+
+} } }  /* namespace Inkscape, Extension, Implementation */
+
+#endif /* WIN32 */
+
+#endif /* EXTENSION_INTERNAL_EMF_WIN32_H */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index b40eec46297f540cddbde7e5764009ac2a066b07..9b1b77f160e08effff9b78c2ea28c6e1059044e5 100644 (file)
-/** \file\r
- * Enhanced Metafile Printing.\r
- */\r
-/*\r
- * Authors:\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-/*\r
- * References:\r
- *  - How to Create & Play Enhanced Metafiles in Win32\r
- *      http://support.microsoft.com/kb/q145999/\r
- *  - INFO: Windows Metafile Functions & Aldus Placeable Metafiles\r
- *      http://support.microsoft.com/kb/q66949/\r
- *  - Metafile Functions\r
- *      http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp\r
- *  - Metafile Structures\r
- *      http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp\r
- */\r
-\r
-#ifdef WIN32\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-#include <string.h>\r
-#include <signal.h>\r
-#include <errno.h>\r
-\r
-#include "libnr/n-art-bpath.h"\r
-#include "libnr/nr-point-matrix-ops.h"\r
-#include "libnr/nr-rect.h"\r
-#include "libnr/nr-matrix.h"\r
-#include "libnr/nr-matrix-fns.h"\r
-#include "libnr/nr-path.h"\r
-#include "libnr/nr-pixblock.h"\r
-#include "display/canvas-bpath.h"\r
-#include "sp-item.h"\r
-\r
-#include "glib.h"\r
-#include "gtk/gtkdialog.h"\r
-#include "gtk/gtkbox.h"\r
-#include "gtk/gtkstock.h"\r
-\r
-#include "glibmm/i18n.h"\r
-#include "enums.h"\r
-#include "document.h"\r
-#include "style.h"\r
-#include "sp-paint-server.h"\r
-#include "inkscape_version.h"\r
-\r
-#include "win32.h"\r
-#include "emf-win32-print.h"\r
-\r
-#include "unit-constants.h"\r
-\r
-#include "extension/extension.h"\r
-#include "extension/system.h"\r
-#include "extension/print.h"\r
-\r
-#include "io/sys.h"\r
-\r
-#include "macros.h"\r
-\r
-#define WIN32_LEAN_AND_MEAN\r
-#include <windows.h>\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-static float dwDPI = 2540;\r
-\r
-\r
-PrintEmfWin32::PrintEmfWin32 (void):\r
-    hdc(NULL),\r
-    hbrush(NULL),\r
-    hpen(NULL),\r
-    fill_path(NULL)\r
-{\r
-}\r
-\r
-\r
-PrintEmfWin32::~PrintEmfWin32 (void)\r
-{\r
-    if (hdc) {\r
-        HENHMETAFILE metafile = CloseEnhMetaFile( hdc );\r
-        if ( metafile ) {\r
-            DeleteEnhMetaFile( metafile );\r
-        }\r
-        DeleteDC( hdc );\r
-    }\r
-\r
-    /* restore default signal handling for SIGPIPE */\r
-#if !defined(_WIN32) && !defined(__WIN32__)\r
-    (void) signal(SIGPIPE, SIG_DFL);\r
-#endif\r
-       return;\r
-}\r
-\r
-\r
-unsigned int\r
-PrintEmfWin32::setup (Inkscape::Extension::Print *mod)\r
-{\r
-    return TRUE;\r
-}\r
-\r
-\r
-unsigned int\r
-PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)\r
-{\r
-    gchar const *utf8_fn = mod->get_param_string("destination");\r
-\r
-    gsize bytesRead = 0;\r
-    gsize bytesWritten = 0;\r
-    GError* error = NULL;\r
-    gchar *local_fn =\r
-        g_filename_from_utf8( utf8_fn, -1,  &bytesRead,  &bytesWritten, &error );\r
-\r
-    if (local_fn == NULL) {\r
-        return 1;\r
-    }\r
-\r
-    CHAR *ansi_uri = (CHAR *) local_fn;\r
-    gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );\r
-    WCHAR *unicode_uri = (WCHAR *) unicode_fn;\r
-\r
-    // width and height in px\r
-    _width = sp_document_width(doc);\r
-    _height = sp_document_height(doc);\r
-\r
-    NRRect d;\r
-    bool pageBoundingBox;\r
-    pageBoundingBox = mod->get_param_bool("pageBoundingBox");\r
-    if (pageBoundingBox) {\r
-        d.x0 = d.y0 = 0;\r
-        d.x1 = _width;\r
-        d.y1 = _height;\r
-    } else {\r
-        SPItem* doc_item = SP_ITEM(sp_document_root(doc));\r
-        sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);\r
-    }\r
-\r
-    d.x0 *= IN_PER_PX;\r
-    d.y0 *= IN_PER_PX;\r
-    d.x1 *= IN_PER_PX;\r
-    d.y1 *= IN_PER_PX;\r
-\r
-    float dwInchesX = (d.x1 - d.x0);\r
-    float dwInchesY = (d.y1 - d.y0);\r
-\r
-    // dwInchesX x dwInchesY in .01mm units\r
-    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) );\r
-\r
-    // Get a Reference DC\r
-    HDC hScreenDC = GetDC( NULL );\r
-\r
-    // Get the physical characteristics of the reference DC\r
-    float PixelsX = (float) GetDeviceCaps( hScreenDC, HORZRES );\r
-    float PixelsY = (float) GetDeviceCaps( hScreenDC, VERTRES );\r
-    float MMX = (float) GetDeviceCaps( hScreenDC, HORZSIZE );\r
-    float MMY = (float) GetDeviceCaps( hScreenDC, VERTSIZE );\r
-\r
-    // Create the Metafile\r
-    if (PrintWin32::is_os_wide())\r
-        hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, NULL );\r
-    else\r
-        hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, NULL );\r
-\r
-    // Release the reference DC\r
-    ReleaseDC( NULL, hScreenDC );\r
-\r
-    // Did we get a good metafile?\r
-    if (hdc == NULL)\r
-    {\r
-        g_free(local_fn);\r
-        g_free(unicode_fn);\r
-        return 1;\r
-    }\r
-\r
-    // Anisotropic mapping mode\r
-    SetMapMode( hdc, MM_ANISOTROPIC );\r
-\r
-    // Set the Windows extent\r
-    SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL );\r
-\r
-    // Set the viewport extent to reflect\r
-    // dwInchesX" x dwInchesY" in device units\r
-    SetViewportExtEx( hdc,\r
-                      (int) ((float) dwInchesX*25.4f*PixelsX/MMX),\r
-                      (int) ((float) dwInchesY*25.4f*PixelsY/MMY),\r
-                      NULL );\r
-\r
-    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );\r
-\r
-    g_free(local_fn);\r
-    g_free(unicode_fn);\r
-\r
-    return 0;\r
-}\r
-\r
-\r
-unsigned int\r
-PrintEmfWin32::finish (Inkscape::Extension::Print *mod)\r
-{\r
-    if (!hdc) return 0;\r
-\r
-    flush_fill(); // flush any pending fills\r
-\r
-    HENHMETAFILE metafile = CloseEnhMetaFile( hdc );\r
-    if ( metafile ) {\r
-        DeleteEnhMetaFile( metafile );\r
-    }\r
-    DeleteDC( hdc );\r
-\r
-    hdc = NULL;\r
-\r
-    return 0;\r
-}\r
-\r
-\r
-unsigned int\r
-PrintEmfWin32::comment (Inkscape::Extension::Print * module,\r
-                                const char *comment)\r
-{\r
-    if (!hdc) return 0;\r
-\r
-    flush_fill(); // flush any pending fills\r
-\r
-    return 0;\r
-}\r
-\r
-\r
-void\r
-PrintEmfWin32::create_brush(SPStyle const *style)\r
-{\r
-    float rgb[3];\r
-\r
-    if (style) {\r
-        sp_color_get_rgb_floatv( &style->fill.value.color, rgb );\r
-        hbrush = CreateSolidBrush( RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]) );\r
-        hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );\r
-\r
-        SetPolyFillMode( hdc,\r
-                         style->fill_rule.computed == 0 ? WINDING :\r
-                         style->fill_rule.computed == 2 ? ALTERNATE : ALTERNATE );\r
-    } else { // if (!style)\r
-        hbrush = CreateSolidBrush( RGB(255, 255, 255) );\r
-        hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );\r
-        SetPolyFillMode( hdc, ALTERNATE );\r
-    }\r
-}\r
-\r
-\r
-void\r
-PrintEmfWin32::destroy_brush()\r
-{\r
-    SelectObject( hdc, hbrushOld );\r
-    if (hbrush)\r
-        DeleteObject( hbrush );\r
-    hbrush = NULL;\r
-}\r
-\r
-\r
-void\r
-PrintEmfWin32::create_pen(SPStyle const *style)\r
-{\r
-    if (style) {\r
-        float rgb[3];\r
-\r
-        sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);\r
-\r
-        LOGBRUSH lb = {0};\r
-        lb.lbStyle = BS_SOLID;\r
-        lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );\r
-\r
-        int linestyle = PS_SOLID;\r
-        int linecap = 0;\r
-        int linejoin = 0;\r
-        DWORD n_dash = 0;\r
-        DWORD *dash = NULL;\r
-        float oldmiterlimit;\r
-\r
-        DWORD linewidth = MAX( 1, (DWORD) (style->stroke_width.computed * IN_PER_PX * dwDPI) );\r
-\r
-        if (style->stroke_linecap.computed == 0) {\r
-            linecap = PS_ENDCAP_FLAT;\r
-        }\r
-        else if (style->stroke_linecap.computed == 1) {\r
-            linecap = PS_ENDCAP_ROUND;\r
-        }\r
-        else if (style->stroke_linecap.computed == 2) {\r
-            linecap = PS_ENDCAP_SQUARE;\r
-        }\r
-\r
-        if (style->stroke_linejoin.computed == 0) {\r
-            linejoin = PS_JOIN_MITER;\r
-        }\r
-        else if (style->stroke_linejoin.computed == 1) {\r
-            linejoin = PS_JOIN_ROUND;\r
-        }\r
-        else if (style->stroke_linejoin.computed == 2) {\r
-            linejoin = PS_JOIN_BEVEL;\r
-        }\r
-\r
-        if (style->stroke_dash.n_dash   &&\r
-            style->stroke_dash.dash       )\r
-        {\r
-            int i = 0;\r
-            while (linestyle != PS_USERSTYLE &&\r
-                   (i < style->stroke_dash.n_dash)) {\r
-                if (style->stroke_dash.dash[i] > 0.00000001)\r
-                    linestyle = PS_USERSTYLE;\r
-                i++;\r
-            }\r
-\r
-            if (linestyle == PS_USERSTYLE) {\r
-                n_dash = style->stroke_dash.n_dash;\r
-                dash = new DWORD[n_dash];\r
-                for (i = 0; i < style->stroke_dash.n_dash; i++) {\r
-                    dash[i] = (DWORD) (style->stroke_dash.dash[i] * IN_PER_PX * dwDPI);\r
-                }\r
-            }\r
-        }\r
-\r
-        hpen = ExtCreatePen(\r
-            PS_GEOMETRIC | linestyle | linecap | linejoin,\r
-            linewidth,\r
-            &lb,\r
-            n_dash,\r
-            dash );\r
-\r
-        if ( !hpen && linestyle == PS_USERSTYLE ) {\r
-            hpen = ExtCreatePen(\r
-                PS_GEOMETRIC | PS_SOLID | linecap | linejoin,\r
-                linewidth,\r
-                &lb,\r
-                0,\r
-                NULL );\r
-        }\r
-\r
-        if ( !hpen ) {\r
-            hpen = CreatePen(\r
-                PS_SOLID,\r
-                linewidth,\r
-                lb.lbColor );\r
-        }\r
-\r
-        hpenOld = (HPEN) SelectObject( hdc, hpen );\r
-\r
-        if (linejoin == PS_JOIN_MITER) {\r
-            float miterlimit = style->stroke_miterlimit.value;\r
-            if (miterlimit < 1)\r
-                miterlimit = 4.0;\r
-            SetMiterLimit(\r
-                hdc,\r
-                miterlimit * IN_PER_PX * dwDPI,\r
-                &oldmiterlimit );\r
-        }\r
-\r
-        if (n_dash) {\r
-            delete[] dash;\r
-        }\r
-    }\r
-    else { // if (!style)\r
-        hpen = CreatePen( PS_SOLID, 1, RGB(0, 0, 0) );\r
-        hpenOld = (HPEN) SelectObject( hdc, hpen );\r
-    }\r
-}\r
-\r
-\r
-void\r
-PrintEmfWin32::destroy_pen()\r
-{\r
-    SelectObject( hdc, hpenOld );\r
-    if (hpen)\r
-        DeleteObject( hpen );\r
-    hpen = NULL;\r
-}\r
-\r
-\r
-void\r
-PrintEmfWin32::flush_fill()\r
-{\r
-    if (fill_path) {\r
-        print_bpath(fill_path, &fill_transform, &fill_pbox);\r
-        FillPath( hdc );\r
-        destroy_brush();\r
-        delete[] fill_path;\r
-        fill_path = NULL;\r
-    }\r
-}\r
-\r
-\r
-NArtBpath *\r
-PrintEmfWin32::copy_bpath(const NArtBpath *bp)\r
-{\r
-    NArtBpath *tmp = (NArtBpath *) bp;\r
-    int num = 1;\r
-    \r
-    while (tmp->code != NR_END) {\r
-        num++;\r
-        tmp += 1;\r
-    }\r
-\r
-    tmp = new NArtBpath[num];\r
-    while (num--) {\r
-        tmp[num] = bp[num];\r
-    }\r
-\r
-    return tmp;\r
-}\r
-\r
-\r
-int\r
-PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2)\r
-{\r
-    if (!bp1 || !bp2) {\r
-        return 1;\r
-    }\r
-    \r
-    while (bp1->code != NR_END && bp2->code != NR_END) {\r
-        if (bp1->code != bp2->code) {\r
-            return 1;\r
-        }\r
-\r
-        if ( fabs(bp1->x1 - bp2->x1) > 0.00000001 ||\r
-             fabs(bp1->y1 - bp2->y1) > 0.00000001 ||\r
-             fabs(bp1->x2 - bp2->x2) > 0.00000001 ||\r
-             fabs(bp1->y2 - bp2->y2) > 0.00000001 ||\r
-             fabs(bp1->x3 - bp2->x3) > 0.00000001 ||\r
-             fabs(bp1->y3 - bp2->y3) > 0.00000001 )\r
-        {\r
-            return 1;\r
-        }\r
-        \r
-        bp1 += 1;\r
-        bp2 += 1;\r
-    }\r
-    \r
-    return bp1->code != NR_END || bp2->code != NR_END;\r
-}\r
-\r
-\r
-unsigned int\r
-PrintEmfWin32::fill(Inkscape::Extension::Print *mod,\r
-               NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style,\r
-               NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)\r
-{\r
-    if (!hdc) return 0;\r
-\r
-    flush_fill(); // flush any pending fills\r
-\r
-    if (style->fill.type == SP_PAINT_TYPE_COLOR) {\r
-        create_brush(style);\r
-    } else {\r
-        // create_brush(NULL);\r
-        return 0;\r
-    }\r
-\r
-    fill_path = copy_bpath( bpath->path );\r
-    fill_transform = *transform;\r
-    fill_pbox = *pbox;\r
-\r
-    // postpone fill in case of stroke-and-fill\r
-\r
-    return 0;\r
-}\r
-\r
-\r
-unsigned int\r
-PrintEmfWin32::stroke (Inkscape::Extension::Print *mod,\r
-                  const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,\r
-                  const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)\r
-{\r
-    if (!hdc) return 0;\r
-\r
-    bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 );\r
-\r
-    if (!stroke_and_fill) {\r
-        flush_fill(); // flush any pending fills\r
-    }\r
-\r
-    if (style->stroke.type == SP_PAINT_TYPE_COLOR) {\r
-        create_pen(style);\r
-    } else {\r
-        // create_pen(NULL);\r
-        return 0;\r
-    }\r
-\r
-    print_bpath(bpath->path, transform, pbox);\r
-\r
-    if (stroke_and_fill) {\r
-        StrokeAndFillPath( hdc );\r
-        destroy_brush();\r
-        delete[] fill_path;\r
-        fill_path = NULL;\r
-    } else {\r
-        StrokePath( hdc );\r
-    }\r
-\r
-    destroy_pen();\r
-\r
-    return 0;\r
-}\r
-\r
-\r
-unsigned int\r
-PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox)\r
-{\r
-    unsigned int closed;\r
-    NR::Matrix tf = *transform;\r
-\r
-    BeginPath( hdc );\r
-    closed = FALSE;\r
-    while (bp->code != NR_END) {\r
-        using NR::X;\r
-        using NR::Y;\r
-\r
-        NR::Point p1(bp->c(1) * tf);\r
-        NR::Point p2(bp->c(2) * tf);\r
-        NR::Point p3(bp->c(3) * tf);\r
-\r
-        p1[X] = (p1[X] * IN_PER_PX * dwDPI);\r
-        p2[X] = (p2[X] * IN_PER_PX * dwDPI);\r
-        p3[X] = (p3[X] * IN_PER_PX * dwDPI);\r
-        p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);\r
-        p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);\r
-        p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);\r
-\r
-        LONG const x1 = (LONG) round(p1[X]);\r
-        LONG const y1 = (LONG) round(rc.bottom-p1[Y]);\r
-        LONG const x2 = (LONG) round(p2[X]);\r
-        LONG const y2 = (LONG) round(rc.bottom-p2[Y]);\r
-        LONG const x3 = (LONG) round(p3[X]);\r
-        LONG const y3 = (LONG) round(rc.bottom-p3[Y]);\r
-\r
-        switch (bp->code) {\r
-            case NR_MOVETO:\r
-                if (closed) {\r
-                    CloseFigure( hdc );\r
-                }\r
-                closed = TRUE;\r
-                MoveToEx( hdc, x3, y3, NULL );\r
-                break;\r
-            case NR_MOVETO_OPEN:\r
-                if (closed) {\r
-                    CloseFigure( hdc );\r
-                }\r
-                closed = FALSE;\r
-                MoveToEx( hdc, x3, y3, NULL );\r
-                break;\r
-            case NR_LINETO:\r
-                LineTo( hdc, x3, y3 );\r
-                break;\r
-            case NR_CURVETO:\r
-            {\r
-                POINT pt[3];\r
-                pt[0].x = x1;\r
-                pt[0].y = y1;\r
-                pt[1].x = x2;\r
-                pt[1].y = y2;\r
-                pt[2].x = x3;\r
-                pt[2].y = y3;\r
-\r
-                PolyBezierTo( hdc, pt, 3 );\r
-                break;\r
-            }\r
-            default:\r
-                break;\r
-        }\r
-        bp += 1;\r
-    }\r
-    if (closed) {\r
-        CloseFigure( hdc );\r
-    }\r
-    EndPath( hdc );\r
-\r
-    return closed;\r
-}\r
-\r
-\r
-bool\r
-PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)\r
-{\r
-    return ext->get_param_bool("textToPath");\r
-}\r
-\r
-\r
-void\r
-PrintEmfWin32::init (void)\r
-{\r
-    Inkscape::Extension::Extension * ext;\r
-\r
-    /* EMF print */\r
-    ext = Inkscape::Extension::build_from_mem(\r
-        "<inkscape-extension>\n"\r
-        "<name>Enhanced Metafile Print</name>\n"\r
-        "<id>org.inkscape.print.emf.win32</id>\n"\r
-        "<param name=\"destination\" type=\"string\"></param>\n"\r
-        "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"\r
-        "<param name=\"pageBoundingBox\" type=\"boolean\">TRUE</param>\n"\r
-        "<print/>\n"\r
-        "</inkscape-extension>", new PrintEmfWin32());\r
-\r
-    return;\r
-}\r
-\r
-\r
-}  /* namespace Internal */\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
-#endif /* WIN32 */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
+/** \file
+ * Enhanced Metafile Printing.
+ */
+/*
+ * Authors:
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+/*
+ * References:
+ *  - How to Create & Play Enhanced Metafiles in Win32
+ *      http://support.microsoft.com/kb/q145999/
+ *  - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
+ *      http://support.microsoft.com/kb/q66949/
+ *  - Metafile Functions
+ *      http://msdn.microsoft.com/library/en-us/gdi/metafile_0whf.asp
+ *  - Metafile Structures
+ *      http://msdn.microsoft.com/library/en-us/gdi/metafile_5hkj.asp
+ */
+
+#ifdef WIN32
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "libnr/n-art-bpath.h"
+#include "libnr/nr-point-matrix-ops.h"
+#include "libnr/nr-rect.h"
+#include "libnr/nr-matrix.h"
+#include "libnr/nr-matrix-fns.h"
+#include "libnr/nr-path.h"
+#include "libnr/nr-pixblock.h"
+#include "display/canvas-bpath.h"
+#include "sp-item.h"
+
+#include "glib.h"
+#include "gtk/gtkdialog.h"
+#include "gtk/gtkbox.h"
+#include "gtk/gtkstock.h"
+
+#include "glibmm/i18n.h"
+#include "enums.h"
+#include "document.h"
+#include "style.h"
+#include "sp-paint-server.h"
+#include "inkscape_version.h"
+
+#include "win32.h"
+#include "emf-win32-print.h"
+
+#include "unit-constants.h"
+
+#include "extension/extension.h"
+#include "extension/system.h"
+#include "extension/print.h"
+
+#include "io/sys.h"
+
+#include "macros.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+static float dwDPI = 2540;
+
+
+PrintEmfWin32::PrintEmfWin32 (void):
+    hdc(NULL),
+    hbrush(NULL),
+    hpen(NULL),
+    fill_path(NULL)
+{
+}
+
+
+PrintEmfWin32::~PrintEmfWin32 (void)
+{
+    if (hdc) {
+        HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
+        if ( metafile ) {
+            DeleteEnhMetaFile( metafile );
+        }
+        DeleteDC( hdc );
+    }
+
+    /* restore default signal handling for SIGPIPE */
+#if !defined(_WIN32) && !defined(__WIN32__)
+    (void) signal(SIGPIPE, SIG_DFL);
+#endif
+       return;
+}
+
+
+unsigned int
+PrintEmfWin32::setup (Inkscape::Extension::Print *mod)
+{
+    return TRUE;
+}
+
+
+unsigned int
+PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
+{
+    gchar const *utf8_fn = mod->get_param_string("destination");
+
+    gsize bytesRead = 0;
+    gsize bytesWritten = 0;
+    GError* error = NULL;
+    gchar *local_fn =
+        g_filename_from_utf8( utf8_fn, -1,  &bytesRead,  &bytesWritten, &error );
+
+    if (local_fn == NULL) {
+        return 1;
+    }
+
+    CHAR *ansi_uri = (CHAR *) local_fn;
+    gunichar2 *unicode_fn = g_utf8_to_utf16( local_fn, -1, NULL, NULL, NULL );
+    WCHAR *unicode_uri = (WCHAR *) unicode_fn;
+
+    // width and height in px
+    _width = sp_document_width(doc);
+    _height = sp_document_height(doc);
+
+    NRRect d;
+    bool pageBoundingBox;
+    pageBoundingBox = mod->get_param_bool("pageBoundingBox");
+    if (pageBoundingBox) {
+        d.x0 = d.y0 = 0;
+        d.x1 = _width;
+        d.y1 = _height;
+    } else {
+        SPItem* doc_item = SP_ITEM(sp_document_root(doc));
+        sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);
+    }
+
+    d.x0 *= IN_PER_PX;
+    d.y0 *= IN_PER_PX;
+    d.x1 *= IN_PER_PX;
+    d.y1 *= IN_PER_PX;
+
+    float dwInchesX = (d.x1 - d.x0);
+    float dwInchesY = (d.y1 - d.y0);
+
+    // dwInchesX x dwInchesY in .01mm units
+    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) );
+
+    // Get a Reference DC
+    HDC hScreenDC = GetDC( NULL );
+
+    // Get the physical characteristics of the reference DC
+    float PixelsX = (float) GetDeviceCaps( hScreenDC, HORZRES );
+    float PixelsY = (float) GetDeviceCaps( hScreenDC, VERTRES );
+    float MMX = (float) GetDeviceCaps( hScreenDC, HORZSIZE );
+    float MMY = (float) GetDeviceCaps( hScreenDC, VERTSIZE );
+
+    // Create the Metafile
+    if (PrintWin32::is_os_wide())
+        hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, NULL );
+    else
+        hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, NULL );
+
+    // Release the reference DC
+    ReleaseDC( NULL, hScreenDC );
+
+    // Did we get a good metafile?
+    if (hdc == NULL)
+    {
+        g_free(local_fn);
+        g_free(unicode_fn);
+        return 1;
+    }
+
+    // Anisotropic mapping mode
+    SetMapMode( hdc, MM_ANISOTROPIC );
+
+    // Set the Windows extent
+    SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL );
+
+    // Set the viewport extent to reflect
+    // dwInchesX" x dwInchesY" in device units
+    SetViewportExtEx( hdc,
+                      (int) ((float) dwInchesX*25.4f*PixelsX/MMX),
+                      (int) ((float) dwInchesY*25.4f*PixelsY/MMY),
+                      NULL );
+
+    SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) );
+
+    g_free(local_fn);
+    g_free(unicode_fn);
+
+    return 0;
+}
+
+
+unsigned int
+PrintEmfWin32::finish (Inkscape::Extension::Print *mod)
+{
+    if (!hdc) return 0;
+
+    flush_fill(); // flush any pending fills
+
+    HENHMETAFILE metafile = CloseEnhMetaFile( hdc );
+    if ( metafile ) {
+        DeleteEnhMetaFile( metafile );
+    }
+    DeleteDC( hdc );
+
+    hdc = NULL;
+
+    return 0;
+}
+
+
+unsigned int
+PrintEmfWin32::comment (Inkscape::Extension::Print * module,
+                                const char *comment)
+{
+    if (!hdc) return 0;
+
+    flush_fill(); // flush any pending fills
+
+    return 0;
+}
+
+
+void
+PrintEmfWin32::create_brush(SPStyle const *style)
+{
+    float rgb[3];
+
+    if (style) {
+        sp_color_get_rgb_floatv( &style->fill.value.color, rgb );
+        hbrush = CreateSolidBrush( RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]) );
+        hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
+
+        SetPolyFillMode( hdc,
+                         style->fill_rule.computed == 0 ? WINDING :
+                         style->fill_rule.computed == 2 ? ALTERNATE : ALTERNATE );
+    } else { // if (!style)
+        hbrush = CreateSolidBrush( RGB(255, 255, 255) );
+        hbrushOld = (HBRUSH) SelectObject( hdc, hbrush );
+        SetPolyFillMode( hdc, ALTERNATE );
+    }
+}
+
+
+void
+PrintEmfWin32::destroy_brush()
+{
+    SelectObject( hdc, hbrushOld );
+    if (hbrush)
+        DeleteObject( hbrush );
+    hbrush = NULL;
+}
+
+
+void
+PrintEmfWin32::create_pen(SPStyle const *style)
+{
+    if (style) {
+        float rgb[3];
+
+        sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
+
+        LOGBRUSH lb = {0};
+        lb.lbStyle = BS_SOLID;
+        lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] );
+
+        int linestyle = PS_SOLID;
+        int linecap = 0;
+        int linejoin = 0;
+        DWORD n_dash = 0;
+        DWORD *dash = NULL;
+        float oldmiterlimit;
+
+        DWORD linewidth = MAX( 1, (DWORD) (style->stroke_width.computed * IN_PER_PX * dwDPI) );
+
+        if (style->stroke_linecap.computed == 0) {
+            linecap = PS_ENDCAP_FLAT;
+        }
+        else if (style->stroke_linecap.computed == 1) {
+            linecap = PS_ENDCAP_ROUND;
+        }
+        else if (style->stroke_linecap.computed == 2) {
+            linecap = PS_ENDCAP_SQUARE;
+        }
+
+        if (style->stroke_linejoin.computed == 0) {
+            linejoin = PS_JOIN_MITER;
+        }
+        else if (style->stroke_linejoin.computed == 1) {
+            linejoin = PS_JOIN_ROUND;
+        }
+        else if (style->stroke_linejoin.computed == 2) {
+            linejoin = PS_JOIN_BEVEL;
+        }
+
+        if (style->stroke_dash.n_dash   &&
+            style->stroke_dash.dash       )
+        {
+            int i = 0;
+            while (linestyle != PS_USERSTYLE &&
+                   (i < style->stroke_dash.n_dash)) {
+                if (style->stroke_dash.dash[i] > 0.00000001)
+                    linestyle = PS_USERSTYLE;
+                i++;
+            }
+
+            if (linestyle == PS_USERSTYLE) {
+                n_dash = style->stroke_dash.n_dash;
+                dash = new DWORD[n_dash];
+                for (i = 0; i < style->stroke_dash.n_dash; i++) {
+                    dash[i] = (DWORD) (style->stroke_dash.dash[i] * IN_PER_PX * dwDPI);
+                }
+            }
+        }
+
+        hpen = ExtCreatePen(
+            PS_GEOMETRIC | linestyle | linecap | linejoin,
+            linewidth,
+            &lb,
+            n_dash,
+            dash );
+
+        if ( !hpen && linestyle == PS_USERSTYLE ) {
+            hpen = ExtCreatePen(
+                PS_GEOMETRIC | PS_SOLID | linecap | linejoin,
+                linewidth,
+                &lb,
+                0,
+                NULL );
+        }
+
+        if ( !hpen ) {
+            hpen = CreatePen(
+                PS_SOLID,
+                linewidth,
+                lb.lbColor );
+        }
+
+        hpenOld = (HPEN) SelectObject( hdc, hpen );
+
+        if (linejoin == PS_JOIN_MITER) {
+            float miterlimit = style->stroke_miterlimit.value;
+            if (miterlimit < 1)
+                miterlimit = 4.0;
+            SetMiterLimit(
+                hdc,
+                miterlimit * IN_PER_PX * dwDPI,
+                &oldmiterlimit );
+        }
+
+        if (n_dash) {
+            delete[] dash;
+        }
+    }
+    else { // if (!style)
+        hpen = CreatePen( PS_SOLID, 1, RGB(0, 0, 0) );
+        hpenOld = (HPEN) SelectObject( hdc, hpen );
+    }
+}
+
+
+void
+PrintEmfWin32::destroy_pen()
+{
+    SelectObject( hdc, hpenOld );
+    if (hpen)
+        DeleteObject( hpen );
+    hpen = NULL;
+}
+
+
+void
+PrintEmfWin32::flush_fill()
+{
+    if (fill_path) {
+        print_bpath(fill_path, &fill_transform, &fill_pbox);
+        FillPath( hdc );
+        destroy_brush();
+        delete[] fill_path;
+        fill_path = NULL;
+    }
+}
+
+
+NArtBpath *
+PrintEmfWin32::copy_bpath(const NArtBpath *bp)
+{
+    NArtBpath *tmp = (NArtBpath *) bp;
+    int num = 1;
+    
+    while (tmp->code != NR_END) {
+        num++;
+        tmp += 1;
+    }
+
+    tmp = new NArtBpath[num];
+    while (num--) {
+        tmp[num] = bp[num];
+    }
+
+    return tmp;
+}
+
+
+int
+PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2)
+{
+    if (!bp1 || !bp2) {
+        return 1;
+    }
+    
+    while (bp1->code != NR_END && bp2->code != NR_END) {
+        if (bp1->code != bp2->code) {
+            return 1;
+        }
+
+        if ( fabs(bp1->x1 - bp2->x1) > 0.00000001 ||
+             fabs(bp1->y1 - bp2->y1) > 0.00000001 ||
+             fabs(bp1->x2 - bp2->x2) > 0.00000001 ||
+             fabs(bp1->y2 - bp2->y2) > 0.00000001 ||
+             fabs(bp1->x3 - bp2->x3) > 0.00000001 ||
+             fabs(bp1->y3 - bp2->y3) > 0.00000001 )
+        {
+            return 1;
+        }
+        
+        bp1 += 1;
+        bp2 += 1;
+    }
+    
+    return bp1->code != NR_END || bp2->code != NR_END;
+}
+
+
+unsigned int
+PrintEmfWin32::fill(Inkscape::Extension::Print *mod,
+               NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style,
+               NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
+{
+    if (!hdc) return 0;
+
+    flush_fill(); // flush any pending fills
+
+    if (style->fill.type == SP_PAINT_TYPE_COLOR) {
+        create_brush(style);
+    } else {
+        // create_brush(NULL);
+        return 0;
+    }
+
+    fill_path = copy_bpath( bpath->path );
+    fill_transform = *transform;
+    fill_pbox = *pbox;
+
+    // postpone fill in case of stroke-and-fill
+
+    return 0;
+}
+
+
+unsigned int
+PrintEmfWin32::stroke (Inkscape::Extension::Print *mod,
+                  const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,
+                  const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)
+{
+    if (!hdc) return 0;
+
+    bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 );
+
+    if (!stroke_and_fill) {
+        flush_fill(); // flush any pending fills
+    }
+
+    if (style->stroke.type == SP_PAINT_TYPE_COLOR) {
+        create_pen(style);
+    } else {
+        // create_pen(NULL);
+        return 0;
+    }
+
+    print_bpath(bpath->path, transform, pbox);
+
+    if (stroke_and_fill) {
+        StrokeAndFillPath( hdc );
+        destroy_brush();
+        delete[] fill_path;
+        fill_path = NULL;
+    } else {
+        StrokePath( hdc );
+    }
+
+    destroy_pen();
+
+    return 0;
+}
+
+
+unsigned int
+PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox)
+{
+    unsigned int closed;
+    NR::Matrix tf = *transform;
+
+    BeginPath( hdc );
+    closed = FALSE;
+    while (bp->code != NR_END) {
+        using NR::X;
+        using NR::Y;
+
+        NR::Point p1(bp->c(1) * tf);
+        NR::Point p2(bp->c(2) * tf);
+        NR::Point p3(bp->c(3) * tf);
+
+        p1[X] = (p1[X] * IN_PER_PX * dwDPI);
+        p2[X] = (p2[X] * IN_PER_PX * dwDPI);
+        p3[X] = (p3[X] * IN_PER_PX * dwDPI);
+        p1[Y] = (p1[Y] * IN_PER_PX * dwDPI);
+        p2[Y] = (p2[Y] * IN_PER_PX * dwDPI);
+        p3[Y] = (p3[Y] * IN_PER_PX * dwDPI);
+
+        LONG const x1 = (LONG) round(p1[X]);
+        LONG const y1 = (LONG) round(rc.bottom-p1[Y]);
+        LONG const x2 = (LONG) round(p2[X]);
+        LONG const y2 = (LONG) round(rc.bottom-p2[Y]);
+        LONG const x3 = (LONG) round(p3[X]);
+        LONG const y3 = (LONG) round(rc.bottom-p3[Y]);
+
+        switch (bp->code) {
+            case NR_MOVETO:
+                if (closed) {
+                    CloseFigure( hdc );
+                }
+                closed = TRUE;
+                MoveToEx( hdc, x3, y3, NULL );
+                break;
+            case NR_MOVETO_OPEN:
+                if (closed) {
+                    CloseFigure( hdc );
+                }
+                closed = FALSE;
+                MoveToEx( hdc, x3, y3, NULL );
+                break;
+            case NR_LINETO:
+                LineTo( hdc, x3, y3 );
+                break;
+            case NR_CURVETO:
+            {
+                POINT pt[3];
+                pt[0].x = x1;
+                pt[0].y = y1;
+                pt[1].x = x2;
+                pt[1].y = y2;
+                pt[2].x = x3;
+                pt[2].y = y3;
+
+                PolyBezierTo( hdc, pt, 3 );
+                break;
+            }
+            default:
+                break;
+        }
+        bp += 1;
+    }
+    if (closed) {
+        CloseFigure( hdc );
+    }
+    EndPath( hdc );
+
+    return closed;
+}
+
+
+bool
+PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext)
+{
+    return ext->get_param_bool("textToPath");
+}
+
+
+void
+PrintEmfWin32::init (void)
+{
+    Inkscape::Extension::Extension * ext;
+
+    /* EMF print */
+    ext = Inkscape::Extension::build_from_mem(
+        "<inkscape-extension>\n"
+        "<name>Enhanced Metafile Print</name>\n"
+        "<id>org.inkscape.print.emf.win32</id>\n"
+        "<param name=\"destination\" type=\"string\"></param>\n"
+        "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"
+        "<param name=\"pageBoundingBox\" type=\"boolean\">TRUE</param>\n"
+        "<print/>\n"
+        "</inkscape-extension>", new PrintEmfWin32());
+
+    return;
+}
+
+
+}  /* namespace Internal */
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+#endif /* WIN32 */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index d1ac819391974087e2bdf1107b09ef8b7d1d148a..305507824226159f969a6892835539a60fe41037 100644 (file)
-#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__\r
-#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__\r
-\r
-/*\r
- * Enhanced Metafile Printing.\r
- *\r
- * Author:\r
- *   Ulf Erikson <ulferikson@users.sf.net>\r
- *\r
- * Copyright (C) 2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef WIN32\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-#include "extension/implementation/implementation.h"\r
-#include "extension/extension.h"\r
-\r
-#include "svg/stringstream.h"\r
-#include "libnr/nr-matrix.h"\r
-#include "libnr/nr-rect.h"\r
-\r
-#define WIN32_LEAN_AND_MEAN\r
-#include <windows.h>\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-class PrintEmfWin32 : public Inkscape::Extension::Implementation::Implementation\r
-{\r
-    double  _width;\r
-    double  _height;\r
-    HDC    hdc;\r
-    RECT   rc;\r
-\r
-    HBRUSH hbrush, hbrushOld;\r
-    HPEN hpen, hpenOld;\r
-\r
-    NArtBpath *fill_path;\r
-    NArtBpath *fill_path_copy;\r
-    NRMatrix fill_transform;\r
-    NRRect fill_pbox;\r
-\r
-    unsigned int print_bpath (const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox);\r
-\r
-public:\r
-    PrintEmfWin32 (void);\r
-    virtual ~PrintEmfWin32 (void);\r
-\r
-    /* Print functions */\r
-    virtual unsigned int setup (Inkscape::Extension::Print * module);\r
-\r
-    virtual unsigned int begin (Inkscape::Extension::Print * module, SPDocument *doc);\r
-    virtual unsigned int finish (Inkscape::Extension::Print * module);\r
-\r
-    /* Rendering methods */\r
-    virtual unsigned int fill (Inkscape::Extension::Print * module,\r
-                               const NRBPath *bpath, const NRMatrix *ctm, const SPStyle *style,\r
-                               const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);\r
-    virtual unsigned int stroke (Inkscape::Extension::Print * module,\r
-                                 const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,\r
-                                 const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);\r
-    virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment);\r
-    bool textToPath (Inkscape::Extension::Print * ext);\r
-\r
-    static void init (void);\r
-\r
-protected:\r
-    void create_brush(SPStyle const *style);\r
-\r
-    void destroy_brush();\r
-\r
-    void create_pen(SPStyle const *style);\r
-\r
-    void destroy_pen();\r
-\r
-    void flush_fill();\r
-\r
-    NArtBpath *copy_bpath(const NArtBpath *bp);\r
-    int cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2);\r
-\r
-};\r
-\r
-}  /* namespace Internal */\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
-#endif /* WIN32 */\r
-\r
-#endif /* __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__ */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:cpp\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__
+#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__
+
+/*
+ * Enhanced Metafile Printing.
+ *
+ * Author:
+ *   Ulf Erikson <ulferikson@users.sf.net>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef WIN32
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "extension/implementation/implementation.h"
+#include "extension/extension.h"
+
+#include "svg/stringstream.h"
+#include "libnr/nr-matrix.h"
+#include "libnr/nr-rect.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class PrintEmfWin32 : public Inkscape::Extension::Implementation::Implementation
+{
+    double  _width;
+    double  _height;
+    HDC    hdc;
+    RECT   rc;
+
+    HBRUSH hbrush, hbrushOld;
+    HPEN hpen, hpenOld;
+
+    NArtBpath *fill_path;
+    NArtBpath *fill_path_copy;
+    NRMatrix fill_transform;
+    NRRect fill_pbox;
+
+    unsigned int print_bpath (const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox);
+
+public:
+    PrintEmfWin32 (void);
+    virtual ~PrintEmfWin32 (void);
+
+    /* Print functions */
+    virtual unsigned int setup (Inkscape::Extension::Print * module);
+
+    virtual unsigned int begin (Inkscape::Extension::Print * module, SPDocument *doc);
+    virtual unsigned int finish (Inkscape::Extension::Print * module);
+
+    /* Rendering methods */
+    virtual unsigned int fill (Inkscape::Extension::Print * module,
+                               const NRBPath *bpath, const NRMatrix *ctm, const SPStyle *style,
+                               const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);
+    virtual unsigned int stroke (Inkscape::Extension::Print * module,
+                                 const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style,
+                                 const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);
+    virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment);
+    bool textToPath (Inkscape::Extension::Print * ext);
+
+    static void init (void);
+
+protected:
+    void create_brush(SPStyle const *style);
+
+    void destroy_brush();
+
+    void create_pen(SPStyle const *style);
+
+    void destroy_pen();
+
+    void flush_fill();
+
+    NArtBpath *copy_bpath(const NArtBpath *bp);
+    int cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2);
+
+};
+
+}  /* namespace Internal */
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+#endif /* WIN32 */
+
+#endif /* __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__ */
+
+/*
+  Local Variables:
+  mode:cpp
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 49562bfd6b866addb0fd4e2b0e66a6273cb124af..af4a3d02fec8f87662346480c061e2582482ecc3 100644 (file)
@@ -1,28 +1,28 @@
 /* POLE - Portable C++ library to access OLE Storage 
    Copyright (C) 2002-2005 Ariya Hidayat <ariya@kde.org>
-\r
-   Redistribution and use in source and binary forms, with or without \r
-   modification, are permitted provided that the following conditions \r
-   are met:\r
-   * Redistributions of source code must retain the above copyright notice, \r
-     this list of conditions and the following disclaimer.\r
-   * Redistributions in binary form must reproduce the above copyright notice, \r
-     this list of conditions and the following disclaimer in the documentation \r
-     and/or other materials provided with the distribution.\r
-   * Neither the name of the authors nor the names of its contributors may be \r
-     used to endorse or promote products derived from this software without \r
-     specific prior written permission.\r
-\r
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" \r
-   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
-   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
-   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
-   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
-   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
-   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
-   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
-   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
-   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF \r
+
+   Redistribution and use in source and binary forms, with or without 
+   modification, are permitted provided that the following conditions 
+   are met:
+   * Redistributions of source code must retain the above copyright notice, 
+     this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright notice, 
+     this list of conditions and the following disclaimer in the documentation 
+     and/or other materials provided with the distribution.
+   * Neither the name of the authors nor the names of its contributors may be 
+     used to endorse or promote products derived from this software without 
+     specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
    THE POSSIBILITY OF SUCH DAMAGE.
 */
 
@@ -46,10 +46,10 @@ class Storage
   friend class Stream;
 
 public:
-\r
+
   // for Storage::result()
-  enum { Ok, OpenFailed, NotOLE, BadOLE, UnknownError };\r
-  \r
+  enum { Ok, OpenFailed, NotOLE, BadOLE, UnknownError };
+  
   /**
    * Constructs a storage with data.
    **/
@@ -84,19 +84,19 @@ class Stream
   friend class Storage;
   friend class StorageIO;
   
-public:\r
-\r
-  /**\r
-   * Creates a new stream.\r
-   */\r
-  // name must be absolute, e.g "/PerfectOffice_MAIN"\r
-  Stream( Storage* storage, const std::string& name );\r
-\r
-  /**\r
-   * Destroys the stream.\r
-   */\r
+public:
+
+  /**
+   * Creates a new stream.
+   */
+  // name must be absolute, e.g "/PerfectOffice_MAIN"
+  Stream( Storage* storage, const std::string& name );
+
+  /**
+   * Destroys the stream.
+   */
   ~Stream();
-\r
+
   /**
    * Returns the stream size.
    **/
@@ -105,11 +105,11 @@ public:
   /**
    * Reads a block of data.
    **/
-  unsigned long read( unsigned char* data, unsigned long maxlen );\r
-  \r
+  unsigned long read( unsigned char* data, unsigned long maxlen );
+  
 private:
   StreamIO* io;
-\r
+
   // no copy or assign
   Stream( const Stream& );
   Stream& operator=( const Stream& );    
index dcdc44c5037af3bff8e78c3bc4d04e29430a02bb..e25b53aabc9d64a7d55999339127a93492b7ed8a 100644 (file)
-/* libwpg\r
- * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)\r
- * Copyright (C) 2004 Marc Oude Kotte (marc@solcon.nl)\r
- * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Library General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Library General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Library General Public\r
- * License along with this library; if not, write to the \r
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, \r
- * Boston, MA  02111-1301 USA\r
- *\r
- * For further information visit http://libwpg.sourceforge.net\r
- */\r
\r
-/* "This product is not manufactured, approved, or supported by\r
- * Corel Corporation or Corel Corporation Limited."\r
- */\r
-\r
-#include "WPGXParser.h"\r
-\r
-using namespace libwpg;\r
-\r
-WPGXParser::WPGXParser(WPGInputStream *input, WPGPaintInterface* painter):\r
-  m_input(input), m_painter(painter)\r
-{\r
-}\r
-\r
-unsigned char WPGXParser::readU8()\r
-{\r
-       return m_input->getc();\r
-}\r
-\r
-unsigned short WPGXParser::readU16()\r
-{\r
-       unsigned short p0 = (unsigned short)readU8();\r
-       unsigned short p1 = (unsigned short)readU8();\r
-       return p0|(p1<<8);\r
-}\r
-\r
-unsigned long WPGXParser::readU32()\r
-{\r
-       unsigned long p0 = (unsigned short)readU8();\r
-       unsigned long p1 = (unsigned short)readU8();\r
-       unsigned long p2 = (unsigned short)readU8();\r
-       unsigned long p3 = (unsigned short)readU8();\r
-       return p0|(p1<<8)|(p2<<16)|(p3<<24);\r
-}\r
-\r
-char WPGXParser::readS8()\r
-{\r
-       return (char)m_input->getc();\r
-}\r
-\r
-short WPGXParser::readS16()\r
-{\r
-       short p0 = readU8();\r
-       short p1 = readS8();\r
-       return p0|(p1<<8);\r
-}\r
-\r
-long WPGXParser::readS32()\r
-{\r
-       long p0 = readU8();\r
-       long p1 = readU8();\r
-       long p2 = readU8();\r
-       long p3 = readS8();\r
-       return p0|(p1<<8)|(p2<<16)|(p3<<24);\r
-}\r
-\r
-unsigned int WPGXParser::readVariableLengthInteger()\r
-{\r
-       // read a byte\r
-       unsigned char value8 = readU8();\r
-       // if it's in the range 0-0xFE, then we have a 8-bit value\r
-       if (value8<=0xFE) {\r
-               return (unsigned int)value8;\r
-       } else {\r
-               // now read a 16 bit value\r
-               unsigned short value16 = readU16();\r
-               // if the MSB is 1, we have a 32 bit value\r
-               if (value16>>15) {\r
-                       // read the next 16 bit value (LSB part, in value16 resides the MSB part)\r
-                       unsigned long lvalue16 = readU16();\r
-                       unsigned long value32 = value16 & 0x7fff;  // mask out the MSB\r
-                       return (value32<<16)+lvalue16;\r
-               } else {\r
-                       // we have a 16 bit value, return it\r
-                       return (unsigned int)value16;\r
-               }\r
-       }\r
-       \r
-       // unreachable\r
-       return 0;\r
-}\r
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc@solcon.nl)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGXParser.h"
+
+using namespace libwpg;
+
+WPGXParser::WPGXParser(WPGInputStream *input, WPGPaintInterface* painter):
+  m_input(input), m_painter(painter)
+{
+}
+
+unsigned char WPGXParser::readU8()
+{
+       return m_input->getc();
+}
+
+unsigned short WPGXParser::readU16()
+{
+       unsigned short p0 = (unsigned short)readU8();
+       unsigned short p1 = (unsigned short)readU8();
+       return p0|(p1<<8);
+}
+
+unsigned long WPGXParser::readU32()
+{
+       unsigned long p0 = (unsigned short)readU8();
+       unsigned long p1 = (unsigned short)readU8();
+       unsigned long p2 = (unsigned short)readU8();
+       unsigned long p3 = (unsigned short)readU8();
+       return p0|(p1<<8)|(p2<<16)|(p3<<24);
+}
+
+char WPGXParser::readS8()
+{
+       return (char)m_input->getc();
+}
+
+short WPGXParser::readS16()
+{
+       short p0 = readU8();
+       short p1 = readS8();
+       return p0|(p1<<8);
+}
+
+long WPGXParser::readS32()
+{
+       long p0 = readU8();
+       long p1 = readU8();
+       long p2 = readU8();
+       long p3 = readS8();
+       return p0|(p1<<8)|(p2<<16)|(p3<<24);
+}
+
+unsigned int WPGXParser::readVariableLengthInteger()
+{
+       // read a byte
+       unsigned char value8 = readU8();
+       // if it's in the range 0-0xFE, then we have a 8-bit value
+       if (value8<=0xFE) {
+               return (unsigned int)value8;
+       } else {
+               // now read a 16 bit value
+               unsigned short value16 = readU16();
+               // if the MSB is 1, we have a 32 bit value
+               if (value16>>15) {
+                       // read the next 16 bit value (LSB part, in value16 resides the MSB part)
+                       unsigned long lvalue16 = readU16();
+                       unsigned long value32 = value16 & 0x7fff;  // mask out the MSB
+                       return (value32<<16)+lvalue16;
+               } else {
+                       // we have a 16 bit value, return it
+                       return (unsigned int)value16;
+               }
+       }
+       
+       // unreachable
+       return 0;
+}
index 71c78d2c0c44e1aa55040eefcc8e0d0e25ebf69f..d7fd4cb5af20ef67ec58813b02b04ff42da158a2 100644 (file)
@@ -1,60 +1,60 @@
-/* libwpg\r
- * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)\r
- * Copyright (C) 2004 Marc Oude Kotte (marc@solcon.nl)\r
- * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Library General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Library General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Library General Public\r
- * License along with this library; if not, write to the \r
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, \r
- * Boston, MA  02111-1301 USA\r
- *\r
- * For further information visit http://libwpg.sourceforge.net\r
- */\r
-\r
-/* "This product is not manufactured, approved, or supported by\r
- * Corel Corporation or Corel Corporation Limited."\r
- */\r
-\r
-#ifndef __WPGXPARSER_H__\r
-#define __WPGXPARSER_H__\r
-\r
-#include "WPGPaintInterface.h"\r
-#include "WPGStream.h"\r
-#include "WPGColor.h"\r
-\r
-#include <map>\r
-\r
-using namespace libwpg;\r
-\r
-class WPGXParser\r
-{\r
-public:\r
-       WPGXParser(WPGInputStream *input, WPGPaintInterface* painter);\r
-       virtual ~WPGXParser() {}\r
-       virtual bool parse() = 0;\r
-       \r
-       unsigned char readU8();\r
-       unsigned short readU16();  \r
-       unsigned long readU32();  \r
-       char readS8();\r
-       short readS16();  \r
-       long readS32();  \r
-       unsigned int readVariableLengthInteger();\r
-       \r
-protected:\r
-       WPGInputStream* m_input;\r
-       WPGPaintInterface* m_painter;\r
-       std::map<int,WPGColor> m_colorPalette;\r
-};\r
-\r
-#endif // __WPGXPARSER_H__\r
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc@solcon.nl)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGXPARSER_H__
+#define __WPGXPARSER_H__
+
+#include "WPGPaintInterface.h"
+#include "WPGStream.h"
+#include "WPGColor.h"
+
+#include <map>
+
+using namespace libwpg;
+
+class WPGXParser
+{
+public:
+       WPGXParser(WPGInputStream *input, WPGPaintInterface* painter);
+       virtual ~WPGXParser() {}
+       virtual bool parse() = 0;
+       
+       unsigned char readU8();
+       unsigned short readU16();  
+       unsigned long readU32();  
+       char readS8();
+       short readS16();  
+       long readS32();  
+       unsigned int readVariableLengthInteger();
+       
+protected:
+       WPGInputStream* m_input;
+       WPGPaintInterface* m_painter;
+       std::map<int,WPGColor> m_colorPalette;
+};
+
+#endif // __WPGXPARSER_H__
index a7454d2a10ee7aea6c2bf7831b6fc39d110ee5e6..e120b802e6aee5b17312b7f20e5af8af9613ee7a 100644 (file)
@@ -1,83 +1,83 @@
-/* libwpg\r
- * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Library General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Library General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Library General Public\r
- * License along with this library; if not, write to the \r
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, \r
- * Boston, MA  02111-1301 USA\r
- *\r
- * For further information visit http://libwpg.sourceforge.net\r
- */\r
-\r
-/* "This product is not manufactured, approved, or supported by\r
- * Corel Corporation or Corel Corporation Limited."\r
- */\r
-\r
-#include "WPGraphics.h"\r
-#include "WPGHeader.h"\r
-#include "WPGStream.h"\r
-#include "WPGXParser.h"\r
-#include "WPG1Parser.h"\r
-#include "WPG2Parser.h"\r
-#include "libwpg_utils.h"\r
-\r
-using namespace libwpg;\r
-\r
-bool WPGraphics::isSupported(WPGInputStream* input)\r
-{\r
-       WPGHeader header;\r
-       if(!header.load(input))\r
-               return false;\r
-       \r
-       return header.isSupported();\r
-}\r
-\r
-bool WPGraphics::parse(WPGInputStream* input, WPGPaintInterface* painter)\r
-{\r
-       WPGXParser *parser = 0;\r
-       \r
-       WPG_DEBUG_MSG(("Loading header...\n"));\r
-       WPGHeader header;\r
-       if(!header.load(input))\r
-               return false;\r
-       \r
-       if(!header.isSupported())\r
-       {\r
-               WPG_DEBUG_MSG(("Unsupported file format!\n"));\r
-               return false;  \r
-       }\r
-       \r
-       // seek to the start of document\r
-       input->seek(header.startOfDocument());\r
-       \r
-       switch (header.majorVersion()) {\r
-               case 0x01: // WPG1\r
-                       WPG_DEBUG_MSG(("Parsing WPG1\n"));\r
-                       parser = new WPG1Parser(input, painter);\r
-                       parser->parse();\r
-                       break;\r
-               case 0x02: // WPG2\r
-                       WPG_DEBUG_MSG(("Parsing WPG2\n"));\r
-                       parser = new WPG2Parser(input, painter);\r
-                       parser->parse();\r
-                       break;\r
-               default: // other :-)\r
-                       WPG_DEBUG_MSG(("Unknown format\n"));\r
-                       break;\r
-       }\r
-       \r
-       delete parser;\r
-       \r
-       return false;\r
-}\r
\r
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGraphics.h"
+#include "WPGHeader.h"
+#include "WPGStream.h"
+#include "WPGXParser.h"
+#include "WPG1Parser.h"
+#include "WPG2Parser.h"
+#include "libwpg_utils.h"
+
+using namespace libwpg;
+
+bool WPGraphics::isSupported(WPGInputStream* input)
+{
+       WPGHeader header;
+       if(!header.load(input))
+               return false;
+       
+       return header.isSupported();
+}
+
+bool WPGraphics::parse(WPGInputStream* input, WPGPaintInterface* painter)
+{
+       WPGXParser *parser = 0;
+       
+       WPG_DEBUG_MSG(("Loading header...\n"));
+       WPGHeader header;
+       if(!header.load(input))
+               return false;
+       
+       if(!header.isSupported())
+       {
+               WPG_DEBUG_MSG(("Unsupported file format!\n"));
+               return false;  
+       }
+       
+       // seek to the start of document
+       input->seek(header.startOfDocument());
+       
+       switch (header.majorVersion()) {
+               case 0x01: // WPG1
+                       WPG_DEBUG_MSG(("Parsing WPG1\n"));
+                       parser = new WPG1Parser(input, painter);
+                       parser->parse();
+                       break;
+               case 0x02: // WPG2
+                       WPG_DEBUG_MSG(("Parsing WPG2\n"));
+                       parser = new WPG2Parser(input, painter);
+                       parser->parse();
+                       break;
+               default: // other :-)
+                       WPG_DEBUG_MSG(("Unknown format\n"));
+                       break;
+       }
+       
+       delete parser;
+       
+       return false;
+}
index 3226835cab6ef4555c08832ad6d6bb47170410a1..21abddd1b3efaf9656c25baee526bb023ccf1985 100644 (file)
@@ -1,46 +1,46 @@
-/* libwpg\r
- * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Library General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Library General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Library General Public\r
- * License along with this library; if not, write to the \r
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, \r
- * Boston, MA  02111-1301 USA\r
- *\r
- * For further information visit http://libwpg.sourceforge.net\r
- */\r
-\r
-/* "This product is not manufactured, approved, or supported by\r
- * Corel Corporation or Corel Corporation Limited."\r
- */\r
-\r
-#ifndef __WPGRAPHICS_H__\r
-#define __WPGRAPHICS_H__\r
-\r
-namespace libwpg\r
-{\r
-\r
-class WPGInputStream;\r
-class WPGPaintInterface;\r
-\r
-class WPGraphics\r
-{\r
-public:\r
-       \r
-       static bool isSupported(WPGInputStream* input);\r
-       \r
-       static bool parse(WPGInputStream* input, WPGPaintInterface* painter);\r
-};\r
-\r
-} // namespace libwpg\r
-\r
-#endif //  __WPGRAPHICS_H__\r
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGRAPHICS_H__
+#define __WPGRAPHICS_H__
+
+namespace libwpg
+{
+
+class WPGInputStream;
+class WPGPaintInterface;
+
+class WPGraphics
+{
+public:
+       
+       static bool isSupported(WPGInputStream* input);
+       
+       static bool parse(WPGInputStream* input, WPGPaintInterface* painter);
+};
+
+} // namespace libwpg
+
+#endif //  __WPGRAPHICS_H__
index 28e9476149c4c3bb736773b4b900c91c13c37fd1..0326b150adc26a6832c6f367a1d1b251f7bd42e0 100644 (file)
-/* \r
- *  This file came from libwpg as a source, their utility wpg2svg\r
- *  specifically.  It has been modified to work as an Inkscape extension.\r
- *  The Inkscape extension code is covered by this copyright, but the\r
- *  rest is covered by the one bellow.\r
- *\r
- * Authors:\r
- *   Ted Gould <ted@gould.cx>\r
- *\r
- * Copyright (C) 2006 Authors\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- *\r
- */\r
-\r
-/* libwpg\r
- * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)\r
- * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Library General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Library General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Library General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\r
- *\r
- * For further information visit http://libwpg.sourceforge.net\r
- */\r
-\r
-/* "This product is not manufactured, approved, or supported by\r
- * Corel Corporation or Corel Corporation Limited."\r
- */\r
-\r
-#include <stdio.h>\r
-\r
-#include "wpg-input.h"\r
-#include "extension/system.h"\r
-#include "extension/input.h"\r
-#include "document.h"\r
-\r
-#include "libwpg/libwpg.h"\r
-#include "libwpg/WPGStreamImplementation.h"\r
-\r
-using namespace libwpg;\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-namespace Internal {\r
-\r
-class InkscapePainter : public libwpg::WPGPaintInterface {\r
-public:\r
-       InkscapePainter();\r
-\r
-       void startDocument(double imageWidth, double imageHeight);\r
-       void endDocument();\r
-       void startLayer(unsigned int id);\r
-       void endLayer(unsigned int id);\r
-\r
-       void setPen(const WPGPen& pen);\r
-       void setBrush(const WPGBrush& brush);\r
-       void setFillRule(FillRule rule);\r
-\r
-       void drawRectangle(const WPGRect& rect, double rx, double ry);\r
-       void drawEllipse(const WPGPoint& center, double rx, double ry);\r
-       void drawPolygon(const WPGPointArray& vertices);\r
-       void drawPath(const WPGPath& path);\r
-\r
-private:\r
-       WPGPen m_pen;\r
-       WPGBrush m_brush;\r
-       FillRule m_fillRule;\r
-       int m_gradientIndex;\r
-       void writeStyle();\r
-        void printf (char * fmt, ...) {\r
-            va_list args;\r
-            va_start(args, fmt);\r
-            gchar * buf = g_strdup_vprintf(fmt, args);\r
-            va_end(args);\r
-            if (buf) {\r
-                document += buf;\r
-                g_free(buf);\r
-            }\r
-        }\r
-\r
-public:\r
-        Glib::ustring document;\r
-};\r
-\r
-InkscapePainter::InkscapePainter(): m_fillRule(AlternatingFill), m_gradientIndex(1)\r
-{\r
-}\r
-\r
-void InkscapePainter::startDocument(double width, double height) \r
-{\r
-        document = "";\r
-       printf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");\r
-       printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"");\r
-       printf(" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");\r
-\r
-//     printf("<!-- Created with wpg2svg/libwpg %s -->\n", LIBWPG_VERSION_STRING);\r
-\r
-       printf("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" ");\r
-       printf("xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");        \r
-       printf("width=\"%g\" height=\"%f\" >\n", 72*width, 72*height);\r
-       \r
-       m_gradientIndex = 1;\r
-}\r
-\r
-void InkscapePainter::endDocument()\r
-{\r
-       printf("</svg>\n");\r
-}\r
-\r
-void InkscapePainter::setPen(const WPGPen& pen)\r
-{\r
-       m_pen = pen;\r
-}\r
-\r
-void InkscapePainter::setBrush(const WPGBrush& brush)\r
-{\r
-       m_brush = brush;\r
-       \r
-       if(m_brush.style == WPGBrush::Gradient)\r
-       {\r
-               double angle = m_brush.gradient.angle();\r
-\r
-               printf("<defs>\n");\r
-               printf("  <linearGradient id=\"grad%d\" >\n", m_gradientIndex++);\r
-               for(unsigned c = 0; c < m_brush.gradient.count(); c++)\r
-               {\r
-                       // round to nearest percentage\r
-                       int ofs = (int)(100.0*m_brush.gradient.stopOffset(c)+0.5);\r
-\r
-                       WPGColor color = m_brush.gradient.stopColor(c);\r
-                       printf("    <stop offset=\"%d%%\" stop-color=\"#%02x%02x%02x\" />\n",\r
-                               ofs, color.red, color.green, color.blue);\r
-               }\r
-               printf("  </linearGradient>\n");\r
-               \r
-               // not a simple horizontal gradient\r
-               if(angle != -90.0)\r
-               {\r
-                       printf("  <linearGradient xlink:href=\"#grad%d\"", m_gradientIndex-1);\r
-                       printf(" id=\"grad%d\" ", m_gradientIndex++);\r
-                       printf("x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" "); \r
-                       printf("gradientTransform=\"rotate(%f)\" ", angle);\r
-                       printf("gradientUnits=\"objectBoundingBox\" >\n");\r
-                       printf("  </linearGradient>\n");\r
-               }\r
-               \r
-               printf("</defs>\n");\r
-       }\r
-}\r
-\r
-void InkscapePainter::setFillRule(FillRule rule)\r
-{\r
-       m_fillRule = rule;\r
-}\r
-\r
-void InkscapePainter::startLayer(unsigned int id)\r
-{\r
-       printf("<g id=\"Layer%d\" >\n", id);\r
-}\r
-\r
-void InkscapePainter::endLayer(unsigned int)\r
-{\r
-       printf("</g>\n");\r
-}\r
-\r
-void InkscapePainter::drawRectangle(const WPGRect& rect, double rx, double ry)\r
-{\r
-       printf("<rect ");\r
-       printf("x=\"%f\" y=\"%f\" ", 72*rect.x1, 72*rect.y1);\r
-       printf("width=\"%f\" height=\"%f\" ", 72*rect.width(), 72*rect.height());\r
-       if((rx !=0) || (ry !=0))\r
-               printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);\r
-       writeStyle();\r
-       printf("/>\n");\r
-}\r
-\r
-void InkscapePainter::drawEllipse(const WPGPoint& center, double rx, double ry)\r
-{\r
-       printf("<ellipse ");\r
-       printf("cx=\"%f\" cy=\"%f\" ", 72*center.x, 72*center.y);\r
-       printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);\r
-       writeStyle();\r
-       printf("/>\n");\r
-}\r
-\r
-void InkscapePainter::drawPolygon(const WPGPointArray& vertices)\r
-{\r
-       if(vertices.count() < 2)\r
-               return;\r
-\r
-       if(vertices.count() == 2)\r
-       {\r
-               const WPGPoint& p1 = vertices[0];\r
-               const WPGPoint& p2 = vertices[1];\r
-               printf("<line ");\r
-               printf("x1=\"%f\"  y1=\"%f\" ", 72*p1.x, 72*p1.y);\r
-               printf("x2=\"%f\"  y2=\"%f\"\n", 72*p2.x, 72*p2.y);\r
-               writeStyle();\r
-               printf("/>\n");\r
-       }\r
-       else\r
-       {\r
-               printf("<polyline ");\r
-               printf("points=\"");\r
-               for(unsigned i = 0; i < vertices.count(); i++)\r
-               {\r
-                       printf("%f %f", 72*vertices[i].x, 72*vertices[i].y);\r
-                       if(i < vertices.count()-1) printf(", ");\r
-               }\r
-               printf("\"\n");\r
-               writeStyle();\r
-               printf("/>\n");\r
-       }\r
-}\r
-\r
-void InkscapePainter::drawPath(const WPGPath& path)\r
-{\r
-       printf("<path d=\"");\r
-       for(unsigned i = 0; i < path.count(); i++)\r
-       {\r
-               WPGPathElement element = path.element(i);\r
-               WPGPoint point = element.point;\r
-               switch(element.type)\r
-               {\r
-                       case WPGPathElement::MoveToElement:\r
-                               printf("\n M%f,%f ", 72*point.x, 72*point.y );\r
-                               break;\r
-                               \r
-                       case WPGPathElement::LineToElement:\r
-                               printf("\n L%f,%f ", 72*point.x, 72*point.y );\r
-                               break;\r
-                       \r
-                       case WPGPathElement::CurveToElement:\r
-                               printf("C");\r
-                               printf("%f,%f ", 72*element.extra1.x, 72*element.extra1.y );\r
-                               printf("%f,%f ", 72*element.extra2.x, 72*element.extra2.y );\r
-                               printf("%f,%f", 72*point.x, 72*point.y );\r
-                               break;\r
-                       \r
-                       default:\r
-                               break;\r
-               }\r
-       }\r
-       \r
-       if(path.closed)\r
-               printf("Z");\r
-\r
-       printf("\" \n");\r
-       writeStyle();\r
-       printf("/>\n");\r
-}\r
-\r
-// create "style" attribute based on current pen and brush\r
-void InkscapePainter::writeStyle()\r
-{\r
-       printf("style=\"");\r
-\r
-       const WPGColor& color = m_pen.foreColor;\r
-       printf("stroke-width: %f; ", 72*m_pen.width);\r
-       if(m_pen.width > 0.0)\r
-       {\r
-               printf("stroke: rgb(%d,%d,%d); ", color.red, color.green, color.blue);\r
-               if(color.alpha != 0)\r
-                       // alpha = 0 means opacity = 1.0, alpha = 256 means opacity = 0\r
-                       printf("stroke-opacity: %f; ", 1.0-(color.alpha/256.0));\r
-       }\r
-\r
-       if(!m_pen.solid)\r
-       {\r
-               printf("stroke-dasharray: ");\r
-               for(unsigned i = 0; i < m_pen.dashArray.count(); i++)\r
-               {\r
-                       printf("%f", 72*m_pen.dashArray.at(i)*m_pen.width);\r
-                       if(i < m_pen.dashArray.count()-1) \r
-                               printf(", ");\r
-               }\r
-               printf("; ");\r
-       }\r
-       \r
-       if(m_brush.style == WPGBrush::NoBrush)\r
-               printf("fill: none; ");\r
-\r
-       if(m_fillRule == InkscapePainter::WindingFill)\r
-               printf("fill-rule: nonzero; ");\r
-       else if(m_fillRule == InkscapePainter::AlternatingFill)\r
-               printf("fill-rule: evenodd; ");\r
-\r
-       if(m_brush.style == WPGBrush::Gradient)\r
-               printf("fill: url(#grad%d); ", m_gradientIndex-1);\r
-\r
-       if(m_brush.style == WPGBrush::Solid)\r
-               printf("fill: rgb(%d,%d,%d); ", m_brush.foreColor.red, \r
-                       m_brush.foreColor.green, m_brush.foreColor.blue);\r
-\r
-       printf("\""); // style\r
-}\r
-\r
-SPDocument *\r
-WpgInput::open(Inkscape::Extension::Input * mod, const gchar * uri) {\r
-    WPGInputStream* input = new WPGFileStream(uri);\r
-    if (input->isOle()) {\r
-        WPGInputStream* olestream = input->getWPGOleStream();\r
-        if (olestream) {\r
-            delete input;\r
-            input = olestream;\r
-        }\r
-    }\r
-\r
-    if (!WPGraphics::isSupported(input)) {\r
-        //! \todo Dialog here\r
-        // fprintf(stderr, "ERROR: Unsupported file format (unsupported version) or file is encrypted!\n");\r
-        // printf("I'm giving up not supported\n");\r
-        return NULL;\r
-    }\r
-\r
-    InkscapePainter painter;\r
-    WPGraphics::parse(input, &painter);\r
-\r
-    //printf("I've got a doc: \n%s", painter.document.c_str());\r
-\r
-    return sp_document_new_from_mem(painter.document.c_str(), strlen(painter.document.c_str()), TRUE);\r
-}\r
-\r
-#include "clear-n_.h"\r
-\r
-void\r
-WpgInput::init(void) {\r
-    Inkscape::Extension::Extension * ext;\r
-\r
-    ext = Inkscape::Extension::build_from_mem(\r
-        "<inkscape-extension>\n"\r
-            "<name>" N_("WPG Input") "</name>\n"\r
-            "<id>org.inkscape.input.wpg</id>\n"\r
-            "<input>\n"\r
-                "<extension>.wpg</extension>\n"\r
-                "<mimetype>image/x-wpg</mimetype>\n"\r
-                "<filetypename>" N_("WordPerfect Graphics (*.wpg)") "</filetypename>\n"\r
-                "<filetypetooltip>" N_("Vector graphics format used by Corel WordPerfect") "</filetypetooltip>\n"\r
-            "</input>\n"\r
-        "</inkscape-extension>", new WpgInput());\r
-} // init\r
-\r
-} } }  /* namespace Inkscape, Extension, Implementation */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+/* 
+ *  This file came from libwpg as a source, their utility wpg2svg
+ *  specifically.  It has been modified to work as an Inkscape extension.
+ *  The Inkscape extension code is covered by this copyright, but the
+ *  rest is covered by the one bellow.
+ *
+ * Authors:
+ *   Ted Gould <ted@gould.cx>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ */
+
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include <stdio.h>
+
+#include "wpg-input.h"
+#include "extension/system.h"
+#include "extension/input.h"
+#include "document.h"
+
+#include "libwpg/libwpg.h"
+#include "libwpg/WPGStreamImplementation.h"
+
+using namespace libwpg;
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class InkscapePainter : public libwpg::WPGPaintInterface {
+public:
+       InkscapePainter();
+
+       void startDocument(double imageWidth, double imageHeight);
+       void endDocument();
+       void startLayer(unsigned int id);
+       void endLayer(unsigned int id);
+
+       void setPen(const WPGPen& pen);
+       void setBrush(const WPGBrush& brush);
+       void setFillRule(FillRule rule);
+
+       void drawRectangle(const WPGRect& rect, double rx, double ry);
+       void drawEllipse(const WPGPoint& center, double rx, double ry);
+       void drawPolygon(const WPGPointArray& vertices);
+       void drawPath(const WPGPath& path);
+
+private:
+       WPGPen m_pen;
+       WPGBrush m_brush;
+       FillRule m_fillRule;
+       int m_gradientIndex;
+       void writeStyle();
+        void printf (char * fmt, ...) {
+            va_list args;
+            va_start(args, fmt);
+            gchar * buf = g_strdup_vprintf(fmt, args);
+            va_end(args);
+            if (buf) {
+                document += buf;
+                g_free(buf);
+            }
+        }
+
+public:
+        Glib::ustring document;
+};
+
+InkscapePainter::InkscapePainter(): m_fillRule(AlternatingFill), m_gradientIndex(1)
+{
+}
+
+void InkscapePainter::startDocument(double width, double height) 
+{
+        document = "";
+       printf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+       printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"");
+       printf(" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+
+//     printf("<!-- Created with wpg2svg/libwpg %s -->\n", LIBWPG_VERSION_STRING);
+
+       printf("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" ");
+       printf("xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");        
+       printf("width=\"%g\" height=\"%f\" >\n", 72*width, 72*height);
+       
+       m_gradientIndex = 1;
+}
+
+void InkscapePainter::endDocument()
+{
+       printf("</svg>\n");
+}
+
+void InkscapePainter::setPen(const WPGPen& pen)
+{
+       m_pen = pen;
+}
+
+void InkscapePainter::setBrush(const WPGBrush& brush)
+{
+       m_brush = brush;
+       
+       if(m_brush.style == WPGBrush::Gradient)
+       {
+               double angle = m_brush.gradient.angle();
+
+               printf("<defs>\n");
+               printf("  <linearGradient id=\"grad%d\" >\n", m_gradientIndex++);
+               for(unsigned c = 0; c < m_brush.gradient.count(); c++)
+               {
+                       // round to nearest percentage
+                       int ofs = (int)(100.0*m_brush.gradient.stopOffset(c)+0.5);
+
+                       WPGColor color = m_brush.gradient.stopColor(c);
+                       printf("    <stop offset=\"%d%%\" stop-color=\"#%02x%02x%02x\" />\n",
+                               ofs, color.red, color.green, color.blue);
+               }
+               printf("  </linearGradient>\n");
+               
+               // not a simple horizontal gradient
+               if(angle != -90.0)
+               {
+                       printf("  <linearGradient xlink:href=\"#grad%d\"", m_gradientIndex-1);
+                       printf(" id=\"grad%d\" ", m_gradientIndex++);
+                       printf("x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" "); 
+                       printf("gradientTransform=\"rotate(%f)\" ", angle);
+                       printf("gradientUnits=\"objectBoundingBox\" >\n");
+                       printf("  </linearGradient>\n");
+               }
+               
+               printf("</defs>\n");
+       }
+}
+
+void InkscapePainter::setFillRule(FillRule rule)
+{
+       m_fillRule = rule;
+}
+
+void InkscapePainter::startLayer(unsigned int id)
+{
+       printf("<g id=\"Layer%d\" >\n", id);
+}
+
+void InkscapePainter::endLayer(unsigned int)
+{
+       printf("</g>\n");
+}
+
+void InkscapePainter::drawRectangle(const WPGRect& rect, double rx, double ry)
+{
+       printf("<rect ");
+       printf("x=\"%f\" y=\"%f\" ", 72*rect.x1, 72*rect.y1);
+       printf("width=\"%f\" height=\"%f\" ", 72*rect.width(), 72*rect.height());
+       if((rx !=0) || (ry !=0))
+               printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);
+       writeStyle();
+       printf("/>\n");
+}
+
+void InkscapePainter::drawEllipse(const WPGPoint& center, double rx, double ry)
+{
+       printf("<ellipse ");
+       printf("cx=\"%f\" cy=\"%f\" ", 72*center.x, 72*center.y);
+       printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);
+       writeStyle();
+       printf("/>\n");
+}
+
+void InkscapePainter::drawPolygon(const WPGPointArray& vertices)
+{
+       if(vertices.count() < 2)
+               return;
+
+       if(vertices.count() == 2)
+       {
+               const WPGPoint& p1 = vertices[0];
+               const WPGPoint& p2 = vertices[1];
+               printf("<line ");
+               printf("x1=\"%f\"  y1=\"%f\" ", 72*p1.x, 72*p1.y);
+               printf("x2=\"%f\"  y2=\"%f\"\n", 72*p2.x, 72*p2.y);
+               writeStyle();
+               printf("/>\n");
+       }
+       else
+       {
+               printf("<polyline ");
+               printf("points=\"");
+               for(unsigned i = 0; i < vertices.count(); i++)
+               {
+                       printf("%f %f", 72*vertices[i].x, 72*vertices[i].y);
+                       if(i < vertices.count()-1) printf(", ");
+               }
+               printf("\"\n");
+               writeStyle();
+               printf("/>\n");
+       }
+}
+
+void InkscapePainter::drawPath(const WPGPath& path)
+{
+       printf("<path d=\"");
+       for(unsigned i = 0; i < path.count(); i++)
+       {
+               WPGPathElement element = path.element(i);
+               WPGPoint point = element.point;
+               switch(element.type)
+               {
+                       case WPGPathElement::MoveToElement:
+                               printf("\n M%f,%f ", 72*point.x, 72*point.y );
+                               break;
+                               
+                       case WPGPathElement::LineToElement:
+                               printf("\n L%f,%f ", 72*point.x, 72*point.y );
+                               break;
+                       
+                       case WPGPathElement::CurveToElement:
+                               printf("C");
+                               printf("%f,%f ", 72*element.extra1.x, 72*element.extra1.y );
+                               printf("%f,%f ", 72*element.extra2.x, 72*element.extra2.y );
+                               printf("%f,%f", 72*point.x, 72*point.y );
+                               break;
+                       
+                       default:
+                               break;
+               }
+       }
+       
+       if(path.closed)
+               printf("Z");
+
+       printf("\" \n");
+       writeStyle();
+       printf("/>\n");
+}
+
+// create "style" attribute based on current pen and brush
+void InkscapePainter::writeStyle()
+{
+       printf("style=\"");
+
+       const WPGColor& color = m_pen.foreColor;
+       printf("stroke-width: %f; ", 72*m_pen.width);
+       if(m_pen.width > 0.0)
+       {
+               printf("stroke: rgb(%d,%d,%d); ", color.red, color.green, color.blue);
+               if(color.alpha != 0)
+                       // alpha = 0 means opacity = 1.0, alpha = 256 means opacity = 0
+                       printf("stroke-opacity: %f; ", 1.0-(color.alpha/256.0));
+       }
+
+       if(!m_pen.solid)
+       {
+               printf("stroke-dasharray: ");
+               for(unsigned i = 0; i < m_pen.dashArray.count(); i++)
+               {
+                       printf("%f", 72*m_pen.dashArray.at(i)*m_pen.width);
+                       if(i < m_pen.dashArray.count()-1) 
+                               printf(", ");
+               }
+               printf("; ");
+       }
+       
+       if(m_brush.style == WPGBrush::NoBrush)
+               printf("fill: none; ");
+
+       if(m_fillRule == InkscapePainter::WindingFill)
+               printf("fill-rule: nonzero; ");
+       else if(m_fillRule == InkscapePainter::AlternatingFill)
+               printf("fill-rule: evenodd; ");
+
+       if(m_brush.style == WPGBrush::Gradient)
+               printf("fill: url(#grad%d); ", m_gradientIndex-1);
+
+       if(m_brush.style == WPGBrush::Solid)
+               printf("fill: rgb(%d,%d,%d); ", m_brush.foreColor.red, 
+                       m_brush.foreColor.green, m_brush.foreColor.blue);
+
+       printf("\""); // style
+}
+
+SPDocument *
+WpgInput::open(Inkscape::Extension::Input * mod, const gchar * uri) {
+    WPGInputStream* input = new WPGFileStream(uri);
+    if (input->isOle()) {
+        WPGInputStream* olestream = input->getWPGOleStream();
+        if (olestream) {
+            delete input;
+            input = olestream;
+        }
+    }
+
+    if (!WPGraphics::isSupported(input)) {
+        //! \todo Dialog here
+        // fprintf(stderr, "ERROR: Unsupported file format (unsupported version) or file is encrypted!\n");
+        // printf("I'm giving up not supported\n");
+        return NULL;
+    }
+
+    InkscapePainter painter;
+    WPGraphics::parse(input, &painter);
+
+    //printf("I've got a doc: \n%s", painter.document.c_str());
+
+    return sp_document_new_from_mem(painter.document.c_str(), strlen(painter.document.c_str()), TRUE);
+}
+
+#include "clear-n_.h"
+
+void
+WpgInput::init(void) {
+    Inkscape::Extension::Extension * ext;
+
+    ext = Inkscape::Extension::build_from_mem(
+        "<inkscape-extension>\n"
+            "<name>" N_("WPG Input") "</name>\n"
+            "<id>org.inkscape.input.wpg</id>\n"
+            "<input>\n"
+                "<extension>.wpg</extension>\n"
+                "<mimetype>image/x-wpg</mimetype>\n"
+                "<filetypename>" N_("WordPerfect Graphics (*.wpg)") "</filetypename>\n"
+                "<filetypetooltip>" N_("Vector graphics format used by Corel WordPerfect") "</filetypetooltip>\n"
+            "</input>\n"
+        "</inkscape-extension>", new WpgInput());
+} // init
+
+} } }  /* namespace Inkscape, Extension, Implementation */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 1e95a18f06bb56fa569440dfc6759c8034ded844..283ef8f5c23ffe30dfc4257a4b39192ff59cdcb1 100644 (file)
-/** \file\r
- * extension parameter for enumerations.\r
- *\r
- * It uses a Gtk:ComboBoxText widget in the extension UI.\r
- */\r
-\r
-/*\r
- * Author:\r
- *   Johan Engelen <johan@shouraizou.nl>\r
- *\r
- * Copyright (C) 2006-2007 Johan Engelen\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-\r
-#include <gtkmm/box.h>\r
-#include <gtkmm/comboboxtext.h>\r
-#include <gtkmm/tooltips.h>\r
-#include <gtkmm/label.h>\r
-\r
-#include <glibmm/i18n.h>\r
-\r
-#include <xml/node.h>\r
-\r
-#include "extension.h"\r
-#include "prefs-utils.h"\r
-#include "document-private.h"\r
-#include "sp-object.h"\r
-\r
-#include "paramenum.h"\r
-\r
-/** \brief  The root directory in the preferences database for extension\r
-            related parameters. */\r
-#define PREF_DIR "extensions"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-\r
-/* For internal use only.\r
-     Note that value and guitext MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */\r
-class enumentry {\r
-public:\r
-    enumentry (Glib::ustring * val, Glib::ustring * text) {\r
-        value = val;\r
-        guitext = text;\r
-    }\r
-    ~enumentry() {\r
-        delete value;\r
-        delete guitext;\r
-    }\r
-\r
-    Glib::ustring * value;\r
-    Glib::ustring * guitext;\r
-};\r
-\r
-\r
-ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
-    Parameter(name, guitext, desc, scope, ext)\r
-{\r
-    choices = NULL;\r
-    _value = NULL;\r
-\r
-    // Read XML tree to add enumeration items:\r
-    // printf("Extension Constructor: ");\r
-    if (xml != NULL) {\r
-        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
-        while (child_repr != NULL) {\r
-            char const * chname = child_repr->name();\r
-            if (!strcmp(chname, "item")) {\r
-                Glib::ustring * newguitext = NULL;\r
-                Glib::ustring * newvalue = NULL;\r
-                const char * contents = sp_repr_children(child_repr)->content();\r
-                if (contents != NULL)\r
-                     newguitext = new Glib::ustring( _(contents) );\r
-                const char * val = child_repr->attribute("value");\r
-                if (val != NULL)\r
-                    newvalue = new Glib::ustring(val);\r
-                if ( (newguitext) && (newvalue) ) {\r
-                    choices = g_slist_append( choices, new enumentry(newvalue, newguitext) );\r
-                }\r
-            }\r
-            child_repr = sp_repr_next(child_repr);\r
-        }\r
-    }\r
-\r
-    // Initialize _value with the default value from xml\r
-    // for simplicity : default to the contents of the first xml-child\r
-    const char * defaultval = NULL;\r
-    if (sp_repr_children(sp_repr_children(xml)) != NULL)\r
-        defaultval = sp_repr_children(xml)->attribute("value");\r
-\r
-    gchar * pref_name = this->pref_name();\r
-    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);\r
-    g_free(pref_name);\r
-\r
-    if (paramval != NULL)\r
-        defaultval = paramval;\r
-    if (defaultval != NULL)\r
-        _value = g_strdup(defaultval);  // allocate space for _value\r
-\r
-    return;\r
-}\r
-\r
-ParamComboBox::~ParamComboBox (void)\r
-{\r
-    //destroy choice strings\r
-    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {\r
-        delete (reinterpret_cast<enumentry *>(list->data));\r
-    }\r
-    g_slist_free(choices);\r
-\r
-    g_free(_value);\r
-}\r
-\r
-\r
-/** \brief  A function to set the \c _value\r
-    \param  in   The value to set\r
-    \param  doc  A document that should be used to set the value.\r
-    \param  node The node where the value may be placed\r
-\r
-    This function sets ONLY the internal value, but it also sets the value\r
-    in the preferences structure.  To put it in the right place, \c PREF_DIR\r
-    and \c pref_name() are used.\r
-\r
-    To copy the data into _value the old memory must be free'd first.\r
-    It is important to note that \c g_free handles \c NULL just fine.  Then\r
-    the passed in value is duplicated using \c g_strdup().\r
-*/\r
-const gchar *\r
-ParamComboBox::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    if (in == NULL) return NULL; /* Can't have NULL string */\r
-\r
-    Glib::ustring * settext = NULL;\r
-    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {\r
-        enumentry * entr = reinterpret_cast<enumentry *>(list->data);\r
-        if ( !entr->guitext->compare(in) ) {\r
-            settext = entr->value;\r
-            break;  // break out of for loop\r
-        }\r
-    }\r
-    if (settext) {\r
-        if (_value != NULL) g_free(_value);\r
-        _value = g_strdup(settext->c_str());\r
-        gchar * prefname = this->pref_name();\r
-        prefs_set_string_attribute(PREF_DIR, prefname, _value);\r
-        g_free(prefname);\r
-    }\r
-\r
-    return _value;\r
-}\r
-\r
-\r
-/**\r
-    \brief  A function to get the value of the parameter in string form\r
-    \return A string with the 'value' as command line argument\r
-*/\r
-Glib::ustring *\r
-ParamComboBox::string (void)\r
-{\r
-    Glib::ustring * param_string = new Glib::ustring("");\r
-\r
-    *param_string += "\"";\r
-    *param_string += _value;\r
-    *param_string += "\"";\r
-\r
-    return param_string;\r
-}\r
-\r
-/** \brief  A special category of Gtk::Entry to handle string parameteres */\r
-class ParamComboBoxEntry : public Gtk::ComboBoxText {\r
-private:\r
-    ParamComboBox * _pref;\r
-    SPDocument * _doc;\r
-    Inkscape::XML::Node * _node;\r
-public:\r
-    /** \brief  Build a string preference for the given parameter\r
-        \param  pref  Where to get the string from, and where to put it\r
-                      when it changes.\r
-    */\r
-    ParamComboBoxEntry (ParamComboBox * pref, SPDocument * doc, Inkscape::XML::Node * node) :\r
-        Gtk::ComboBoxText(), _pref(pref), _doc(doc), _node(node) {\r
-        this->signal_changed().connect(sigc::mem_fun(this, &ParamComboBoxEntry::changed));\r
-    };\r
-    void changed (void);\r
-};\r
-\r
-/** \brief  Respond to the text box changing\r
-\r
-    This function responds to the box changing by grabbing the value\r
-    from the text box and putting it in the parameter.\r
-*/\r
-void\r
-ParamComboBoxEntry::changed (void)\r
-{\r
-    Glib::ustring data = this->get_active_text();\r
-    _pref->set(data.c_str(), _doc, _node);\r
-    return;\r
-}\r
-\r
-\r
-\r
-/**\r
-    \brief  Creates a combobox widget for an enumeration parameter\r
-*/\r
-Gtk::Widget *\r
-ParamComboBox::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));\r
-\r
-    Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));\r
-    label->show();\r
-    hbox->pack_start(*label, false, false);\r
-\r
-    ParamComboBoxEntry * combo = Gtk::manage(new ParamComboBoxEntry(this, doc, node));\r
-    // add choice strings:\r
-    Glib::ustring * settext = 0;\r
-    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {\r
-        enumentry * entr = reinterpret_cast<enumentry *>(list->data);\r
-        Glib::ustring * text = entr->guitext;\r
-        combo->append_text(*text);\r
-        if ( !entr->value->compare(_value) ) {\r
-            settext = entr->guitext;\r
-        }\r
-    }\r
-    if (settext) combo->set_active_text(*settext);\r
-\r
-    combo->show();\r
-    hbox->pack_start(*combo, true, true);\r
-\r
-    hbox->show();\r
-\r
-    return dynamic_cast<Gtk::Widget *>(hbox);\r
-}\r
-\r
-\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
+/** \file
+ * extension parameter for enumerations.
+ *
+ * It uses a Gtk:ComboBoxText widget in the extension UI.
+ */
+
+/*
+ * Author:
+ *   Johan Engelen <johan@shouraizou.nl>
+ *
+ * Copyright (C) 2006-2007 Johan Engelen
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <gtkmm/box.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/label.h>
+
+#include <glibmm/i18n.h>
+
+#include <xml/node.h>
+
+#include "extension.h"
+#include "prefs-utils.h"
+#include "document-private.h"
+#include "sp-object.h"
+
+#include "paramenum.h"
+
+/** \brief  The root directory in the preferences database for extension
+            related parameters. */
+#define PREF_DIR "extensions"
+
+namespace Inkscape {
+namespace Extension {
+
+/* For internal use only.
+     Note that value and guitext MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */
+class enumentry {
+public:
+    enumentry (Glib::ustring * val, Glib::ustring * text) {
+        value = val;
+        guitext = text;
+    }
+    ~enumentry() {
+        delete value;
+        delete guitext;
+    }
+
+    Glib::ustring * value;
+    Glib::ustring * guitext;
+};
+
+
+ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
+    Parameter(name, guitext, desc, scope, ext)
+{
+    choices = NULL;
+    _value = NULL;
+
+    // Read XML tree to add enumeration items:
+    // printf("Extension Constructor: ");
+    if (xml != NULL) {
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);
+        while (child_repr != NULL) {
+            char const * chname = child_repr->name();
+            if (!strcmp(chname, "item")) {
+                Glib::ustring * newguitext = NULL;
+                Glib::ustring * newvalue = NULL;
+                const char * contents = sp_repr_children(child_repr)->content();
+                if (contents != NULL)
+                     newguitext = new Glib::ustring( _(contents) );
+                const char * val = child_repr->attribute("value");
+                if (val != NULL)
+                    newvalue = new Glib::ustring(val);
+                if ( (newguitext) && (newvalue) ) {
+                    choices = g_slist_append( choices, new enumentry(newvalue, newguitext) );
+                }
+            }
+            child_repr = sp_repr_next(child_repr);
+        }
+    }
+
+    // Initialize _value with the default value from xml
+    // for simplicity : default to the contents of the first xml-child
+    const char * defaultval = NULL;
+    if (sp_repr_children(sp_repr_children(xml)) != NULL)
+        defaultval = sp_repr_children(xml)->attribute("value");
+
+    gchar * pref_name = this->pref_name();
+    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
+    g_free(pref_name);
+
+    if (paramval != NULL)
+        defaultval = paramval;
+    if (defaultval != NULL)
+        _value = g_strdup(defaultval);  // allocate space for _value
+
+    return;
+}
+
+ParamComboBox::~ParamComboBox (void)
+{
+    //destroy choice strings
+    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
+        delete (reinterpret_cast<enumentry *>(list->data));
+    }
+    g_slist_free(choices);
+
+    g_free(_value);
+}
+
+
+/** \brief  A function to set the \c _value
+    \param  in   The value to set
+    \param  doc  A document that should be used to set the value.
+    \param  node The node where the value may be placed
+
+    This function sets ONLY the internal value, but it also sets the value
+    in the preferences structure.  To put it in the right place, \c PREF_DIR
+    and \c pref_name() are used.
+
+    To copy the data into _value the old memory must be free'd first.
+    It is important to note that \c g_free handles \c NULL just fine.  Then
+    the passed in value is duplicated using \c g_strdup().
+*/
+const gchar *
+ParamComboBox::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
+{
+    if (in == NULL) return NULL; /* Can't have NULL string */
+
+    Glib::ustring * settext = NULL;
+    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
+        enumentry * entr = reinterpret_cast<enumentry *>(list->data);
+        if ( !entr->guitext->compare(in) ) {
+            settext = entr->value;
+            break;  // break out of for loop
+        }
+    }
+    if (settext) {
+        if (_value != NULL) g_free(_value);
+        _value = g_strdup(settext->c_str());
+        gchar * prefname = this->pref_name();
+        prefs_set_string_attribute(PREF_DIR, prefname, _value);
+        g_free(prefname);
+    }
+
+    return _value;
+}
+
+
+/**
+    \brief  A function to get the value of the parameter in string form
+    \return A string with the 'value' as command line argument
+*/
+Glib::ustring *
+ParamComboBox::string (void)
+{
+    Glib::ustring * param_string = new Glib::ustring("");
+
+    *param_string += "\"";
+    *param_string += _value;
+    *param_string += "\"";
+
+    return param_string;
+}
+
+/** \brief  A special category of Gtk::Entry to handle string parameteres */
+class ParamComboBoxEntry : public Gtk::ComboBoxText {
+private:
+    ParamComboBox * _pref;
+    SPDocument * _doc;
+    Inkscape::XML::Node * _node;
+public:
+    /** \brief  Build a string preference for the given parameter
+        \param  pref  Where to get the string from, and where to put it
+                      when it changes.
+    */
+    ParamComboBoxEntry (ParamComboBox * pref, SPDocument * doc, Inkscape::XML::Node * node) :
+        Gtk::ComboBoxText(), _pref(pref), _doc(doc), _node(node) {
+        this->signal_changed().connect(sigc::mem_fun(this, &ParamComboBoxEntry::changed));
+    };
+    void changed (void);
+};
+
+/** \brief  Respond to the text box changing
+
+    This function responds to the box changing by grabbing the value
+    from the text box and putting it in the parameter.
+*/
+void
+ParamComboBoxEntry::changed (void)
+{
+    Glib::ustring data = this->get_active_text();
+    _pref->set(data.c_str(), _doc, _node);
+    return;
+}
+
+
+
+/**
+    \brief  Creates a combobox widget for an enumeration parameter
+*/
+Gtk::Widget *
+ParamComboBox::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
+{
+    Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
+
+    Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
+    label->show();
+    hbox->pack_start(*label, false, false);
+
+    ParamComboBoxEntry * combo = Gtk::manage(new ParamComboBoxEntry(this, doc, node));
+    // add choice strings:
+    Glib::ustring * settext = 0;
+    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
+        enumentry * entr = reinterpret_cast<enumentry *>(list->data);
+        Glib::ustring * text = entr->guitext;
+        combo->append_text(*text);
+        if ( !entr->value->compare(_value) ) {
+            settext = entr->guitext;
+        }
+    }
+    if (settext) combo->set_active_text(*settext);
+
+    combo->show();
+    hbox->pack_start(*combo, true, true);
+
+    hbox->show();
+
+    return dynamic_cast<Gtk::Widget *>(hbox);
+}
+
+
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
index f6fea4e05717f06c2ca566fc631331cf17c32b77..4ad4485496efb3b72d284885088e636bbfd78a6e 100644 (file)
@@ -1,67 +1,67 @@
-#ifndef __INK_EXTENSION_PARAMENUM_H__\r
-#define __INK_EXTENSION_PARAMENUM_H__\r
-\r
-/** \file\r
- * Enumeration parameter for extensions.\r
- */\r
-\r
-/*\r
- * Author:\r
- *   Johan Engelen <johan@shouraizou.nl>\r
- *\r
- * Copyright (C) 2006-2007 Johan Engelen\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#include <gtkmm/widget.h>\r
-\r
-#include "xml/document.h"\r
-#include "extension-forward.h"\r
-\r
-#include "parameter.h"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-\r
-\r
-\r
-// \brief  A class to represent a notebookparameter of an extension\r
-class ParamComboBox : public Parameter {\r
-private:\r
-    /** \brief  Internal value.  This should point to a string that has\r
-                been allocated in memory.  And should be free'd. \r
-                It is the value of the current selected string */\r
-    gchar * _value;\r
-    \r
-    GSList * choices; /**< A table to store the choice strings  */\r
-    \r
-public:\r
-    ParamComboBox(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);\r
-    ~ParamComboBox(void);\r
-    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);\r
-    Glib::ustring * string (void);\r
-        \r
-    const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }\r
-    const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);\r
-}; /* class ParamComboBox */\r
-\r
-\r
-\r
-\r
-\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
-#endif /* __INK_EXTENSION_PARAMENUM_H__ */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+#ifndef __INK_EXTENSION_PARAMENUM_H__
+#define __INK_EXTENSION_PARAMENUM_H__
+
+/** \file
+ * Enumeration parameter for extensions.
+ */
+
+/*
+ * Author:
+ *   Johan Engelen <johan@shouraizou.nl>
+ *
+ * Copyright (C) 2006-2007 Johan Engelen
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/widget.h>
+
+#include "xml/document.h"
+#include "extension-forward.h"
+
+#include "parameter.h"
+
+namespace Inkscape {
+namespace Extension {
+
+
+
+// \brief  A class to represent a notebookparameter of an extension
+class ParamComboBox : public Parameter {
+private:
+    /** \brief  Internal value.  This should point to a string that has
+                been allocated in memory.  And should be free'd. 
+                It is the value of the current selected string */
+    gchar * _value;
+    
+    GSList * choices; /**< A table to store the choice strings  */
+    
+public:
+    ParamComboBox(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
+    ~ParamComboBox(void);
+    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
+    Glib::ustring * string (void);
+        
+    const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
+    const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
+}; /* class ParamComboBox */
+
+
+
+
+
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+#endif /* __INK_EXTENSION_PARAMENUM_H__ */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index cd8bddcaa0e435ceb59de3bafaa41d08922bd448..e8bd1e902273b6c768a80d20d25b67d3b4010670 100644 (file)
-/** \file\r
- * Notebook and NotebookPage parameters for extensions.\r
- */\r
-\r
-/*\r
- * Author:\r
- *   Johan Engelen <johan@shouraizou.nl>\r
- *\r
- * Copyright (C) 2006 Author\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-\r
-#include <gtkmm/adjustment.h>\r
-#include <gtkmm/box.h>\r
-#include <gtkmm/spinbutton.h>\r
-#include <gtkmm/notebook.h>\r
-#include <gtkmm/tooltips.h>\r
-\r
-#include <glibmm/i18n.h>\r
-\r
-#include <xml/node.h>\r
-\r
-#include "extension.h"\r
-#include "prefs-utils.h"\r
-#include "document-private.h"\r
-#include "sp-object.h"\r
-\r
-#include "paramnotebook.h"\r
-\r
-/** \brief  The root directory in the preferences database for extension\r
-            related parameters. */\r
-#define PREF_DIR "extensions"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-\r
-\r
-// \brief  A class to represent the pages of a notebookparameter of an extension\r
-class ParamNotebookPage : public Parameter {\r
-private:\r
-    GSList * parameters; /**< A table to store the parameters for this page.\r
-                              This only gets created if there are parameters on this\r
-                              page */\r
-    Gtk::Tooltips * _tooltips;\r
-    \r
-public:\r
-    static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext);\r
-\r
-    ParamNotebookPage(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);\r
-    ~ParamNotebookPage(void);\r
-    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);\r
-    Glib::ustring * paramString (void);\r
-    gchar * get_guitext (void) {return _text;};\r
-    \r
-}; /* class ParamNotebookPage */\r
-\r
-\r
-ParamNotebookPage::ParamNotebookPage (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
-    Parameter(name, guitext, desc, scope, ext)\r
-{\r
-    parameters = NULL;\r
-        \r
-    // Read XML to build page\r
-    if (xml != NULL) {\r
-        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
-        while (child_repr != NULL) {\r
-            char const * chname = child_repr->name();\r
-            if (chname[0] == '_') // Allow _ for translation of tags\r
-                chname++;\r
-            if (!strcmp(chname, "param") || !strcmp(chname, "_param")) {\r
-                Parameter * param;\r
-                param = Parameter::make(child_repr, ext);\r
-                if (param != NULL) parameters = g_slist_append(parameters, param);\r
-            }\r
-            child_repr = sp_repr_next(child_repr);\r
-        }\r
-    }\r
-    \r
-    return;\r
-}\r
-\r
-ParamNotebookPage::~ParamNotebookPage (void)\r
-{\r
-    if (_tooltips) delete _tooltips;\r
-    //destroy parameters\r
-    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
-        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
-        delete param;\r
-    }\r
-    g_slist_free(parameters);\r
-}\r
-\r
-/** \brief  Return the value as a string */\r
-Glib::ustring *\r
-ParamNotebookPage::paramString (void)\r
-{\r
-    Glib::ustring * param_string = new Glib::ustring("");\r
-\r
-    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
-        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
-\r
-        *param_string += " --";\r
-        *param_string += param->name();\r
-        *param_string += "=";\r
-        Glib::ustring * paramstr = param->string();\r
-        *param_string += *paramstr;\r
-        delete paramstr;\r
-    }\r
-\r
-    return param_string;\r
-}\r
-\r
-\r
-/**\r
-    \return None\r
-    \brief  This function creates a page that can be used later.  This\r
-            is typically done in the creation of the notebook and defined\r
-            in the XML file describing the extension (it's private so people\r
-            have to use the system) :)\r
-    \param  in_repr  The XML describing the page\r
-\r
-    This function first grabs all of the data out of the Repr and puts\r
-    it into local variables.  Actually, these are just pointers, and the\r
-    data is not duplicated so we need to be careful with it.  If there\r
-    isn't a name in the XML, then no page is created as\r
-    the function just returns.\r
-\r
-    From this point on, we're pretty committed as we've allocated an\r
-    object and we're starting to fill it.  The name is set first, and\r
-    is created with a strdup to actually allocate memory for it.  Then\r
-    there is a case statement (roughly because strcmp requires 'ifs')\r
-    based on what type of parameter this is.  Depending which type it\r
-    is, the value is interpreted differently, but they are relatively\r
-    straight forward.  In all cases the value is set to the default\r
-    value from the XML and the type is set to the interpreted type.\r
-*/\r
-ParamNotebookPage *\r
-ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)\r
-{\r
-    const char * name;\r
-    const char * guitext;\r
-    const char * desc;\r
-    const char * scope_str;\r
-    Parameter::_scope_t scope = Parameter::SCOPE_USER;\r
-\r
-    name = in_repr->attribute("name");\r
-    guitext = in_repr->attribute("gui-text");\r
-    if (guitext == NULL)\r
-        guitext = in_repr->attribute("_gui-text");\r
-    desc = in_repr->attribute("gui-description");\r
-    if (desc == NULL)\r
-        desc = in_repr->attribute("_gui-description");\r
-    scope_str = in_repr->attribute("scope");\r
-\r
-    /* In this case we just don't have enough information */\r
-    if (name == NULL) {\r
-        return NULL;\r
-    }\r
-\r
-    if (scope_str != NULL) {\r
-        if (!strcmp(scope_str, "user")) {\r
-            scope = Parameter::SCOPE_USER;\r
-        } else if (!strcmp(scope_str, "document")) {\r
-            scope = Parameter::SCOPE_DOCUMENT;\r
-        } else if (!strcmp(scope_str, "node")) {\r
-            scope = Parameter::SCOPE_NODE;\r
-        }\r
-    }\r
-\r
-    ParamNotebookPage * page = new ParamNotebookPage(name, guitext, desc, scope, in_ext, in_repr);\r
-    \r
-    /* Note: page could equal NULL */\r
-    return page;\r
-}\r
-\r
-\r
-\r
-/**\r
-    \brief  Creates a notebookpage widget for a notebook\r
-\r
-    Builds a notebook page (a vbox) and puts parameters on it.\r
-*/\r
-Gtk::Widget *\r
-ParamNotebookPage::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
-{                      \r
-    if (!_tooltips) _tooltips = new Gtk::Tooltips();\r
-    \r
-    Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox);\r
-    vbox->set_border_width(5);  \r
-    \r
-    // add parameters onto page (if any)    \r
-    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
-        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
-        Gtk::Widget * widg = param->get_widget(doc, node);\r
-        gchar const * tip = param->get_tooltip();\r
-        \r
-        vbox->pack_start(*widg, true, true, 2);\r
-        if (tip != NULL) {\r
-            _tooltips->set_tip(*widg, Glib::ustring(tip));\r
-        }\r
-    }\r
-        \r
-    vbox->show();\r
-    \r
-    return dynamic_cast<Gtk::Widget *>(vbox);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-ParamNotebook::ParamNotebook (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
-    Parameter(name, guitext, desc, scope, ext)\r
-{\r
-    pages = NULL;\r
-    \r
-    // Read XML tree to add pages:\r
-    if (xml != NULL) {\r
-        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
-        while (child_repr != NULL) {\r
-            char const * chname = child_repr->name();\r
-            if (chname[0] == '_') // Allow _ for translation of tags\r
-                chname++;\r
-            if (!strcmp(chname, "page")) {\r
-                ParamNotebookPage * page;\r
-                page = ParamNotebookPage::makepage(child_repr, ext);\r
-                if (page != NULL) pages = g_slist_append(pages, page);\r
-            }\r
-            child_repr = sp_repr_next(child_repr);\r
-        }\r
-    }\r
-    \r
-    // Initialize _value with the current page\r
-    const char * defaultval = NULL;\r
-    // set first page as default\r
-    if (pages != NULL) {\r
-        ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data);\r
-        defaultval = defpage->name();\r
-    }\r
-\r
-    gchar * pref_name = this->pref_name();\r
-    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);\r
-    g_free(pref_name);\r
-\r
-    if (paramval != NULL)\r
-        defaultval = paramval;\r
-    if (defaultval != NULL)\r
-        _value = g_strdup(defaultval);  // allocate space for _value\r
-        \r
-    return;\r
-}\r
-\r
-ParamNotebook::~ParamNotebook (void)\r
-{\r
-    //destroy pages\r
-    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
-        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-        delete page;\r
-    }\r
-    g_slist_free(pages);\r
-\r
-    g_free(_value);\r
-}\r
-\r
-\r
-/** \brief  A function to set the \c _value\r
-    \param  in   The number of the page which value must be set\r
-    \param  doc  A document that should be used to set the value.\r
-    \param  node The node where the value may be placed\r
-\r
-    This function sets the internal value, but it also sets the value\r
-    in the preferences structure.  To put it in the right place, \c PREF_DIR\r
-    and \c pref_name() are used.\r
-\r
-    To copy the data into _value the old memory must be free'd first.\r
-    It is important to note that \c g_free handles \c NULL just fine.  Then\r
-    the passed in value is duplicated using \c g_strdup().\r
-*/\r
-const gchar *\r
-ParamNotebook::set (const int in, SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    ParamNotebookPage * page = NULL;\r
-    int i = 0;\r
-    for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) {\r
-        page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-        i++;\r
-    }\r
-    \r
-    if (page == NULL) return _value;\r
-   \r
-    if (_value != NULL) g_free(_value);\r
-    _value = g_strdup(page->name());\r
-\r
-    gchar * prefname = this->pref_name();\r
-    prefs_set_string_attribute(PREF_DIR, prefname, _value);\r
-    g_free(prefname);\r
-\r
-    return _value;\r
-}\r
-\r
-\r
-/**\r
-    \brief  A function to get the currentpage and the parameters in a string form\r
-    \return A string with the 'value' and all the parameters on all pages as command line arguments\r
-\r
-    This is really a hack. The function is called by Extension::paramString() to build\r
-    the commandline string like: '--param1name=\"param1value\" --param2name=\"param2value\" ...'\r
-    Extension::paramString expects this function to return '\"param1value\"'; but instead, \r
-    this function returns: '\"param1value\" --page1param1name=\"page1param1value\" ...'\r
-\r
-    \TODO  Do this better. For example, make Parameter::paramString() that returns '--name=\"value\"'\r
-    instead of just returning '\"value\"'.\r
-*/\r
-Glib::ustring *\r
-ParamNotebook::string (void)\r
-{\r
-    Glib::ustring * param_string = new Glib::ustring("");\r
-\r
-    *param_string += "\"";\r
-    *param_string += _value;  // the name of the current page\r
-    *param_string += "\"";\r
-\r
-    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
-        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-\r
-        Glib::ustring * pageparamstr = page->paramString();\r
-        *param_string += *pageparamstr;\r
-        delete pageparamstr;\r
-    }\r
-\r
-    return param_string;\r
-}\r
-\r
-/** \brief  A special category of Gtk::Notebook to handle notebook parameters */\r
-class ParamNotebookWdg : public Gtk::Notebook {\r
-private:\r
-    ParamNotebook * _pref;\r
-    SPDocument * _doc;\r
-    Inkscape::XML::Node * _node;\r
-public:\r
-    /** \brief  Build a notebookpage preference for the given parameter\r
-        \param  pref  Where to get the string (pagename) from, and where to put it\r
-                      when it changes.\r
-    */\r
-    ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) :\r
-        Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) {\r
-        // don't have to set the correct page: this is done in ParamNotebook::get_widget.\r
-        // hook function\r
-        this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page));\r
-        return;\r
-    };\r
-    void changed_page(GtkNotebookPage *page, guint pagenum);\r
-    bool activated;\r
-};\r
-\r
-/** \brief  Respond to the selected page of notebook changing\r
-    This function responds to the changing by reporting it to\r
-    ParamNotebook. The change is only reported when the notebook\r
-    is actually visible. This to exclude 'fake' changes when the\r
-    notebookpages are added or removed.\r
-*/\r
-void\r
-ParamNotebookWdg::changed_page(GtkNotebookPage *page,\r
-                                   guint pagenum)\r
-{\r
-    if (is_visible()) {\r
-        _pref->set((int)pagenum, _doc, _node);\r
-    }\r
-    return;\r
-}\r
-\r
-\r
-\r
-/**\r
-    \brief  Creates a Notebook widget for a notebook parameter\r
-\r
-    Builds a notebook and puts pages in it.\r
-*/\r
-Gtk::Widget *\r
-ParamNotebook::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node));\r
-\r
-    // add pages (if any)    \r
-    int i = -1;\r
-    int pagenr = i;\r
-    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
-        i++;  \r
-        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-        Gtk::Widget * widg = page->get_widget(doc, node);\r
-        nb->append_page(*widg, _(page->get_guitext()));\r
-        if (!strcmp(_value, page->name())) {\r
-            pagenr = i; // this is the page to be displayed?\r
-        }\r
-    }\r
-\r
-    nb->show();\r
-    \r
-    if (pagenr >= 0) nb->set_current_page(pagenr);\r
-\r
-    return dynamic_cast<Gtk::Widget *>(nb);\r
-}\r
-\r
-\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+/** \file
+ * Notebook and NotebookPage parameters for extensions.
+ */
+
+/*
+ * Author:
+ *   Johan Engelen <johan@shouraizou.nl>
+ *
+ * Copyright (C) 2006 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/box.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/notebook.h>
+#include <gtkmm/tooltips.h>
+
+#include <glibmm/i18n.h>
+
+#include <xml/node.h>
+
+#include "extension.h"
+#include "prefs-utils.h"
+#include "document-private.h"
+#include "sp-object.h"
+
+#include "paramnotebook.h"
+
+/** \brief  The root directory in the preferences database for extension
+            related parameters. */
+#define PREF_DIR "extensions"
+
+namespace Inkscape {
+namespace Extension {
+
+
+// \brief  A class to represent the pages of a notebookparameter of an extension
+class ParamNotebookPage : public Parameter {
+private:
+    GSList * parameters; /**< A table to store the parameters for this page.
+                              This only gets created if there are parameters on this
+                              page */
+    Gtk::Tooltips * _tooltips;
+    
+public:
+    static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext);
+
+    ParamNotebookPage(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
+    ~ParamNotebookPage(void);
+    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
+    Glib::ustring * paramString (void);
+    gchar * get_guitext (void) {return _text;};
+    
+}; /* class ParamNotebookPage */
+
+
+ParamNotebookPage::ParamNotebookPage (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
+    Parameter(name, guitext, desc, scope, ext)
+{
+    parameters = NULL;
+        
+    // Read XML to build page
+    if (xml != NULL) {
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);
+        while (child_repr != NULL) {
+            char const * chname = child_repr->name();
+            if (chname[0] == '_') // Allow _ for translation of tags
+                chname++;
+            if (!strcmp(chname, "param") || !strcmp(chname, "_param")) {
+                Parameter * param;
+                param = Parameter::make(child_repr, ext);
+                if (param != NULL) parameters = g_slist_append(parameters, param);
+            }
+            child_repr = sp_repr_next(child_repr);
+        }
+    }
+    
+    return;
+}
+
+ParamNotebookPage::~ParamNotebookPage (void)
+{
+    if (_tooltips) delete _tooltips;
+    //destroy parameters
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);
+        delete param;
+    }
+    g_slist_free(parameters);
+}
+
+/** \brief  Return the value as a string */
+Glib::ustring *
+ParamNotebookPage::paramString (void)
+{
+    Glib::ustring * param_string = new Glib::ustring("");
+
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);
+
+        *param_string += " --";
+        *param_string += param->name();
+        *param_string += "=";
+        Glib::ustring * paramstr = param->string();
+        *param_string += *paramstr;
+        delete paramstr;
+    }
+
+    return param_string;
+}
+
+
+/**
+    \return None
+    \brief  This function creates a page that can be used later.  This
+            is typically done in the creation of the notebook and defined
+            in the XML file describing the extension (it's private so people
+            have to use the system) :)
+    \param  in_repr  The XML describing the page
+
+    This function first grabs all of the data out of the Repr and puts
+    it into local variables.  Actually, these are just pointers, and the
+    data is not duplicated so we need to be careful with it.  If there
+    isn't a name in the XML, then no page is created as
+    the function just returns.
+
+    From this point on, we're pretty committed as we've allocated an
+    object and we're starting to fill it.  The name is set first, and
+    is created with a strdup to actually allocate memory for it.  Then
+    there is a case statement (roughly because strcmp requires 'ifs')
+    based on what type of parameter this is.  Depending which type it
+    is, the value is interpreted differently, but they are relatively
+    straight forward.  In all cases the value is set to the default
+    value from the XML and the type is set to the interpreted type.
+*/
+ParamNotebookPage *
+ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
+{
+    const char * name;
+    const char * guitext;
+    const char * desc;
+    const char * scope_str;
+    Parameter::_scope_t scope = Parameter::SCOPE_USER;
+
+    name = in_repr->attribute("name");
+    guitext = in_repr->attribute("gui-text");
+    if (guitext == NULL)
+        guitext = in_repr->attribute("_gui-text");
+    desc = in_repr->attribute("gui-description");
+    if (desc == NULL)
+        desc = in_repr->attribute("_gui-description");
+    scope_str = in_repr->attribute("scope");
+
+    /* In this case we just don't have enough information */
+    if (name == NULL) {
+        return NULL;
+    }
+
+    if (scope_str != NULL) {
+        if (!strcmp(scope_str, "user")) {
+            scope = Parameter::SCOPE_USER;
+        } else if (!strcmp(scope_str, "document")) {
+            scope = Parameter::SCOPE_DOCUMENT;
+        } else if (!strcmp(scope_str, "node")) {
+            scope = Parameter::SCOPE_NODE;
+        }
+    }
+
+    ParamNotebookPage * page = new ParamNotebookPage(name, guitext, desc, scope, in_ext, in_repr);
+    
+    /* Note: page could equal NULL */
+    return page;
+}
+
+
+
+/**
+    \brief  Creates a notebookpage widget for a notebook
+
+    Builds a notebook page (a vbox) and puts parameters on it.
+*/
+Gtk::Widget *
+ParamNotebookPage::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
+{                      
+    if (!_tooltips) _tooltips = new Gtk::Tooltips();
+    
+    Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox);
+    vbox->set_border_width(5);  
+    
+    // add parameters onto page (if any)    
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);
+        Gtk::Widget * widg = param->get_widget(doc, node);
+        gchar const * tip = param->get_tooltip();
+        
+        vbox->pack_start(*widg, true, true, 2);
+        if (tip != NULL) {
+            _tooltips->set_tip(*widg, Glib::ustring(tip));
+        }
+    }
+        
+    vbox->show();
+    
+    return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+
+
+
+
+
+
+
+
+ParamNotebook::ParamNotebook (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
+    Parameter(name, guitext, desc, scope, ext)
+{
+    pages = NULL;
+    
+    // Read XML tree to add pages:
+    if (xml != NULL) {
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);
+        while (child_repr != NULL) {
+            char const * chname = child_repr->name();
+            if (chname[0] == '_') // Allow _ for translation of tags
+                chname++;
+            if (!strcmp(chname, "page")) {
+                ParamNotebookPage * page;
+                page = ParamNotebookPage::makepage(child_repr, ext);
+                if (page != NULL) pages = g_slist_append(pages, page);
+            }
+            child_repr = sp_repr_next(child_repr);
+        }
+    }
+    
+    // Initialize _value with the current page
+    const char * defaultval = NULL;
+    // set first page as default
+    if (pages != NULL) {
+        ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data);
+        defaultval = defpage->name();
+    }
+
+    gchar * pref_name = this->pref_name();
+    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
+    g_free(pref_name);
+
+    if (paramval != NULL)
+        defaultval = paramval;
+    if (defaultval != NULL)
+        _value = g_strdup(defaultval);  // allocate space for _value
+        
+    return;
+}
+
+ParamNotebook::~ParamNotebook (void)
+{
+    //destroy pages
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
+        delete page;
+    }
+    g_slist_free(pages);
+
+    g_free(_value);
+}
+
+
+/** \brief  A function to set the \c _value
+    \param  in   The number of the page which value must be set
+    \param  doc  A document that should be used to set the value.
+    \param  node The node where the value may be placed
+
+    This function sets the internal value, but it also sets the value
+    in the preferences structure.  To put it in the right place, \c PREF_DIR
+    and \c pref_name() are used.
+
+    To copy the data into _value the old memory must be free'd first.
+    It is important to note that \c g_free handles \c NULL just fine.  Then
+    the passed in value is duplicated using \c g_strdup().
+*/
+const gchar *
+ParamNotebook::set (const int in, SPDocument * doc, Inkscape::XML::Node * node)
+{
+    ParamNotebookPage * page = NULL;
+    int i = 0;
+    for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) {
+        page = reinterpret_cast<ParamNotebookPage *>(list->data);
+        i++;
+    }
+    
+    if (page == NULL) return _value;
+   
+    if (_value != NULL) g_free(_value);
+    _value = g_strdup(page->name());
+
+    gchar * prefname = this->pref_name();
+    prefs_set_string_attribute(PREF_DIR, prefname, _value);
+    g_free(prefname);
+
+    return _value;
+}
+
+
+/**
+    \brief  A function to get the currentpage and the parameters in a string form
+    \return A string with the 'value' and all the parameters on all pages as command line arguments
+
+    This is really a hack. The function is called by Extension::paramString() to build
+    the commandline string like: '--param1name=\"param1value\" --param2name=\"param2value\" ...'
+    Extension::paramString expects this function to return '\"param1value\"'; but instead, 
+    this function returns: '\"param1value\" --page1param1name=\"page1param1value\" ...'
+
+    \TODO  Do this better. For example, make Parameter::paramString() that returns '--name=\"value\"'
+    instead of just returning '\"value\"'.
+*/
+Glib::ustring *
+ParamNotebook::string (void)
+{
+    Glib::ustring * param_string = new Glib::ustring("");
+
+    *param_string += "\"";
+    *param_string += _value;  // the name of the current page
+    *param_string += "\"";
+
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
+
+        Glib::ustring * pageparamstr = page->paramString();
+        *param_string += *pageparamstr;
+        delete pageparamstr;
+    }
+
+    return param_string;
+}
+
+/** \brief  A special category of Gtk::Notebook to handle notebook parameters */
+class ParamNotebookWdg : public Gtk::Notebook {
+private:
+    ParamNotebook * _pref;
+    SPDocument * _doc;
+    Inkscape::XML::Node * _node;
+public:
+    /** \brief  Build a notebookpage preference for the given parameter
+        \param  pref  Where to get the string (pagename) from, and where to put it
+                      when it changes.
+    */
+    ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) :
+        Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) {
+        // don't have to set the correct page: this is done in ParamNotebook::get_widget.
+        // hook function
+        this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page));
+        return;
+    };
+    void changed_page(GtkNotebookPage *page, guint pagenum);
+    bool activated;
+};
+
+/** \brief  Respond to the selected page of notebook changing
+    This function responds to the changing by reporting it to
+    ParamNotebook. The change is only reported when the notebook
+    is actually visible. This to exclude 'fake' changes when the
+    notebookpages are added or removed.
+*/
+void
+ParamNotebookWdg::changed_page(GtkNotebookPage *page,
+                                   guint pagenum)
+{
+    if (is_visible()) {
+        _pref->set((int)pagenum, _doc, _node);
+    }
+    return;
+}
+
+
+
+/**
+    \brief  Creates a Notebook widget for a notebook parameter
+
+    Builds a notebook and puts pages in it.
+*/
+Gtk::Widget *
+ParamNotebook::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
+{
+    ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node));
+
+    // add pages (if any)    
+    int i = -1;
+    int pagenr = i;
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
+        i++;  
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
+        Gtk::Widget * widg = page->get_widget(doc, node);
+        nb->append_page(*widg, _(page->get_guitext()));
+        if (!strcmp(_value, page->name())) {
+            pagenr = i; // this is the page to be displayed?
+        }
+    }
+
+    nb->show();
+    
+    if (pagenr >= 0) nb->set_current_page(pagenr);
+
+    return dynamic_cast<Gtk::Widget *>(nb);
+}
+
+
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index a7811576e69f6553b18761737be37961b36c412d..f0ab15f5744ca9f9e6c4cff15f0485c5bdf7321d 100644 (file)
@@ -1,68 +1,68 @@
-#ifndef __INK_EXTENSION_PARAMNOTEBOOK_H__\r
-#define __INK_EXTENSION_PARAMNOTEBOOK_H__\r
-\r
-/** \file\r
- * Notebook parameter for extensions.\r
- */\r
-\r
-/*\r
- * Author:\r
- *   Johan Engelen <johan@shouraizou.nl>\r
- *\r
- * Copyright (C) 2006 Author\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#include <gtkmm/widget.h>\r
-\r
-#include "xml/document.h"\r
-#include "extension-forward.h"\r
-\r
-#include "parameter.h"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-\r
-\r
-\r
-// \brief  A class to represent a notebookparameter of an extension\r
-class ParamNotebook : public Parameter {\r
-private:\r
-    /** \brief  Internal value.  This should point to a string that has\r
-                been allocated in memory.  And should be free'd. \r
-                It is the name of the current page. */\r
-    gchar * _value;\r
-    \r
-    GSList * pages; /**< A table to store the pages with parameters for this notebook.\r
-                              This only gets created if there are pages in this\r
-                              notebook */\r
-public:\r
-    ParamNotebook(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);\r
-    ~ParamNotebook(void);\r
-    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);\r
-    Glib::ustring * string (void);\r
-        \r
-    const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }\r
-    const gchar * set (const int in, SPDocument * doc, Inkscape::XML::Node * node);\r
-}; /* class ParamNotebook */\r
-\r
-\r
-\r
-\r
-\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
-#endif /* __INK_EXTENSION_PARAMNOTEBOOK_H__ */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+#ifndef __INK_EXTENSION_PARAMNOTEBOOK_H__
+#define __INK_EXTENSION_PARAMNOTEBOOK_H__
+
+/** \file
+ * Notebook parameter for extensions.
+ */
+
+/*
+ * Author:
+ *   Johan Engelen <johan@shouraizou.nl>
+ *
+ * Copyright (C) 2006 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/widget.h>
+
+#include "xml/document.h"
+#include "extension-forward.h"
+
+#include "parameter.h"
+
+namespace Inkscape {
+namespace Extension {
+
+
+
+// \brief  A class to represent a notebookparameter of an extension
+class ParamNotebook : public Parameter {
+private:
+    /** \brief  Internal value.  This should point to a string that has
+                been allocated in memory.  And should be free'd. 
+                It is the name of the current page. */
+    gchar * _value;
+    
+    GSList * pages; /**< A table to store the pages with parameters for this notebook.
+                              This only gets created if there are pages in this
+                              notebook */
+public:
+    ParamNotebook(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
+    ~ParamNotebook(void);
+    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
+    Glib::ustring * string (void);
+        
+    const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
+    const gchar * set (const int in, SPDocument * doc, Inkscape::XML::Node * node);
+}; /* class ParamNotebook */
+
+
+
+
+
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+#endif /* __INK_EXTENSION_PARAMNOTEBOOK_H__ */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 794abed94ac6e30157a4eb9f8d7696551e489fd2..3ca051f14733dd30974b8222f407385b3d4be5a7 100644 (file)
-/** \file\r
- * extension parameter for radiobuttons.\r
- *\r
- * It uses a Gtk:ComboBoxText widget in the extension UI.\r
- */\r
-\r
-/*\r
- * Author:\r
- *   Johan Engelen <johan@shouraizou.nl>\r
- *\r
- * Copyright (C) 2006-2007 Johan Engelen\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-\r
-#include <gtkmm/box.h>\r
-#include <gtkmm/radiobutton.h>\r
-#include <gtkmm/radiobuttongroup.h>\r
-#include <gtkmm/tooltips.h>\r
-#include <gtkmm/label.h>\r
-\r
-#include <glibmm/i18n.h>\r
-\r
-#include <xml/node.h>\r
-\r
-#include "extension.h"\r
-#include "prefs-utils.h"\r
-#include "document-private.h"\r
-#include "sp-object.h"\r
-\r
-#include "paramradiobutton.h"\r
-\r
-/** \brief  The root directory in the preferences database for extension\r
-            related parameters. */\r
-#define PREF_DIR "extensions"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-\r
-/* For internal use only.\r
-     Note that value and guitext MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */\r
-class optionentry {\r
-public:\r
-    optionentry (Glib::ustring * val, Glib::ustring * text) {\r
-        value = val;\r
-        guitext = text;\r
-    }\r
-    ~optionentry() {\r
-        delete value;\r
-        delete guitext;\r
-    }\r
-\r
-    Glib::ustring * value;\r
-    Glib::ustring * guitext;\r
-};\r
-\r
-ParamRadioButton::ParamRadioButton (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
-    Parameter(name, guitext, desc, scope, ext)\r
-{\r
-    choices = NULL;\r
-    _value = NULL;\r
-\r
-    // Read XML tree to add enumeration items:\r
-    // printf("Extension Constructor: ");\r
-    if (xml != NULL) {\r
-        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
-        while (child_repr != NULL) {\r
-            char const * chname = child_repr->name();\r
-            if (!strcmp(chname, "option")) {\r
-                Glib::ustring * newguitext = NULL;\r
-                Glib::ustring * newvalue = NULL;\r
-                const char * contents = sp_repr_children(child_repr)->content();\r
-                if (contents != NULL)\r
-                     newguitext = new Glib::ustring(contents);\r
-                const char * val = child_repr->attribute("value");\r
-                if (val != NULL)\r
-                    newvalue = new Glib::ustring(val);\r
-                if ( (newguitext) && (newvalue) ) {\r
-                    choices = g_slist_append( choices, new optionentry(newvalue, newguitext) );\r
-                }\r
-            }\r
-            child_repr = sp_repr_next(child_repr);\r
-        }\r
-    }\r
-\r
-    // Initialize _value with the default value from xml\r
-    // for simplicity : default to the contents of the first xml-child\r
-    const char * defaultval = NULL;\r
-    if (sp_repr_children(sp_repr_children(xml)) != NULL)\r
-        defaultval = sp_repr_children(xml)->attribute("value");\r
-\r
-        gchar * pref_name = this->pref_name();\r
-    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);\r
-    g_free(pref_name);\r
-\r
-    if (paramval != NULL)\r
-        defaultval = paramval;\r
-    if (defaultval != NULL)\r
-        _value = g_strdup(defaultval);  // allocate space for _value\r
-\r
-    return;\r
-}\r
-\r
-ParamRadioButton::~ParamRadioButton (void)\r
-{\r
-    //destroy choice strings\r
-    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {\r
-        delete (reinterpret_cast<optionentry *>(list->data));\r
-    }\r
-    g_slist_free(choices);\r
-\r
-    g_free(_value);\r
-}\r
-\r
-\r
-/** \brief  A function to set the \c _value\r
-    \param  in   The value to set\r
-    \param  doc  A document that should be used to set the value.\r
-    \param  node The node where the value may be placed\r
-\r
-    This function sets ONLY the internal value, but it also sets the value\r
-    in the preferences structure.  To put it in the right place, \c PREF_DIR\r
-    and \c pref_name() are used.\r
-\r
-    To copy the data into _value the old memory must be free'd first.\r
-    It is important to note that \c g_free handles \c NULL just fine.  Then\r
-    the passed in value is duplicated using \c g_strdup().\r
-*/\r
-const gchar *\r
-ParamRadioButton::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    if (in == NULL) return NULL; /* Can't have NULL string */\r
-\r
-    Glib::ustring * settext = NULL;\r
-    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {\r
-        optionentry * entr = reinterpret_cast<optionentry *>(list->data);\r
-        if ( !entr->guitext->compare(in) ) {\r
-            settext = entr->value;\r
-            break;  // break out of for loop\r
-        }\r
-    }\r
-    if (settext) {\r
-        if (_value != NULL) g_free(_value);\r
-        _value = g_strdup(settext->c_str());\r
-        gchar * prefname = this->pref_name();\r
-        prefs_set_string_attribute(PREF_DIR, prefname, _value);\r
-        g_free(prefname);\r
-    }\r
-\r
-    return _value;\r
-}\r
-\r
-\r
-/**\r
-    \brief  A function to get the current value of the parameter in a string form\r
-    \return A string with the 'value' as command line argument\r
-*/\r
-Glib::ustring *\r
-ParamRadioButton::string (void)\r
-{\r
-    Glib::ustring * param_string = new Glib::ustring("");\r
-\r
-    *param_string += "\"";\r
-    *param_string += _value;\r
-    *param_string += "\"";\r
-\r
-    return param_string;\r
-}\r
-\r
-/** \brief  A special radiobutton class to use in ParamRadioButton */\r
-class ParamRadioButtonWdg : public Gtk::RadioButton {\r
-private:\r
-    ParamRadioButton * _pref;\r
-    SPDocument * _doc;\r
-    Inkscape::XML::Node * _node;\r
-public:\r
-    /** \brief  Build a string preference for the given parameter\r
-        \param  pref  Where to put the radiobutton's string when it is selected.\r
-    */\r
-    ParamRadioButtonWdg ( Gtk::RadioButtonGroup& group, const Glib::ustring& label,\r
-                          ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node ) :\r
-        Gtk::RadioButton(group, label), _pref(pref), _doc(doc), _node(node) {\r
-        add_changesignal();\r
-    };\r
-    ParamRadioButtonWdg ( const Glib::ustring& label,\r
-                          ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node ) :\r
-        Gtk::RadioButton(label), _pref(pref), _doc(doc), _node(node) {\r
-        add_changesignal();\r
-    };\r
-    void add_changesignal() {\r
-        this->signal_toggled().connect(sigc::mem_fun(this, &ParamRadioButtonWdg::changed));\r
-    };\r
-    void changed (void);\r
-};\r
-\r
-/** \brief  Respond to the selected radiobutton changing\r
-\r
-    This function responds to the radiobutton selection changing by grabbing the value\r
-    from the text box and putting it in the parameter.\r
-*/\r
-void\r
-ParamRadioButtonWdg::changed (void)\r
-{\r
-    if (this->get_active()) {\r
-        Glib::ustring data = this->get_label();\r
-        _pref->set(data.c_str(), _doc, _node);\r
-    }\r
-}\r
-\r
-\r
-\r
-/**\r
-    \brief  Creates a combobox widget for an enumeration parameter\r
-*/\r
-Gtk::Widget *\r
-ParamRadioButton::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));\r
-    Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox(false, 0));\r
-\r
-    Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP));\r
-    label->show();\r
-    hbox->pack_start(*label, false, false);\r
-\r
-    // add choice strings as radiobuttons\r
-    // and select last selected option (_value)\r
-    bool first = true;\r
-    ParamRadioButtonWdg * radio;\r
-    Gtk::RadioButtonGroup group;\r
-    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {\r
-        optionentry * entr = reinterpret_cast<optionentry *>(list->data);\r
-        Glib::ustring * text = entr->guitext;\r
-        if (first) {\r
-            radio = Gtk::manage(new ParamRadioButtonWdg(*text, this, doc, node));\r
-            group = radio->get_group();\r
-            first = false;\r
-        } else {\r
-            radio = Gtk::manage(new ParamRadioButtonWdg(group, *text, this, doc, node));\r
-        }\r
-        radio->show();\r
-        vbox->pack_start(*radio, true, true);\r
-        if (!entr->value->compare(_value)) {\r
-            radio->set_active();\r
-        }\r
-    }\r
-\r
-    vbox->show();\r
-    hbox->pack_end(*vbox, false, false);\r
-    hbox->show();\r
-\r
-\r
-    return dynamic_cast<Gtk::Widget *>(hbox);\r
-}\r
-\r
-\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
+/** \file
+ * extension parameter for radiobuttons.
+ *
+ * It uses a Gtk:ComboBoxText widget in the extension UI.
+ */
+
+/*
+ * Author:
+ *   Johan Engelen <johan@shouraizou.nl>
+ *
+ * Copyright (C) 2006-2007 Johan Engelen
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <gtkmm/box.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/radiobuttongroup.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/label.h>
+
+#include <glibmm/i18n.h>
+
+#include <xml/node.h>
+
+#include "extension.h"
+#include "prefs-utils.h"
+#include "document-private.h"
+#include "sp-object.h"
+
+#include "paramradiobutton.h"
+
+/** \brief  The root directory in the preferences database for extension
+            related parameters. */
+#define PREF_DIR "extensions"
+
+namespace Inkscape {
+namespace Extension {
+
+/* For internal use only.
+     Note that value and guitext MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */
+class optionentry {
+public:
+    optionentry (Glib::ustring * val, Glib::ustring * text) {
+        value = val;
+        guitext = text;
+    }
+    ~optionentry() {
+        delete value;
+        delete guitext;
+    }
+
+    Glib::ustring * value;
+    Glib::ustring * guitext;
+};
+
+ParamRadioButton::ParamRadioButton (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
+    Parameter(name, guitext, desc, scope, ext)
+{
+    choices = NULL;
+    _value = NULL;
+
+    // Read XML tree to add enumeration items:
+    // printf("Extension Constructor: ");
+    if (xml != NULL) {
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);
+        while (child_repr != NULL) {
+            char const * chname = child_repr->name();
+            if (!strcmp(chname, "option")) {
+                Glib::ustring * newguitext = NULL;
+                Glib::ustring * newvalue = NULL;
+                const char * contents = sp_repr_children(child_repr)->content();
+                if (contents != NULL)
+                     newguitext = new Glib::ustring(contents);
+                const char * val = child_repr->attribute("value");
+                if (val != NULL)
+                    newvalue = new Glib::ustring(val);
+                if ( (newguitext) && (newvalue) ) {
+                    choices = g_slist_append( choices, new optionentry(newvalue, newguitext) );
+                }
+            }
+            child_repr = sp_repr_next(child_repr);
+        }
+    }
+
+    // Initialize _value with the default value from xml
+    // for simplicity : default to the contents of the first xml-child
+    const char * defaultval = NULL;
+    if (sp_repr_children(sp_repr_children(xml)) != NULL)
+        defaultval = sp_repr_children(xml)->attribute("value");
+
+        gchar * pref_name = this->pref_name();
+    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
+    g_free(pref_name);
+
+    if (paramval != NULL)
+        defaultval = paramval;
+    if (defaultval != NULL)
+        _value = g_strdup(defaultval);  // allocate space for _value
+
+    return;
+}
+
+ParamRadioButton::~ParamRadioButton (void)
+{
+    //destroy choice strings
+    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
+        delete (reinterpret_cast<optionentry *>(list->data));
+    }
+    g_slist_free(choices);
+
+    g_free(_value);
+}
+
+
+/** \brief  A function to set the \c _value
+    \param  in   The value to set
+    \param  doc  A document that should be used to set the value.
+    \param  node The node where the value may be placed
+
+    This function sets ONLY the internal value, but it also sets the value
+    in the preferences structure.  To put it in the right place, \c PREF_DIR
+    and \c pref_name() are used.
+
+    To copy the data into _value the old memory must be free'd first.
+    It is important to note that \c g_free handles \c NULL just fine.  Then
+    the passed in value is duplicated using \c g_strdup().
+*/
+const gchar *
+ParamRadioButton::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
+{
+    if (in == NULL) return NULL; /* Can't have NULL string */
+
+    Glib::ustring * settext = NULL;
+    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
+        optionentry * entr = reinterpret_cast<optionentry *>(list->data);
+        if ( !entr->guitext->compare(in) ) {
+            settext = entr->value;
+            break;  // break out of for loop
+        }
+    }
+    if (settext) {
+        if (_value != NULL) g_free(_value);
+        _value = g_strdup(settext->c_str());
+        gchar * prefname = this->pref_name();
+        prefs_set_string_attribute(PREF_DIR, prefname, _value);
+        g_free(prefname);
+    }
+
+    return _value;
+}
+
+
+/**
+    \brief  A function to get the current value of the parameter in a string form
+    \return A string with the 'value' as command line argument
+*/
+Glib::ustring *
+ParamRadioButton::string (void)
+{
+    Glib::ustring * param_string = new Glib::ustring("");
+
+    *param_string += "\"";
+    *param_string += _value;
+    *param_string += "\"";
+
+    return param_string;
+}
+
+/** \brief  A special radiobutton class to use in ParamRadioButton */
+class ParamRadioButtonWdg : public Gtk::RadioButton {
+private:
+    ParamRadioButton * _pref;
+    SPDocument * _doc;
+    Inkscape::XML::Node * _node;
+public:
+    /** \brief  Build a string preference for the given parameter
+        \param  pref  Where to put the radiobutton's string when it is selected.
+    */
+    ParamRadioButtonWdg ( Gtk::RadioButtonGroup& group, const Glib::ustring& label,
+                          ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node ) :
+        Gtk::RadioButton(group, label), _pref(pref), _doc(doc), _node(node) {
+        add_changesignal();
+    };
+    ParamRadioButtonWdg ( const Glib::ustring& label,
+                          ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node ) :
+        Gtk::RadioButton(label), _pref(pref), _doc(doc), _node(node) {
+        add_changesignal();
+    };
+    void add_changesignal() {
+        this->signal_toggled().connect(sigc::mem_fun(this, &ParamRadioButtonWdg::changed));
+    };
+    void changed (void);
+};
+
+/** \brief  Respond to the selected radiobutton changing
+
+    This function responds to the radiobutton selection changing by grabbing the value
+    from the text box and putting it in the parameter.
+*/
+void
+ParamRadioButtonWdg::changed (void)
+{
+    if (this->get_active()) {
+        Glib::ustring data = this->get_label();
+        _pref->set(data.c_str(), _doc, _node);
+    }
+}
+
+
+
+/**
+    \brief  Creates a combobox widget for an enumeration parameter
+*/
+Gtk::Widget *
+ParamRadioButton::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
+{
+    Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
+    Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox(false, 0));
+
+    Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP));
+    label->show();
+    hbox->pack_start(*label, false, false);
+
+    // add choice strings as radiobuttons
+    // and select last selected option (_value)
+    bool first = true;
+    ParamRadioButtonWdg * radio;
+    Gtk::RadioButtonGroup group;
+    for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
+        optionentry * entr = reinterpret_cast<optionentry *>(list->data);
+        Glib::ustring * text = entr->guitext;
+        if (first) {
+            radio = Gtk::manage(new ParamRadioButtonWdg(*text, this, doc, node));
+            group = radio->get_group();
+            first = false;
+        } else {
+            radio = Gtk::manage(new ParamRadioButtonWdg(group, *text, this, doc, node));
+        }
+        radio->show();
+        vbox->pack_start(*radio, true, true);
+        if (!entr->value->compare(_value)) {
+            radio->set_active();
+        }
+    }
+
+    vbox->show();
+    hbox->pack_end(*vbox, false, false);
+    hbox->show();
+
+
+    return dynamic_cast<Gtk::Widget *>(hbox);
+}
+
+
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
index 04c4e58468baf04833a528efd11ff6350f260743..8e1edf5b8f5f91d187d16b9f25c596cccbd9b5b5 100644 (file)
@@ -1,57 +1,57 @@
-#ifndef __INK_EXTENSION_PARAMRADIOBUTTON_H__\r
-#define __INK_EXTENSION_PARAMRADIOBUTTON_H__\r
-\r
-/** \file\r
- * Radiobutton parameter for extensions.\r
- */\r
-\r
-/*\r
- * Author:\r
- *   Johan Engelen <johan@shouraizou.nl>\r
- *\r
- * Copyright (C) 2006-2007 Johan Engelen\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#include <gtkmm/widget.h>\r
-\r
-#include "xml/document.h"\r
-#include "extension-forward.h"\r
-\r
-#include "parameter.h"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-\r
-\r
-\r
-// \brief  A class to represent a radiobutton parameter of an extension\r
-class ParamRadioButton : public Parameter {\r
-private:\r
-    /** \brief  Internal value.  This should point to a string that has\r
-                been allocated in memory.  And should be free'd. \r
-                It is the value of the current selected string */\r
-    gchar * _value;\r
-    \r
-    GSList * choices; /**< A table to store the choice strings  */\r
-    \r
-public:\r
-    ParamRadioButton(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);\r
-    ~ParamRadioButton(void);\r
-    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);\r
-    Glib::ustring * string (void);\r
-        \r
-    const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }\r
-    const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);\r
-}; /* class ParamRadioButton */\r
-\r
-\r
-\r
-\r
-\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
-#endif /* __INK_EXTENSION_PARAMRADIOBUTTON_H__ */\r
-\r
+#ifndef __INK_EXTENSION_PARAMRADIOBUTTON_H__
+#define __INK_EXTENSION_PARAMRADIOBUTTON_H__
+
+/** \file
+ * Radiobutton parameter for extensions.
+ */
+
+/*
+ * Author:
+ *   Johan Engelen <johan@shouraizou.nl>
+ *
+ * Copyright (C) 2006-2007 Johan Engelen
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/widget.h>
+
+#include "xml/document.h"
+#include "extension-forward.h"
+
+#include "parameter.h"
+
+namespace Inkscape {
+namespace Extension {
+
+
+
+// \brief  A class to represent a radiobutton parameter of an extension
+class ParamRadioButton : public Parameter {
+private:
+    /** \brief  Internal value.  This should point to a string that has
+                been allocated in memory.  And should be free'd. 
+                It is the value of the current selected string */
+    gchar * _value;
+    
+    GSList * choices; /**< A table to store the choice strings  */
+    
+public:
+    ParamRadioButton(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
+    ~ParamRadioButton(void);
+    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
+    Glib::ustring * string (void);
+        
+    const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
+    const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
+}; /* class ParamRadioButton */
+
+
+
+
+
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+#endif /* __INK_EXTENSION_PARAMRADIOBUTTON_H__ */
+
index 1f33bc65930490cfc392ac6222a31ada9c51dd72..a019b9f7d90280f369193711dc85d1ff20491f64 100644 (file)
@@ -1,38 +1,38 @@
-/* XPM */\r
-static char * cursor_gradient_add_xpm[] = {\r
-"32 32 3 1",\r
-"      c None",\r
-".     c #FFFFFF",\r
-"+     c #000000",\r
-"   ...                          ",\r
-"   .+.                          ",\r
-"   .+.                          ",\r
-"....+....                       ",\r
-".+++ +++.                       ",\r
-"....+....                       ",\r
-"   .+.                          ",\r
-"   .+.  .....                   ",\r
-"   ...  .+++.                   ",\r
-"        .+.+.                   ",\r
-"        .+++.                   ",\r
-"         .+.                    ",\r
-"         .+.                    ",\r
-"         .+.                    ",\r
-"         .+.                    ",\r
-"        .+++.                   ",\r
-"        .+.+.                   ",\r
-"        .+++.                   ",\r
-"        .....                   ",\r
-"                    ...         ",\r
-"                    .+.         ",\r
-"                    .+.         ",\r
-"                    .+.         ",\r
-"                    .+.         ",\r
-"               ......+......    ",\r
-"               .+++++++++++.    ",\r
-"               ......+......    ",\r
-"                    .+.         ",\r
-"                    .+.         ",\r
-"                    .+.         ",\r
-"                    .+.         ",\r
-"                    ...         "};\r
+/* XPM */
+static char * cursor_gradient_add_xpm[] = {
+"32 32 3 1",
+"      c None",
+".     c #FFFFFF",
+"+     c #000000",
+"   ...                          ",
+"   .+.                          ",
+"   .+.                          ",
+"....+....                       ",
+".+++ +++.                       ",
+"....+....                       ",
+"   .+.                          ",
+"   .+.  .....                   ",
+"   ...  .+++.                   ",
+"        .+.+.                   ",
+"        .+++.                   ",
+"         .+.                    ",
+"         .+.                    ",
+"         .+.                    ",
+"         .+.                    ",
+"        .+++.                   ",
+"        .+.+.                   ",
+"        .+++.                   ",
+"        .....                   ",
+"                    ...         ",
+"                    .+.         ",
+"                    .+.         ",
+"                    .+.         ",
+"                    .+.         ",
+"               ......+......    ",
+"               .+++++++++++.    ",
+"               ......+......    ",
+"                    .+.         ",
+"                    .+.         ",
+"                    .+.         ",
+"                    .+.         ",
+"                    ...         "};
index 9832aa5255f8a18d9a77e196e9b79f1c3d9e70c4..da70c95259d8d88649a866904dd94cda70cf8218 100644 (file)
@@ -1,38 +1,38 @@
-/* XPM */\r
-static char * cursor_gradient_delete_xpm[] = {\r
-"32 32 3 1",\r
-"      c None",\r
-".     c #FFFFFF",\r
-"+     c #000000",\r
-"   ...                          ",\r
-"   .+.                          ",\r
-"   .+.                          ",\r
-"....+....                       ",\r
-".+++ +++.                       ",\r
-"....+....                       ",\r
-"   .+.                          ",\r
-"   .+.  .....                   ",\r
-"   ...  .+++.                   ",\r
-"        .+.+.                   ",\r
-"        .+++.                   ",\r
-"         .+.                    ",\r
-"         .+.                    ",\r
-"         .+.                    ",\r
-"         .+.                    ",\r
-"        .+++.                   ",\r
-"        .+.+.                   ",\r
-"        .+++.                   ",\r
-"        .....                   ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"               .............    ",\r
-"               .+++++++++++.    ",\r
-"               .............    ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                "};\r
+/* XPM */
+static char * cursor_gradient_delete_xpm[] = {
+"32 32 3 1",
+"      c None",
+".     c #FFFFFF",
+"+     c #000000",
+"   ...                          ",
+"   .+.                          ",
+"   .+.                          ",
+"....+....                       ",
+".+++ +++.                       ",
+"....+....                       ",
+"   .+.                          ",
+"   .+.  .....                   ",
+"   ...  .+++.                   ",
+"        .+.+.                   ",
+"        .+++.                   ",
+"         .+.                    ",
+"         .+.                    ",
+"         .+.                    ",
+"         .+.                    ",
+"        .+++.                   ",
+"        .+.+.                   ",
+"        .+++.                   ",
+"        .....                   ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"               .............    ",
+"               .+++++++++++.    ",
+"               .............    ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
index 8a098de12383c944898898025038345a25f72484..c0027e7c38346484a128f6001af12291ca911ee5 100644 (file)
-#define __SP_FILTER_PRIMITIVE_CPP__\r
-\r
-/** \file\r
- * Superclass for all the filter primitives\r
- *\r
- */\r
-/*\r
- * Authors:\r
- *   Kees Cook <kees@outflux.net>\r
- *\r
- * Copyright (C) 2004 Kees Cook\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-#include "attributes.h"\r
-#include "sp-filter-primitive.h"\r
-#include "xml/repr.h"\r
-#include "sp-filter.h"\r
-\r
-/* FilterPrimitive base class */\r
-\r
-static void sp_filter_primitive_class_init(SPFilterPrimitiveClass *klass);\r
-static void sp_filter_primitive_init(SPFilterPrimitive *filter_primitive);\r
-\r
-static void sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);\r
-static void sp_filter_primitive_release(SPObject *object);\r
-static void sp_filter_primitive_set(SPObject *object, unsigned int key, gchar const *value);\r
-static void sp_filter_primitive_update(SPObject *object, SPCtx *ctx, guint flags);\r
-static Inkscape::XML::Node *sp_filter_primitive_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);\r
-\r
-static SPObjectClass *filter_primitive_parent_class;\r
-\r
-GType\r
-sp_filter_primitive_get_type()\r
-{\r
-    static GType filter_primitive_type = 0;\r
-\r
-    if (!filter_primitive_type) {\r
-        GTypeInfo filter_primitive_info = {\r
-            sizeof(SPFilterPrimitiveClass),\r
-            NULL, NULL,\r
-            (GClassInitFunc) sp_filter_primitive_class_init,\r
-            NULL, NULL,\r
-            sizeof(SPFilterPrimitive),\r
-            16,\r
-            (GInstanceInitFunc) sp_filter_primitive_init,\r
-            NULL,    /* value_table */\r
-        };\r
-        filter_primitive_type = g_type_register_static(SP_TYPE_OBJECT, "SPFilterPrimitive", &filter_primitive_info, (GTypeFlags)0);\r
-    }\r
-    return filter_primitive_type;\r
-}\r
-\r
-static void\r
-sp_filter_primitive_class_init(SPFilterPrimitiveClass *klass)\r
-{\r
-    //GObjectClass *gobject_class = (GObjectClass *)klass;\r
-    SPObjectClass *sp_object_class = (SPObjectClass *)klass;\r
-\r
-    filter_primitive_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);\r
-\r
-    sp_object_class->build = sp_filter_primitive_build;\r
-    sp_object_class->release = sp_filter_primitive_release;\r
-    sp_object_class->write = sp_filter_primitive_write;\r
-    sp_object_class->set = sp_filter_primitive_set;\r
-    sp_object_class->update = sp_filter_primitive_update;\r
-}\r
-\r
-static void\r
-sp_filter_primitive_init(SPFilterPrimitive *filter_primitive)\r
-{\r
-}\r
-\r
-/**\r
- * Reads the Inkscape::XML::Node, and initializes SPFilterPrimitive variables.  For this to get called,\r
- * our name must be associated with a repr via "sp_object_type_register".  Best done through\r
- * sp-object-repr.cpp's repr_name_entries array.\r
- */\r
-static void\r
-sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)\r
-{\r
-    if (((SPObjectClass *) filter_primitive_parent_class)->build) {\r
-        ((SPObjectClass *) filter_primitive_parent_class)->build(object, document, repr);\r
-    }\r
-\r
-    if (object->parent)\r
-        add_primitive((SPFilter*)object->parent, (SPFilterPrimitive*)object);\r
-}\r
-\r
-/**\r
- * Drops any allocated memory.\r
- */\r
-static void\r
-sp_filter_primitive_release(SPObject *object)\r
-{\r
-    /* deal with our children and our selves here */\r
-    if (((SPObjectClass *) filter_primitive_parent_class)->release)\r
-        ((SPObjectClass *) filter_primitive_parent_class)->release(object);\r
-}\r
-\r
-/**\r
- * Sets a specific value in the SPFilterPrimitive.\r
- */\r
-static void\r
-sp_filter_primitive_set(SPObject *object, unsigned int key, gchar const *value)\r
-{\r
-    SPFilterPrimitive *filter_primitive = SP_FILTER_PRIMITIVE(object);\r
-    (void)filter_primitive;\r
-\r
-    /* See if any parents need this value. */\r
-    if (((SPObjectClass *) filter_primitive_parent_class)->set) {\r
-        ((SPObjectClass *) filter_primitive_parent_class)->set(object, key, value);\r
-    }\r
-}\r
-\r
-/**\r
- * Receives update notifications.\r
- */\r
-static void\r
-sp_filter_primitive_update(SPObject *object, SPCtx *ctx, guint flags)\r
-{\r
-    //SPFilterPrimitive *filter_primitive = SP_FILTER_PRIMITIVE(object);\r
-\r
-    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |\r
-                 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {\r
-\r
-        /* do something to trigger redisplay, updates? */\r
-    }\r
-\r
-    if (((SPObjectClass *) filter_primitive_parent_class)->update) {\r
-        ((SPObjectClass *) filter_primitive_parent_class)->update(object, ctx, flags);\r
-    }\r
-}\r
-\r
-/**\r
- * Writes its settings to an incoming repr object, if any.\r
- */\r
-static Inkscape::XML::Node *\r
-sp_filter_primitive_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)\r
-{\r
-    //SPFilterPrimitive *filterPrimitive = SP_FILTER_PRIMITIVE(object);\r
-\r
-    // Inkscape-only object, not copied during an "plain SVG" dump:\r
-    if (flags & SP_OBJECT_WRITE_EXT) {\r
-        if (repr) {\r
-            // is this sane?\r
-            //repr->mergeFrom(SP_OBJECT_REPR(object), "id");\r
-        } else {\r
-            repr = SP_OBJECT_REPR(object)->duplicate();\r
-        }\r
-    }\r
-\r
-    if (((SPObjectClass *) filter_primitive_parent_class)->write) {\r
-        ((SPObjectClass *) filter_primitive_parent_class)->write(object, repr, flags);\r
-    }\r
-\r
-    return repr;\r
-}\r
-\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
+#define __SP_FILTER_PRIMITIVE_CPP__
+
+/** \file
+ * Superclass for all the filter primitives
+ *
+ */
+/*
+ * Authors:
+ *   Kees Cook <kees@outflux.net>
+ *
+ * Copyright (C) 2004 Kees Cook
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "attributes.h"
+#include "sp-filter-primitive.h"
+#include "xml/repr.h"
+#include "sp-filter.h"
+
+/* FilterPrimitive base class */
+
+static void sp_filter_primitive_class_init(SPFilterPrimitiveClass *klass);
+static void sp_filter_primitive_init(SPFilterPrimitive *filter_primitive);
+
+static void sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
+static void sp_filter_primitive_release(SPObject *object);
+static void sp_filter_primitive_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_filter_primitive_update(SPObject *object, SPCtx *ctx, guint flags);
+static Inkscape::XML::Node *sp_filter_primitive_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+
+static SPObjectClass *filter_primitive_parent_class;
+
+GType
+sp_filter_primitive_get_type()
+{
+    static GType filter_primitive_type = 0;
+
+    if (!filter_primitive_type) {
+        GTypeInfo filter_primitive_info = {
+            sizeof(SPFilterPrimitiveClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_filter_primitive_class_init,
+            NULL, NULL,
+            sizeof(SPFilterPrimitive),
+            16,
+            (GInstanceInitFunc) sp_filter_primitive_init,
+            NULL,    /* value_table */
+        };
+        filter_primitive_type = g_type_register_static(SP_TYPE_OBJECT, "SPFilterPrimitive", &filter_primitive_info, (GTypeFlags)0);
+    }
+    return filter_primitive_type;
+}
+
+static void
+sp_filter_primitive_class_init(SPFilterPrimitiveClass *klass)
+{
+    //GObjectClass *gobject_class = (GObjectClass *)klass;
+    SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+
+    filter_primitive_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
+
+    sp_object_class->build = sp_filter_primitive_build;
+    sp_object_class->release = sp_filter_primitive_release;
+    sp_object_class->write = sp_filter_primitive_write;
+    sp_object_class->set = sp_filter_primitive_set;
+    sp_object_class->update = sp_filter_primitive_update;
+}
+
+static void
+sp_filter_primitive_init(SPFilterPrimitive *filter_primitive)
+{
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPFilterPrimitive variables.  For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register".  Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+static void
+sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+    if (((SPObjectClass *) filter_primitive_parent_class)->build) {
+        ((SPObjectClass *) filter_primitive_parent_class)->build(object, document, repr);
+    }
+
+    if (object->parent)
+        add_primitive((SPFilter*)object->parent, (SPFilterPrimitive*)object);
+}
+
+/**
+ * Drops any allocated memory.
+ */
+static void
+sp_filter_primitive_release(SPObject *object)
+{
+    /* deal with our children and our selves here */
+    if (((SPObjectClass *) filter_primitive_parent_class)->release)
+        ((SPObjectClass *) filter_primitive_parent_class)->release(object);
+}
+
+/**
+ * Sets a specific value in the SPFilterPrimitive.
+ */
+static void
+sp_filter_primitive_set(SPObject *object, unsigned int key, gchar const *value)
+{
+    SPFilterPrimitive *filter_primitive = SP_FILTER_PRIMITIVE(object);
+    (void)filter_primitive;
+
+    /* See if any parents need this value. */
+    if (((SPObjectClass *) filter_primitive_parent_class)->set) {
+        ((SPObjectClass *) filter_primitive_parent_class)->set(object, key, value);
+    }
+}
+
+/**
+ * Receives update notifications.
+ */
+static void
+sp_filter_primitive_update(SPObject *object, SPCtx *ctx, guint flags)
+{
+    //SPFilterPrimitive *filter_primitive = SP_FILTER_PRIMITIVE(object);
+
+    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
+                 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
+
+        /* do something to trigger redisplay, updates? */
+    }
+
+    if (((SPObjectClass *) filter_primitive_parent_class)->update) {
+        ((SPObjectClass *) filter_primitive_parent_class)->update(object, ctx, flags);
+    }
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+static Inkscape::XML::Node *
+sp_filter_primitive_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+{
+    //SPFilterPrimitive *filterPrimitive = SP_FILTER_PRIMITIVE(object);
+
+    // Inkscape-only object, not copied during an "plain SVG" dump:
+    if (flags & SP_OBJECT_WRITE_EXT) {
+        if (repr) {
+            // is this sane?
+            //repr->mergeFrom(SP_OBJECT_REPR(object), "id");
+        } else {
+            repr = SP_OBJECT_REPR(object)->duplicate();
+        }
+    }
+
+    if (((SPObjectClass *) filter_primitive_parent_class)->write) {
+        ((SPObjectClass *) filter_primitive_parent_class)->write(object, repr, flags);
+    }
+
+    return repr;
+}
+
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 9fa628aa5c484c63103433a2d791ff001a8223a7..3a41f52de08fdfd25463b9f728b529c3e78caea3 100644 (file)
@@ -1,26 +1,26 @@
-#ifndef __SP_FILTER_PRIMITIVE_H__\r
-#define __SP_FILTER_PRIMITIVE_H__\r
-\r
-\r
-#include "sp-object.h"\r
-\r
-\r
-#define SP_TYPE_FILTER_PRIMITIVE (sp_filter_primitive_get_type ())\r
-#define SP_FILTER_PRIMITIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_FILTER_PRIMITIVE, SPFilterPrimitive))\r
-#define SP_FILTER_PRIMITIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_FILTER_PRIMITIVE, SPFilterPrimitiveClass))\r
-#define SP_IS_FILTER_PRIMITIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_FILTER_PRIMITIVE))\r
-#define SP_IS_FILTER_PRIMITIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_FILTER_PRIMITIVE))\r
-\r
-class SPFilterPrimitive;\r
-class SPFilterPrimitiveClass;\r
-\r
-struct SPFilterPrimitive : public SPObject {\r
-};\r
-\r
-struct SPFilterPrimitiveClass {\r
-       SPObjectClass sp_object_class;\r
-};\r
-\r
-GType sp_filter_primitive_get_type (void);\r
-\r
-#endif\r
+#ifndef __SP_FILTER_PRIMITIVE_H__
+#define __SP_FILTER_PRIMITIVE_H__
+
+
+#include "sp-object.h"
+
+
+#define SP_TYPE_FILTER_PRIMITIVE (sp_filter_primitive_get_type ())
+#define SP_FILTER_PRIMITIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_FILTER_PRIMITIVE, SPFilterPrimitive))
+#define SP_FILTER_PRIMITIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_FILTER_PRIMITIVE, SPFilterPrimitiveClass))
+#define SP_IS_FILTER_PRIMITIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_FILTER_PRIMITIVE))
+#define SP_IS_FILTER_PRIMITIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_FILTER_PRIMITIVE))
+
+class SPFilterPrimitive;
+class SPFilterPrimitiveClass;
+
+struct SPFilterPrimitive : public SPObject {
+};
+
+struct SPFilterPrimitiveClass {
+       SPObjectClass sp_object_class;
+};
+
+GType sp_filter_primitive_get_type (void);
+
+#endif
index c60ffb44f7c60cf30822804cfe52f294c45f841b..729e13d4aec5a453d16d64ed230744eea8c5d03b 100644 (file)
@@ -36,9 +36,9 @@ static void sp_filter_build(SPObject *object, SPDocument *document, Inkscape::XM
 static void sp_filter_release(SPObject *object);
 static void sp_filter_set(SPObject *object, unsigned int key, gchar const *value);
 static void sp_filter_update(SPObject *object, SPCtx *ctx, guint flags);
-static void sp_filter_child_added(SPObject *object,\r
-                                    Inkscape::XML::Node *child,\r
-                                    Inkscape::XML::Node *ref);\r
+static void sp_filter_child_added(SPObject *object,
+                                    Inkscape::XML::Node *child,
+                                    Inkscape::XML::Node *ref);
 static void sp_filter_remove_child(SPObject *object, Inkscape::XML::Node *child);
 static Inkscape::XML::Node *sp_filter_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
 
@@ -81,7 +81,7 @@ sp_filter_class_init(SPFilterClass *klass)
     sp_object_class->write = sp_filter_write;
     sp_object_class->set = sp_filter_set;
     sp_object_class->update = sp_filter_update;
-    sp_object_class->child_added = sp_filter_child_added;\r
+    sp_object_class->child_added = sp_filter_child_added;
     sp_object_class->remove_child = sp_filter_remove_child;
 }
 
index 6159b4fe52f4238d14e1dee45eab6de6c65f4f0a..7b19ac861e3227c90e68df92793e591345867f0b 100644 (file)
@@ -1,35 +1,35 @@
-/** \file\r
- *\r
- * \brief Helperclass for Gtk::Entry widgets\r
- *\r
- * Authors:\r
- *   Johan Engelen <goejendaagh@zonnet.nl>\r
- *\r
- * Copyright (C) 2006 Authors\r
- *\r
- * Released under GNU GPL.  Read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include <config.h>\r
-#endif\r
-\r
-#include "entry.h"\r
-\r
-namespace Inkscape {\r
-namespace UI {\r
-namespace Widget {\r
-\r
-Entry::Entry(  Glib::ustring const &label, Glib::ustring const &tooltip,\r
-               Glib::ustring const &suffix,\r
-               Glib::ustring const &icon,\r
-               bool mnemonic)\r
-    : Labelled(label, tooltip, new Gtk::Entry(), suffix, icon, mnemonic)\r
-{\r    
-}\r
-    \r
-\r
-} // namespace Widget\r
-} // namespace UI\r
-} // namespace Inkscape\r
-\r
+/** \file
+ *
+ * \brief Helperclass for Gtk::Entry widgets
+ *
+ * Authors:
+ *   Johan Engelen <goejendaagh@zonnet.nl>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL.  Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "entry.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+Entry::Entry(  Glib::ustring const &label, Glib::ustring const &tooltip,
+               Glib::ustring const &suffix,
+               Glib::ustring const &icon,
+               bool mnemonic)
+    : Labelled(label, tooltip, new Gtk::Entry(), suffix, icon, mnemonic)
+{    
+}
+    
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
index 06cb19bef19d6593321f3f5b0e0dfada6b6f5a8f..bb6c1321a63b60c63ffa89a77af06c73f4eb1661 100644 (file)
@@ -1,44 +1,44 @@
-/** \file \r
- *\r
- * \brief Helperclass for Gtk::Entry widgets\r
- *\r
- * Authors:\r
- *   Johan Engelen <goejendaagh@zonnet.nl>\r
- *\r
- * Copyright (C) 2006 Authors\r
- *\r
- * Released under GNU GPL.  Read the file 'COPYING' for more information.\r
- */\r
-\r
-#ifndef INKSCAPE_UI_WIDGET_ENTRY__H\r
-#define INKSCAPE_UI_WIDGET_ENTRY__H\r
-\r
-#include <gtkmm/entry.h>\r
-#include <gtkmm/tooltips.h>\r
-#include <gtkmm/label.h>\r
-#include <gtkmm/box.h>\r
-#include "labelled.h"\r
-\r
-namespace Inkscape {\r
-namespace UI {\r
-namespace Widget {\r
-\r
-class Entry : public Labelled\r
-{\r
-public:\r
-    Entry( Glib::ustring const &label,\r
-           Glib::ustring const &tooltip,\r
-           Glib::ustring const &suffix = "",\r
-           Glib::ustring const &icon = "",\r
-           bool mnemonic = true);\r
-\r
-    // TO DO: add methods to access Gtk::Entry widget\r
-    \r
-    Gtk::Entry*  getEntry() {return (Gtk::Entry*)(_widget);};    \r
-};\r
-\r
-} // namespace Widget\r
-} // namespace UI\r
-} // namespace Inkscape\r
-\r
-#endif // INKSCAPE_UI_WIDGET_ENTRY__H\r
+/** \file 
+ *
+ * \brief Helperclass for Gtk::Entry widgets
+ *
+ * Authors:
+ *   Johan Engelen <goejendaagh@zonnet.nl>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL.  Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_ENTRY__H
+#define INKSCAPE_UI_WIDGET_ENTRY__H
+
+#include <gtkmm/entry.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/label.h>
+#include <gtkmm/box.h>
+#include "labelled.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Entry : public Labelled
+{
+public:
+    Entry( Glib::ustring const &label,
+           Glib::ustring const &tooltip,
+           Glib::ustring const &suffix = "",
+           Glib::ustring const &icon = "",
+           bool mnemonic = true);
+
+    // TO DO: add methods to access Gtk::Entry widget
+    
+    Gtk::Entry*  getEntry() {return (Gtk::Entry*)(_widget);};    
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_ENTRY__H
index bea891742e7253c2cfc7b43c2dde5e5abeac86a2..6afec5e3cb1effebc61ab291a0f4a5b27382ca77 100644 (file)
-/*\r
- * Inkscape::Util::FixedPoint - fixed point type\r
- *\r
- * Authors:\r
- *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>\r
- *\r
- * Copyright (C) 2006 Jasper van de Gronde\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
-#define SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
-\r
-#include "traits/reference.h"\r
-#include <math.h>\r
-#include <algorithm>\r
-#include <limits>\r
-\r
-namespace Inkscape {\r
-\r
-namespace Util {\r
-\r
-template <typename T, unsigned int precision>\r
-class FixedPoint {\r
-public:\r
-    FixedPoint() {}\r
-    FixedPoint(const FixedPoint& value) : v(value.v) {}\r
-    FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}\r
-\r
-    FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }\r
-    FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }\r
-    FixedPoint& operator*=(FixedPoint val) {\r
-        const unsigned int half_size = 8*sizeof(T)/2;\r
-        const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);\r
-        const T ah = v>>half_size, bh = val.v>>half_size;\r
-        v = static_cast<unsigned int>(al*bl)>>precision;\r
-        if ( half_size >= precision ) {\r
-            v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);\r
-        } else {\r
-            v += ((al*bh)+(ah*bl))>>(precision-half_size);\r
-            v += (ah*bh)<<(2*half_size-precision);\r
-        }\r
-        return *this;\r
-    }\r
-\r
-    FixedPoint& operator*=(char val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(short val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(int val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }\r
-\r
-    FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }\r
-    FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }\r
-    FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }\r
-\r
-    FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }\r
-\r
-    float operator*(float val) const { return static_cast<float>(*this)*val; }\r
-    double operator*(double val) const { return static_cast<double>(*this)*val; }\r
-\r
-    operator char() const { return v>>precision; }\r
-    operator unsigned char() const { return v>>precision; }\r
-    operator short() const { return v>>precision; }\r
-    operator unsigned short() const { return v>>precision; }\r
-    operator int() const { return v>>precision; }\r
-    operator unsigned int() const { return v>>precision; }\r
-\r
-    operator float() const { return ldexpf(v,-precision); }\r
-    operator double() const { return ldexp(v,-precision); }\r
-private:\r
-    T v;\r
-};\r
-\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }\r
-\r
-template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }\r
-template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }\r
-\r
-}\r
-\r
-}\r
-\r
-#endif\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
-/*\r
- * Inkscape::Util::FixedPoint - fixed point type\r
- *\r
- * Authors:\r
- *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>\r
- *\r
- * Copyright (C) 2006 Jasper van de Gronde\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
-#define SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
-\r
-#include "traits/reference.h"\r
-#include <math.h>\r
-#include <algorithm>\r
-#include <limits>\r
-\r
-namespace Inkscape {\r
-\r
-namespace Util {\r
-\r
-template <typename T, unsigned int precision>\r
-class FixedPoint {\r
-public:\r
-    FixedPoint() {}\r
-    FixedPoint(const FixedPoint& value) : v(value.v) {}\r
-    FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}\r
-\r
-    FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }\r
-    FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }\r
-    FixedPoint& operator*=(FixedPoint val) {\r
-        const unsigned int half_size = 8*sizeof(T)/2;\r
-        const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);\r
-        const T ah = v>>half_size, bh = val.v>>half_size;\r
-        v = static_cast<unsigned int>(al*bl)>>precision;\r
-        if ( half_size >= precision ) {\r
-            v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);\r
-        } else {\r
-            v += ((al*bh)+(ah*bl))>>(precision-half_size);\r
-            v += (ah*bh)<<(2*half_size-precision);\r
-        }\r
-        return *this;\r
-    }\r
-\r
-    FixedPoint& operator*=(char val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(short val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(int val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }\r
-\r
-    FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }\r
-    FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }\r
-    FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }\r
-\r
-    FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }\r
-\r
-    float operator*(float val) const { return static_cast<float>(*this)*val; }\r
-    double operator*(double val) const { return static_cast<double>(*this)*val; }\r
-\r
-    operator char() const { return v>>precision; }\r
-    operator unsigned char() const { return v>>precision; }\r
-    operator short() const { return v>>precision; }\r
-    operator unsigned short() const { return v>>precision; }\r
-    operator int() const { return v>>precision; }\r
-    operator unsigned int() const { return v>>precision; }\r
-\r
-    operator float() const { return ldexpf(v,-precision); }\r
-    operator double() const { return ldexp(v,-precision); }\r
-private:\r
-    T v;\r
-};\r
-\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }\r
-\r
-template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }\r
-template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }\r
-\r
-}\r
-\r
-}\r
-\r
-#endif\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
-/*\r
- * Inkscape::Util::FixedPoint - fixed point type\r
- *\r
- * Authors:\r
- *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>\r
- *\r
- * Copyright (C) 2006 Jasper van de Gronde\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
-#define SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
-\r
-#include "traits/reference.h"\r
-#include <math.h>\r
-#include <algorithm>\r
-#include <limits>\r
-\r
-namespace Inkscape {\r
-\r
-namespace Util {\r
-\r
-template <typename T, unsigned int precision>\r
-class FixedPoint {\r
-public:\r
-    FixedPoint() {}\r
-    FixedPoint(const FixedPoint& value) : v(value.v) {}\r
-    FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}\r
-    FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}\r
-\r
-    FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }\r
-    FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }\r
-    FixedPoint& operator*=(FixedPoint val) {\r
-        const unsigned int half_size = 8*sizeof(T)/2;\r
-        const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);\r
-        const T ah = v>>half_size, bh = val.v>>half_size;\r
-        v = static_cast<unsigned int>(al*bl)>>precision;\r
-        if ( half_size >= precision ) {\r
-            v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);\r
-        } else {\r
-            v += ((al*bh)+(ah*bl))>>(precision-half_size);\r
-            v += (ah*bh)<<(2*half_size-precision);\r
-        }\r
-        return *this;\r
-    }\r
-\r
-    FixedPoint& operator*=(char val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(short val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(int val) { v *= val; return *this; }\r
-    FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }\r
-\r
-    FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }\r
-    FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }\r
-    FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }\r
-\r
-    FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }\r
-    FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }\r
-\r
-    float operator*(float val) const { return static_cast<float>(*this)*val; }\r
-    double operator*(double val) const { return static_cast<double>(*this)*val; }\r
-\r
-    operator char() const { return v>>precision; }\r
-    operator unsigned char() const { return v>>precision; }\r
-    operator short() const { return v>>precision; }\r
-    operator unsigned short() const { return v>>precision; }\r
-    operator int() const { return v>>precision; }\r
-    operator unsigned int() const { return v>>precision; }\r
-\r
-    operator float() const { return ldexpf(v,-precision); }\r
-    operator double() const { return ldexp(v,-precision); }\r
-private:\r
-    T v;\r
-};\r
-\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }\r
-template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }\r
-\r
-template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }\r
-template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }\r
-\r
-}\r
-\r
-}\r
-\r
-#endif\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
+/*
+ * Inkscape::Util::FixedPoint - fixed point type
+ *
+ * Authors:
+ *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>
+ *
+ * Copyright (C) 2006 Jasper van de Gronde
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H
+#define SEEN_INKSCAPE_UTIL_FIXED_POINT_H
+
+#include "traits/reference.h"
+#include <math.h>
+#include <algorithm>
+#include <limits>
+
+namespace Inkscape {
+
+namespace Util {
+
+template <typename T, unsigned int precision>
+class FixedPoint {
+public:
+    FixedPoint() {}
+    FixedPoint(const FixedPoint& value) : v(value.v) {}
+    FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}
+
+    FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }
+    FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }
+    FixedPoint& operator*=(FixedPoint val) {
+        const unsigned int half_size = 8*sizeof(T)/2;
+        const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);
+        const T ah = v>>half_size, bh = val.v>>half_size;
+        v = static_cast<unsigned int>(al*bl)>>precision;
+        if ( half_size >= precision ) {
+            v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);
+        } else {
+            v += ((al*bh)+(ah*bl))>>(precision-half_size);
+            v += (ah*bh)<<(2*half_size-precision);
+        }
+        return *this;
+    }
+
+    FixedPoint& operator*=(char val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }
+    FixedPoint& operator*=(short val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }
+    FixedPoint& operator*=(int val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }
+
+    FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }
+    FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }
+    FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }
+
+    FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }
+
+    float operator*(float val) const { return static_cast<float>(*this)*val; }
+    double operator*(double val) const { return static_cast<double>(*this)*val; }
+
+    operator char() const { return v>>precision; }
+    operator unsigned char() const { return v>>precision; }
+    operator short() const { return v>>precision; }
+    operator unsigned short() const { return v>>precision; }
+    operator int() const { return v>>precision; }
+    operator unsigned int() const { return v>>precision; }
+
+    operator float() const { return ldexpf(v,-precision); }
+    operator double() const { return ldexp(v,-precision); }
+private:
+    T v;
+};
+
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }
+
+template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }
+template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }
+
+}
+
+}
+
+#endif
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+/*
+ * Inkscape::Util::FixedPoint - fixed point type
+ *
+ * Authors:
+ *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>
+ *
+ * Copyright (C) 2006 Jasper van de Gronde
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H
+#define SEEN_INKSCAPE_UTIL_FIXED_POINT_H
+
+#include "traits/reference.h"
+#include <math.h>
+#include <algorithm>
+#include <limits>
+
+namespace Inkscape {
+
+namespace Util {
+
+template <typename T, unsigned int precision>
+class FixedPoint {
+public:
+    FixedPoint() {}
+    FixedPoint(const FixedPoint& value) : v(value.v) {}
+    FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}
+
+    FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }
+    FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }
+    FixedPoint& operator*=(FixedPoint val) {
+        const unsigned int half_size = 8*sizeof(T)/2;
+        const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);
+        const T ah = v>>half_size, bh = val.v>>half_size;
+        v = static_cast<unsigned int>(al*bl)>>precision;
+        if ( half_size >= precision ) {
+            v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);
+        } else {
+            v += ((al*bh)+(ah*bl))>>(precision-half_size);
+            v += (ah*bh)<<(2*half_size-precision);
+        }
+        return *this;
+    }
+
+    FixedPoint& operator*=(char val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }
+    FixedPoint& operator*=(short val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }
+    FixedPoint& operator*=(int val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }
+
+    FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }
+    FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }
+    FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }
+
+    FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }
+
+    float operator*(float val) const { return static_cast<float>(*this)*val; }
+    double operator*(double val) const { return static_cast<double>(*this)*val; }
+
+    operator char() const { return v>>precision; }
+    operator unsigned char() const { return v>>precision; }
+    operator short() const { return v>>precision; }
+    operator unsigned short() const { return v>>precision; }
+    operator int() const { return v>>precision; }
+    operator unsigned int() const { return v>>precision; }
+
+    operator float() const { return ldexpf(v,-precision); }
+    operator double() const { return ldexp(v,-precision); }
+private:
+    T v;
+};
+
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }
+
+template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }
+template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }
+
+}
+
+}
+
+#endif
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+/*
+ * Inkscape::Util::FixedPoint - fixed point type
+ *
+ * Authors:
+ *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>
+ *
+ * Copyright (C) 2006 Jasper van de Gronde
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H
+#define SEEN_INKSCAPE_UTIL_FIXED_POINT_H
+
+#include "traits/reference.h"
+#include <math.h>
+#include <algorithm>
+#include <limits>
+
+namespace Inkscape {
+
+namespace Util {
+
+template <typename T, unsigned int precision>
+class FixedPoint {
+public:
+    FixedPoint() {}
+    FixedPoint(const FixedPoint& value) : v(value.v) {}
+    FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}
+    FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}
+
+    FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }
+    FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }
+    FixedPoint& operator*=(FixedPoint val) {
+        const unsigned int half_size = 8*sizeof(T)/2;
+        const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);
+        const T ah = v>>half_size, bh = val.v>>half_size;
+        v = static_cast<unsigned int>(al*bl)>>precision;
+        if ( half_size >= precision ) {
+            v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);
+        } else {
+            v += ((al*bh)+(ah*bl))>>(precision-half_size);
+            v += (ah*bh)<<(2*half_size-precision);
+        }
+        return *this;
+    }
+
+    FixedPoint& operator*=(char val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }
+    FixedPoint& operator*=(short val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }
+    FixedPoint& operator*=(int val) { v *= val; return *this; }
+    FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }
+
+    FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }
+    FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }
+    FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }
+
+    FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }
+    FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }
+
+    float operator*(float val) const { return static_cast<float>(*this)*val; }
+    double operator*(double val) const { return static_cast<double>(*this)*val; }
+
+    operator char() const { return v>>precision; }
+    operator unsigned char() const { return v>>precision; }
+    operator short() const { return v>>precision; }
+    operator unsigned short() const { return v>>precision; }
+    operator int() const { return v>>precision; }
+    operator unsigned int() const { return v>>precision; }
+
+    operator float() const { return ldexpf(v,-precision); }
+    operator double() const { return ldexp(v,-precision); }
+private:
+    T v;
+};
+
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }
+template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }
+
+template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }
+template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }
+
+}
+
+}
+
+#endif
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :