From: joncruz Date: Mon, 19 Feb 2007 20:48:09 +0000 (+0000) Subject: Cleaned up DOS line ends that had snuck in. X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=91934be261c16d036521379306a74b0991720e67;p=inkscape.git Cleaned up DOS line ends that had snuck in. --- diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 2f986f16f..9dfbed925 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -1,469 +1,469 @@ -#define SP_CANVAS_AXONOMGRID_C - -/* - * SPCAxonomGrid - * - * Copyright (C) 2006 Johan Engelen - * 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 - -#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 : +#define SP_CANVAS_AXONOMGRID_C + +/* + * SPCAxonomGrid + * + * Copyright (C) 2006 Johan Engelen + * 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 + +#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 : diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index 22fceed44..79de72b43 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -1,59 +1,59 @@ -#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 - * Copyright (C) 2000 Lauris Kaplinski 2000 - * - */ - -#include -#include - - -#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 - - +#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 + * Copyright (C) 2000 Lauris Kaplinski 2000 + * + */ + +#include +#include + + +#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 + + diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp index be0c9c5be..7ebeebd88 100644 --- a/src/display/nr-filter-gaussian.cpp +++ b/src/display/nr-filter-gaussian.cpp @@ -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); + 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<=0 ; shift-=8) - { - int ch = (val >> shift) & 0xff; - printf("%02x", ch); - } -} -*/ - - -static char *hexDigits = "0123456789abcdef"; - -static std::string toHex(const std::vector &bytes) -{ - std::string str; - std::vector::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 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 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 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 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 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 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 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 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 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 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 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 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 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 -//######################################################################## +/** + * 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 &bytes) +{ + std::string str; + std::vector::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 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 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 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 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 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 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 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 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 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 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 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 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 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 +//######################################################################## diff --git a/src/dom/util/digest.h b/src/dom/util/digest.h index 3667a25a9..46c60d2a3 100644 --- a/src/dom/util/digest.h +++ b/src/dom/util/digest.h @@ -1,493 +1,493 @@ -#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 -#include - - -/** - * 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 buf) - { - for (unsigned int i=0 ; i finish() - { - std::vector 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 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 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 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 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 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 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__ */ - - +#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 +#include + + +/** + * 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 buf) + { + for (unsigned int i=0 ; i finish() + { + std::vector 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 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 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 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 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 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 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__ */ + + diff --git a/src/extension/internal/cairo-pdf-out.cpp b/src/extension/internal/cairo-pdf-out.cpp index 9ee1ae32f..88010e686 100644 --- a/src/extension/internal/cairo-pdf-out.cpp +++ b/src/extension/internal/cairo-pdf-out.cpp @@ -1,150 +1,150 @@ -/* - * A quick hack to use the print output to write out a file. This - * then makes 'save as...' PDF. - * - * Authors: - * Ted Gould - * Ulf Erikson - * - * Copyright (C) 2004-2006 Authors - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef HAVE_CAIRO_PDF - -#include "cairo-pdf-out.h" -#include -#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( - "\n" - "Cairo PDF Output\n" - "org.inkscape.output.pdf.cairo\n" - "\n" - ".pdf\n" - "application/pdf\n" - "Cairo PDF (*.pdf)\n" - "PDF File\n" - "\n" - "", new CairoPdfOutput()); - - return; -} - -} } } /* namespace Inkscape, Extension, Implementation */ - -#endif /* HAVE_CAIRO_PDF */ +/* + * A quick hack to use the print output to write out a file. This + * then makes 'save as...' PDF. + * + * Authors: + * Ted Gould + * Ulf Erikson + * + * Copyright (C) 2004-2006 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_CAIRO_PDF + +#include "cairo-pdf-out.h" +#include +#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( + "\n" + "Cairo PDF Output\n" + "org.inkscape.output.pdf.cairo\n" + "\n" + ".pdf\n" + "application/pdf\n" + "Cairo PDF (*.pdf)\n" + "PDF File\n" + "\n" + "", new CairoPdfOutput()); + + return; +} + +} } } /* namespace Inkscape, Extension, Implementation */ + +#endif /* HAVE_CAIRO_PDF */ diff --git a/src/extension/internal/cairo-pdf-out.h b/src/extension/internal/cairo-pdf-out.h index f0e67f165..42cd9365c 100644 --- a/src/extension/internal/cairo-pdf-out.h +++ b/src/extension/internal/cairo-pdf-out.h @@ -1,50 +1,50 @@ -/* - * A quick hack to use the print output to write out a file. This - * then makes 'save as...' PDF. - * - * Authors: - * Ted Gould - * Ulf Erikson - * - * 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 : +/* + * A quick hack to use the print output to write out a file. This + * then makes 'save as...' PDF. + * + * Authors: + * Ted Gould + * Ulf Erikson + * + * 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 : diff --git a/src/extension/internal/cairo-png-out.cpp b/src/extension/internal/cairo-png-out.cpp index f34a90b22..6fd45d0d5 100644 --- a/src/extension/internal/cairo-png-out.cpp +++ b/src/extension/internal/cairo-png-out.cpp @@ -1,133 +1,133 @@ -/* - * A quick hack to use the Cairo renderer to write out a file. This - * then makes 'save as...' PNG. - * - * Authors: - * Ted Gould - * Ulf Erikson - * - * Copyright (C) 2004-2006 Authors - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef HAVE_CAIRO_PDF - -#include "cairo-png-out.h" -#include "cairo-render-context.h" -#include "cairo-renderer.h" -#include -#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 - -#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( - "\n" - "Cairo PNG Output\n" - "org.inkscape.output.png.cairo\n" - "\n" - ".png\n" - "image/png\n" - "Cairo PNG (*.png)\n" - "PNG File\n" - "\n" - "", new CairoRendererOutput()); - - return; -} - -} } } /* namespace Inkscape, Extension, Implementation */ - -#endif /* HAVE_CAIRO_PDF */ +/* + * A quick hack to use the Cairo renderer to write out a file. This + * then makes 'save as...' PNG. + * + * Authors: + * Ted Gould + * Ulf Erikson + * + * Copyright (C) 2004-2006 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_CAIRO_PDF + +#include "cairo-png-out.h" +#include "cairo-render-context.h" +#include "cairo-renderer.h" +#include +#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 + +#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( + "\n" + "Cairo PNG Output\n" + "org.inkscape.output.png.cairo\n" + "\n" + ".png\n" + "image/png\n" + "Cairo PNG (*.png)\n" + "PNG File\n" + "\n" + "", new CairoRendererOutput()); + + return; +} + +} } } /* namespace Inkscape, Extension, Implementation */ + +#endif /* HAVE_CAIRO_PDF */ diff --git a/src/extension/internal/cairo-png-out.h b/src/extension/internal/cairo-png-out.h index 207786c88..625c53ffc 100644 --- a/src/extension/internal/cairo-png-out.h +++ b/src/extension/internal/cairo-png-out.h @@ -1,50 +1,50 @@ -/* - * A quick hack to use the print output to write out a file. This - * then makes 'save as...' PNG. - * - * Authors: - * Ted Gould - * Ulf Erikson - * - * 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 : +/* + * A quick hack to use the print output to write out a file. This + * then makes 'save as...' PNG. + * + * Authors: + * Ted Gould + * Ulf Erikson + * + * 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 : diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp index 5d2765660..82b736ad2 100644 --- a/src/extension/internal/cairo-renderer-pdf-out.cpp +++ b/src/extension/internal/cairo-renderer-pdf-out.cpp @@ -1,133 +1,133 @@ -/* - * A quick hack to use the Cairo renderer to write out a file. This - * then makes 'save as...' PDF. - * - * Authors: - * Ted Gould - * Ulf Erikson - * - * Copyright (C) 2004-2006 Authors - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef HAVE_CAIRO_PDF - -#include "cairo-renderer-pdf-out.h" -#include "cairo-render-context.h" -#include "cairo-renderer.h" -#include -#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 - -#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( - "\n" - "Cairo PDF Output (experimental)\n" - "org.inkscape.output.pdf.cairorenderer\n" - "\n" - ".pdf\n" - "application/pdf\n" - "Cairo PDF experimental (*.pdf)\n" - "PDF File\n" - "\n" - "", new CairoRendererPdfOutput()); - - return; -} - -} } } /* namespace Inkscape, Extension, Internal */ - -#endif /* HAVE_CAIRO_PDF */ +/* + * A quick hack to use the Cairo renderer to write out a file. This + * then makes 'save as...' PDF. + * + * Authors: + * Ted Gould + * Ulf Erikson + * + * Copyright (C) 2004-2006 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_CAIRO_PDF + +#include "cairo-renderer-pdf-out.h" +#include "cairo-render-context.h" +#include "cairo-renderer.h" +#include +#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 + +#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( + "\n" + "Cairo PDF Output (experimental)\n" + "org.inkscape.output.pdf.cairorenderer\n" + "\n" + ".pdf\n" + "application/pdf\n" + "Cairo PDF experimental (*.pdf)\n" + "PDF File\n" + "\n" + "", new CairoRendererPdfOutput()); + + return; +} + +} } } /* namespace Inkscape, Extension, Internal */ + +#endif /* HAVE_CAIRO_PDF */ diff --git a/src/extension/internal/cairo-renderer-pdf-out.h b/src/extension/internal/cairo-renderer-pdf-out.h index d7d5a6681..1c18519a0 100644 --- a/src/extension/internal/cairo-renderer-pdf-out.h +++ b/src/extension/internal/cairo-renderer-pdf-out.h @@ -1,50 +1,50 @@ -/* - * A quick hack to use the Cairo renderer to write out a file. This - * then makes 'save as...' PDF. - * - * Authors: - * Ted Gould - * Ulf Erikson - * - * 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 : +/* + * A quick hack to use the Cairo renderer to write out a file. This + * then makes 'save as...' PDF. + * + * Authors: + * Ted Gould + * Ulf Erikson + * + * 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 : diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index a39d1fb1d..b9d65f50c 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -1,1430 +1,1430 @@ -/** \file - * Enhanced Metafile Input and Output. - */ -/* - * Authors: - * Ulf Erikson - * - * 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 -#include - -#include -#include - -#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; istyle.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; ielp.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 << "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) += " 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; icptl; ) { - tmp_str << "\n\tC "; - for (j=0; j<3 && icptl; 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) += " 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; icptl; 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) += " 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; icptl; 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; icptl;) { - tmp_path << "\n\tC "; - for (j=0; j<3 && icptl; 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; icptl;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 << "\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) += " 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) += " 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; icpts; ) { - tmp_str << "\n\tC "; - for (j=0; j<3 && icpts; 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) += "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; icpts; 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) += " 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; icpts; 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; icpts;) { - tmp_path << "\n\tC "; - for (j=0; j<3 && icpts; 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; icpts;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) += "outsvg) += "\n\td=\""; - - i = pEmr->nPolys-1; // ??? - for (n=0; nnPolys /*&& icpts*/; 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; jaPolyCounts[n] /*&& icpts*/; 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; ielp.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\n" - "" N_("EMF Input") "\n" - "org.inkscape.input.emf.win32\n" - "\n" - ".emf\n" - "image/x-emf\n" - "" N_("Enhanced Metafiles (*.emf)") "\n" - "" N_("Enhanced Metafiles") "\n" - "org.inkscape.output.emf.win32\n" - "\n" - "", new EmfWin32()); - - /* WMF in */ - ext = Inkscape::Extension::build_from_mem( - "\n" - "" N_("WMF Input") "\n" - "org.inkscape.input.wmf.win32\n" - "\n" - ".wmf\n" - "image/x-wmf\n" - "" N_("Windows Metafiles (*.wmf)") "\n" - "" N_("Windows Metafiles") "\n" - "org.inkscape.output.emf.win32\n" - "\n" - "", new EmfWin32()); - - /* EMF out */ - ext = Inkscape::Extension::build_from_mem( - "\n" - "" N_("EMF Output") "\n" - "org.inkscape.output.emf.win32\n" - "\n" - ".emf\n" - "image/x-emf\n" - "" N_("Enhanced Metafile (*.emf)") "\n" - "" N_("Enhanced Metafile") "\n" - "\n" - "", 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 : +/** \file + * Enhanced Metafile Input and Output. + */ +/* + * Authors: + * Ulf Erikson + * + * 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 +#include + +#include +#include + +#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; istyle.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; ielp.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 << "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) += " 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; icptl; ) { + tmp_str << "\n\tC "; + for (j=0; j<3 && icptl; 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) += " 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; icptl; 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) += " 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; icptl; 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; icptl;) { + tmp_path << "\n\tC "; + for (j=0; j<3 && icptl; 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; icptl;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 << "\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) += " 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) += " 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; icpts; ) { + tmp_str << "\n\tC "; + for (j=0; j<3 && icpts; 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) += "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; icpts; 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) += " 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; icpts; 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; icpts;) { + tmp_path << "\n\tC "; + for (j=0; j<3 && icpts; 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; icpts;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) += "outsvg) += "\n\td=\""; + + i = pEmr->nPolys-1; // ??? + for (n=0; nnPolys /*&& icpts*/; 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; jaPolyCounts[n] /*&& icpts*/; 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; ielp.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\n" + "" N_("EMF Input") "\n" + "org.inkscape.input.emf.win32\n" + "\n" + ".emf\n" + "image/x-emf\n" + "" N_("Enhanced Metafiles (*.emf)") "\n" + "" N_("Enhanced Metafiles") "\n" + "org.inkscape.output.emf.win32\n" + "\n" + "", new EmfWin32()); + + /* WMF in */ + ext = Inkscape::Extension::build_from_mem( + "\n" + "" N_("WMF Input") "\n" + "org.inkscape.input.wmf.win32\n" + "\n" + ".wmf\n" + "image/x-wmf\n" + "" N_("Windows Metafiles (*.wmf)") "\n" + "" N_("Windows Metafiles") "\n" + "org.inkscape.output.emf.win32\n" + "\n" + "", new EmfWin32()); + + /* EMF out */ + ext = Inkscape::Extension::build_from_mem( + "\n" + "" N_("EMF Output") "\n" + "org.inkscape.output.emf.win32\n" + "\n" + ".emf\n" + "image/x-emf\n" + "" N_("Enhanced Metafile (*.emf)") "\n" + "" N_("Enhanced Metafile") "\n" + "\n" + "", 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 : diff --git a/src/extension/internal/emf-win32-inout.h b/src/extension/internal/emf-win32-inout.h index eff850049..3ec81b6b5 100644 --- a/src/extension/internal/emf-win32-inout.h +++ b/src/extension/internal/emf-win32-inout.h @@ -1,60 +1,60 @@ -/* - * Enhanced Metafile Input/Output. - * - * Authors: - * Ulf Erikson - * - * 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 : +/* + * Enhanced Metafile Input/Output. + * + * Authors: + * Ulf Erikson + * + * 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 : diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index b40eec462..9b1b77f16 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -1,629 +1,629 @@ -/** \file - * Enhanced Metafile Printing. - */ -/* - * Authors: - * Ulf Erikson - * - * 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 -#include -#include - -#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 - -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( - "\n" - "Enhanced Metafile Print\n" - "org.inkscape.print.emf.win32\n" - "\n" - "TRUE\n" - "TRUE\n" - "\n" - "", 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 : +/** \file + * Enhanced Metafile Printing. + */ +/* + * Authors: + * Ulf Erikson + * + * 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 +#include +#include + +#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 + +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( + "\n" + "Enhanced Metafile Print\n" + "org.inkscape.print.emf.win32\n" + "\n" + "TRUE\n" + "TRUE\n" + "\n" + "", 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 : diff --git a/src/extension/internal/emf-win32-print.h b/src/extension/internal/emf-win32-print.h index d1ac81939..305507824 100644 --- a/src/extension/internal/emf-win32-print.h +++ b/src/extension/internal/emf-win32-print.h @@ -1,107 +1,107 @@ -#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__ -#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__ - -/* - * Enhanced Metafile Printing. - * - * Author: - * Ulf Erikson - * - * 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 - -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 : +#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__ +#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_EMF_WIN32_H__ + +/* + * Enhanced Metafile Printing. + * + * Author: + * Ulf Erikson + * + * 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 + +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 : diff --git a/src/extension/internal/libwpg/WPGOLEStream.h b/src/extension/internal/libwpg/WPGOLEStream.h index 49562bfd6..af4a3d02f 100644 --- a/src/extension/internal/libwpg/WPGOLEStream.h +++ b/src/extension/internal/libwpg/WPGOLEStream.h @@ -1,28 +1,28 @@ /* POLE - Portable C++ library to access OLE Storage Copyright (C) 2002-2005 Ariya Hidayat - - 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 + + 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: - + // for Storage::result() - enum { Ok, OpenFailed, NotOLE, BadOLE, UnknownError }; - + enum { Ok, OpenFailed, NotOLE, BadOLE, UnknownError }; + /** * Constructs a storage with data. **/ @@ -84,19 +84,19 @@ class Stream friend class Storage; friend class StorageIO; -public: - - /** - * Creates a new stream. - */ - // name must be absolute, e.g "/PerfectOffice_MAIN" - Stream( Storage* storage, const std::string& name ); - - /** - * Destroys the stream. - */ +public: + + /** + * Creates a new stream. + */ + // name must be absolute, e.g "/PerfectOffice_MAIN" + Stream( Storage* storage, const std::string& name ); + + /** + * Destroys the stream. + */ ~Stream(); - + /** * Returns the stream size. **/ @@ -105,11 +105,11 @@ public: /** * Reads a block of data. **/ - unsigned long read( unsigned char* data, unsigned long maxlen ); - + unsigned long read( unsigned char* data, unsigned long maxlen ); + private: StreamIO* io; - + // no copy or assign Stream( const Stream& ); Stream& operator=( const Stream& ); diff --git a/src/extension/internal/libwpg/WPGXParser.cpp b/src/extension/internal/libwpg/WPGXParser.cpp index dcdc44c50..e25b53aab 100644 --- a/src/extension/internal/libwpg/WPGXParser.cpp +++ b/src/extension/internal/libwpg/WPGXParser.cpp @@ -1,103 +1,103 @@ -/* 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; -} +/* 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; +} diff --git a/src/extension/internal/libwpg/WPGXParser.h b/src/extension/internal/libwpg/WPGXParser.h index 71c78d2c0..d7fd4cb5a 100644 --- a/src/extension/internal/libwpg/WPGXParser.h +++ b/src/extension/internal/libwpg/WPGXParser.h @@ -1,60 +1,60 @@ -/* 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 - -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 m_colorPalette; -}; - -#endif // __WPGXPARSER_H__ +/* 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 + +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 m_colorPalette; +}; + +#endif // __WPGXPARSER_H__ diff --git a/src/extension/internal/libwpg/WPGraphics.cpp b/src/extension/internal/libwpg/WPGraphics.cpp index a7454d2a1..e120b802e 100644 --- a/src/extension/internal/libwpg/WPGraphics.cpp +++ b/src/extension/internal/libwpg/WPGraphics.cpp @@ -1,83 +1,83 @@ -/* 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; -} - +/* 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; +} + diff --git a/src/extension/internal/libwpg/WPGraphics.h b/src/extension/internal/libwpg/WPGraphics.h index 3226835ca..21abddd1b 100644 --- a/src/extension/internal/libwpg/WPGraphics.h +++ b/src/extension/internal/libwpg/WPGraphics.h @@ -1,46 +1,46 @@ -/* 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__ +/* 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__ diff --git a/src/extension/internal/wpg-input.cpp b/src/extension/internal/wpg-input.cpp index 28e947614..0326b150a 100644 --- a/src/extension/internal/wpg-input.cpp +++ b/src/extension/internal/wpg-input.cpp @@ -1,365 +1,365 @@ -/* - * 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 - * - * 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 - -#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("\n"); - printf("\n"); - -// printf("\n", LIBWPG_VERSION_STRING); - - printf("\n", 72*width, 72*height); - - m_gradientIndex = 1; -} - -void InkscapePainter::endDocument() -{ - printf("\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("\n"); - printf(" \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(" \n", - ofs, color.red, color.green, color.blue); - } - printf(" \n"); - - // not a simple horizontal gradient - if(angle != -90.0) - { - printf(" \n"); - printf(" \n"); - } - - printf("\n"); - } -} - -void InkscapePainter::setFillRule(FillRule rule) -{ - m_fillRule = rule; -} - -void InkscapePainter::startLayer(unsigned int id) -{ - printf("\n", id); -} - -void InkscapePainter::endLayer(unsigned int) -{ - printf("\n"); -} - -void InkscapePainter::drawRectangle(const WPGRect& rect, double rx, double ry) -{ - printf("\n"); -} - -void InkscapePainter::drawEllipse(const WPGPoint& center, double rx, double ry) -{ - 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("\n"); - } - else - { - printf("\n"); - } -} - -void InkscapePainter::drawPath(const WPGPath& path) -{ - 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( - "\n" - "" N_("WPG Input") "\n" - "org.inkscape.input.wpg\n" - "\n" - ".wpg\n" - "image/x-wpg\n" - "" N_("WordPerfect Graphics (*.wpg)") "\n" - "" N_("Vector graphics format used by Corel WordPerfect") "\n" - "\n" - "", 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 : +/* + * 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 + * + * 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 + +#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("\n"); + printf("\n"); + +// printf("\n", LIBWPG_VERSION_STRING); + + printf("\n", 72*width, 72*height); + + m_gradientIndex = 1; +} + +void InkscapePainter::endDocument() +{ + printf("\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("\n"); + printf(" \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(" \n", + ofs, color.red, color.green, color.blue); + } + printf(" \n"); + + // not a simple horizontal gradient + if(angle != -90.0) + { + printf(" \n"); + printf(" \n"); + } + + printf("\n"); + } +} + +void InkscapePainter::setFillRule(FillRule rule) +{ + m_fillRule = rule; +} + +void InkscapePainter::startLayer(unsigned int id) +{ + printf("\n", id); +} + +void InkscapePainter::endLayer(unsigned int) +{ + printf("\n"); +} + +void InkscapePainter::drawRectangle(const WPGRect& rect, double rx, double ry) +{ + printf("\n"); +} + +void InkscapePainter::drawEllipse(const WPGPoint& center, double rx, double ry) +{ + 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("\n"); + } + else + { + printf("\n"); + } +} + +void InkscapePainter::drawPath(const WPGPath& path) +{ + 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( + "\n" + "" N_("WPG Input") "\n" + "org.inkscape.input.wpg\n" + "\n" + ".wpg\n" + "image/x-wpg\n" + "" N_("WordPerfect Graphics (*.wpg)") "\n" + "" N_("Vector graphics format used by Corel WordPerfect") "\n" + "\n" + "", 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 : diff --git a/src/extension/paramenum.cpp b/src/extension/paramenum.cpp index 1e95a18f0..283ef8f5c 100644 --- a/src/extension/paramenum.cpp +++ b/src/extension/paramenum.cpp @@ -1,244 +1,244 @@ -/** \file - * extension parameter for enumerations. - * - * It uses a Gtk:ComboBoxText widget in the extension UI. - */ - -/* - * Author: - * Johan Engelen - * - * 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 -#include -#include -#include - -#include - -#include - -#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(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(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(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(hbox); -} - - -} /* namespace Extension */ -} /* namespace Inkscape */ - +/** \file + * extension parameter for enumerations. + * + * It uses a Gtk:ComboBoxText widget in the extension UI. + */ + +/* + * Author: + * Johan Engelen + * + * 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 +#include +#include +#include + +#include + +#include + +#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(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(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(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(hbox); +} + + +} /* namespace Extension */ +} /* namespace Inkscape */ + diff --git a/src/extension/paramenum.h b/src/extension/paramenum.h index f6fea4e05..4ad448549 100644 --- a/src/extension/paramenum.h +++ b/src/extension/paramenum.h @@ -1,67 +1,67 @@ -#ifndef __INK_EXTENSION_PARAMENUM_H__ -#define __INK_EXTENSION_PARAMENUM_H__ - -/** \file - * Enumeration parameter for extensions. - */ - -/* - * Author: - * Johan Engelen - * - * Copyright (C) 2006-2007 Johan Engelen - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include - -#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 : +#ifndef __INK_EXTENSION_PARAMENUM_H__ +#define __INK_EXTENSION_PARAMENUM_H__ + +/** \file + * Enumeration parameter for extensions. + */ + +/* + * Author: + * Johan Engelen + * + * Copyright (C) 2006-2007 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#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 : diff --git a/src/extension/paramnotebook.cpp b/src/extension/paramnotebook.cpp index cd8bddcaa..e8bd1e902 100644 --- a/src/extension/paramnotebook.cpp +++ b/src/extension/paramnotebook.cpp @@ -1,427 +1,427 @@ -/** \file - * Notebook and NotebookPage parameters for extensions. - */ - -/* - * Author: - * Johan Engelen - * - * Copyright (C) 2006 Author - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - - -#include -#include -#include -#include -#include - -#include - -#include - -#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(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(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(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(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(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(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(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(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(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(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 : +/** \file + * Notebook and NotebookPage parameters for extensions. + */ + +/* + * Author: + * Johan Engelen + * + * Copyright (C) 2006 Author + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include +#include +#include +#include +#include + +#include + +#include + +#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(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(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(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(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(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(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(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(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(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(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 : diff --git a/src/extension/paramnotebook.h b/src/extension/paramnotebook.h index a7811576e..f0ab15f57 100644 --- a/src/extension/paramnotebook.h +++ b/src/extension/paramnotebook.h @@ -1,68 +1,68 @@ -#ifndef __INK_EXTENSION_PARAMNOTEBOOK_H__ -#define __INK_EXTENSION_PARAMNOTEBOOK_H__ - -/** \file - * Notebook parameter for extensions. - */ - -/* - * Author: - * Johan Engelen - * - * Copyright (C) 2006 Author - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include - -#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 : +#ifndef __INK_EXTENSION_PARAMNOTEBOOK_H__ +#define __INK_EXTENSION_PARAMNOTEBOOK_H__ + +/** \file + * Notebook parameter for extensions. + */ + +/* + * Author: + * Johan Engelen + * + * Copyright (C) 2006 Author + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#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 : diff --git a/src/extension/paramradiobutton.cpp b/src/extension/paramradiobutton.cpp index 794abed94..3ca051f14 100644 --- a/src/extension/paramradiobutton.cpp +++ b/src/extension/paramradiobutton.cpp @@ -1,263 +1,263 @@ -/** \file - * extension parameter for radiobuttons. - * - * It uses a Gtk:ComboBoxText widget in the extension UI. - */ - -/* - * Author: - * Johan Engelen - * - * 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 -#include -#include -#include -#include - -#include - -#include - -#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(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(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(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(hbox); -} - - -} /* namespace Extension */ -} /* namespace Inkscape */ - +/** \file + * extension parameter for radiobuttons. + * + * It uses a Gtk:ComboBoxText widget in the extension UI. + */ + +/* + * Author: + * Johan Engelen + * + * 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 +#include +#include +#include +#include + +#include + +#include + +#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(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(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(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(hbox); +} + + +} /* namespace Extension */ +} /* namespace Inkscape */ + diff --git a/src/extension/paramradiobutton.h b/src/extension/paramradiobutton.h index 04c4e5846..8e1edf5b8 100644 --- a/src/extension/paramradiobutton.h +++ b/src/extension/paramradiobutton.h @@ -1,57 +1,57 @@ -#ifndef __INK_EXTENSION_PARAMRADIOBUTTON_H__ -#define __INK_EXTENSION_PARAMRADIOBUTTON_H__ - -/** \file - * Radiobutton parameter for extensions. - */ - -/* - * Author: - * Johan Engelen - * - * Copyright (C) 2006-2007 Johan Engelen - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include - -#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__ */ - +#ifndef __INK_EXTENSION_PARAMRADIOBUTTON_H__ +#define __INK_EXTENSION_PARAMRADIOBUTTON_H__ + +/** \file + * Radiobutton parameter for extensions. + */ + +/* + * Author: + * Johan Engelen + * + * Copyright (C) 2006-2007 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#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__ */ + diff --git a/src/pixmaps/cursor-gradient-add.xpm b/src/pixmaps/cursor-gradient-add.xpm index 1f33bc659..a019b9f7d 100644 --- a/src/pixmaps/cursor-gradient-add.xpm +++ b/src/pixmaps/cursor-gradient-add.xpm @@ -1,38 +1,38 @@ -/* XPM */ -static char * cursor_gradient_add_xpm[] = { -"32 32 3 1", -" c None", -". c #FFFFFF", -"+ c #000000", -" ... ", -" .+. ", -" .+. ", -"....+.... ", -".+++ +++. ", -"....+.... ", -" .+. ", -" .+. ..... ", -" ... .+++. ", -" .+.+. ", -" .+++. ", -" .+. ", -" .+. ", -" .+. ", -" .+. ", -" .+++. ", -" .+.+. ", -" .+++. ", -" ..... ", -" ... ", -" .+. ", -" .+. ", -" .+. ", -" .+. ", -" ......+...... ", -" .+++++++++++. ", -" ......+...... ", -" .+. ", -" .+. ", -" .+. ", -" .+. ", -" ... "}; +/* XPM */ +static char * cursor_gradient_add_xpm[] = { +"32 32 3 1", +" c None", +". c #FFFFFF", +"+ c #000000", +" ... ", +" .+. ", +" .+. ", +"....+.... ", +".+++ +++. ", +"....+.... ", +" .+. ", +" .+. ..... ", +" ... .+++. ", +" .+.+. ", +" .+++. ", +" .+. ", +" .+. ", +" .+. ", +" .+. ", +" .+++. ", +" .+.+. ", +" .+++. ", +" ..... ", +" ... ", +" .+. ", +" .+. ", +" .+. ", +" .+. ", +" ......+...... ", +" .+++++++++++. ", +" ......+...... ", +" .+. ", +" .+. ", +" .+. ", +" .+. ", +" ... "}; diff --git a/src/pixmaps/cursor-gradient-delete.xpm b/src/pixmaps/cursor-gradient-delete.xpm index 9832aa525..da70c9525 100644 --- a/src/pixmaps/cursor-gradient-delete.xpm +++ b/src/pixmaps/cursor-gradient-delete.xpm @@ -1,38 +1,38 @@ -/* XPM */ -static char * cursor_gradient_delete_xpm[] = { -"32 32 3 1", -" c None", -". c #FFFFFF", -"+ c #000000", -" ... ", -" .+. ", -" .+. ", -"....+.... ", -".+++ +++. ", -"....+.... ", -" .+. ", -" .+. ..... ", -" ... .+++. ", -" .+.+. ", -" .+++. ", -" .+. ", -" .+. ", -" .+. ", -" .+. ", -" .+++. ", -" .+.+. ", -" .+++. ", -" ..... ", -" ", -" ", -" ", -" ", -" ", -" ", -" ............. ", -" .+++++++++++. ", -" ............. ", -" ", -" ", -" ", -" "}; +/* XPM */ +static char * cursor_gradient_delete_xpm[] = { +"32 32 3 1", +" c None", +". c #FFFFFF", +"+ c #000000", +" ... ", +" .+. ", +" .+. ", +"....+.... ", +".+++ +++. ", +"....+.... ", +" .+. ", +" .+. ..... ", +" ... .+++. ", +" .+.+. ", +" .+++. ", +" .+. ", +" .+. ", +" .+. ", +" .+. ", +" .+++. ", +" .+.+. ", +" .+++. ", +" ..... ", +" ", +" ", +" ", +" ", +" ", +" ", +" ............. ", +" .+++++++++++. ", +" ............. ", +" ", +" ", +" ", +" "}; diff --git a/src/sp-filter-primitive.cpp b/src/sp-filter-primitive.cpp index 8a098de12..c0027e7c3 100644 --- a/src/sp-filter-primitive.cpp +++ b/src/sp-filter-primitive.cpp @@ -1,175 +1,175 @@ -#define __SP_FILTER_PRIMITIVE_CPP__ - -/** \file - * Superclass for all the filter primitives - * - */ -/* - * Authors: - * Kees Cook - * - * 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 : +#define __SP_FILTER_PRIMITIVE_CPP__ + +/** \file + * Superclass for all the filter primitives + * + */ +/* + * Authors: + * Kees Cook + * + * 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 : diff --git a/src/sp-filter-primitive.h b/src/sp-filter-primitive.h index 9fa628aa5..3a41f52de 100644 --- a/src/sp-filter-primitive.h +++ b/src/sp-filter-primitive.h @@ -1,26 +1,26 @@ -#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 +#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 diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp index c60ffb44f..729e13d4a 100644 --- a/src/sp-filter.cpp +++ b/src/sp-filter.cpp @@ -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, - Inkscape::XML::Node *child, - Inkscape::XML::Node *ref); +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; + sp_object_class->child_added = sp_filter_child_added; sp_object_class->remove_child = sp_filter_remove_child; } diff --git a/src/ui/widget/entry.cpp b/src/ui/widget/entry.cpp index 6159b4fe5..7b19ac861 100644 --- a/src/ui/widget/entry.cpp +++ b/src/ui/widget/entry.cpp @@ -1,35 +1,35 @@ -/** \file - * - * \brief Helperclass for Gtk::Entry widgets - * - * Authors: - * Johan Engelen - * - * Copyright (C) 2006 Authors - * - * Released under GNU GPL. Read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include -#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 - +/** \file + * + * \brief Helperclass for Gtk::Entry widgets + * + * Authors: + * Johan Engelen + * + * Copyright (C) 2006 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include +#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 + diff --git a/src/ui/widget/entry.h b/src/ui/widget/entry.h index 06cb19bef..bb6c1321a 100644 --- a/src/ui/widget/entry.h +++ b/src/ui/widget/entry.h @@ -1,44 +1,44 @@ -/** \file - * - * \brief Helperclass for Gtk::Entry widgets - * - * Authors: - * Johan Engelen - * - * 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 -#include -#include -#include -#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 +/** \file + * + * \brief Helperclass for Gtk::Entry widgets + * + * Authors: + * Johan Engelen + * + * 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 +#include +#include +#include +#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 diff --git a/src/util/fixed_point.h b/src/util/fixed_point.h index bea891742..6afec5e3c 100644 --- a/src/util/fixed_point.h +++ b/src/util/fixed_point.h @@ -1,333 +1,333 @@ -/* - * Inkscape::Util::FixedPoint - fixed point type - * - * Authors: - * Jasper van de Gronde - * - * 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 -#include -#include - -namespace Inkscape { - -namespace Util { - -template -class FixedPoint { -public: - FixedPoint() {} - FixedPoint(const FixedPoint& value) : v(value.v) {} - FixedPoint(char value) : v(static_cast(value)<(value)<(value)<(value)<(value)<(value)<(floor(value*(1<>half_size, bh = val.v>>half_size; - v = static_cast(al*bl)>>precision; - if ( half_size >= precision ) { - v += ((al*bh)+(ah*bl)+((ah*bh)<>(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(*this)*val; } - double operator*(double val) const { return static_cast(*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 FixedPoint operator *(char a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned char a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(short a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned short a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(int a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned int a, FixedPoint b) { return b*=a; } - -template float operator *(float a, FixedPoint b) { return b*a; } -template double operator *(double a, FixedPoint 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 - * - * 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 -#include -#include - -namespace Inkscape { - -namespace Util { - -template -class FixedPoint { -public: - FixedPoint() {} - FixedPoint(const FixedPoint& value) : v(value.v) {} - FixedPoint(char value) : v(static_cast(value)<(value)<(value)<(value)<(value)<(value)<(floor(value*(1<>half_size, bh = val.v>>half_size; - v = static_cast(al*bl)>>precision; - if ( half_size >= precision ) { - v += ((al*bh)+(ah*bl)+((ah*bh)<>(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(*this)*val; } - double operator*(double val) const { return static_cast(*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 FixedPoint operator *(char a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned char a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(short a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned short a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(int a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned int a, FixedPoint b) { return b*=a; } - -template float operator *(float a, FixedPoint b) { return b*a; } -template double operator *(double a, FixedPoint 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 - * - * 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 -#include -#include - -namespace Inkscape { - -namespace Util { - -template -class FixedPoint { -public: - FixedPoint() {} - FixedPoint(const FixedPoint& value) : v(value.v) {} - FixedPoint(char value) : v(static_cast(value)<(value)<(value)<(value)<(value)<(value)<(floor(value*(1<>half_size, bh = val.v>>half_size; - v = static_cast(al*bl)>>precision; - if ( half_size >= precision ) { - v += ((al*bh)+(ah*bl)+((ah*bh)<>(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(*this)*val; } - double operator*(double val) const { return static_cast(*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 FixedPoint operator *(char a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned char a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(short a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned short a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(int a, FixedPoint b) { return b*=a; } -template FixedPoint operator *(unsigned int a, FixedPoint b) { return b*=a; } - -template float operator *(float a, FixedPoint b) { return b*a; } -template double operator *(double a, FixedPoint 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 + * + * 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 +#include +#include + +namespace Inkscape { + +namespace Util { + +template +class FixedPoint { +public: + FixedPoint() {} + FixedPoint(const FixedPoint& value) : v(value.v) {} + FixedPoint(char value) : v(static_cast(value)<(value)<(value)<(value)<(value)<(value)<(floor(value*(1<>half_size, bh = val.v>>half_size; + v = static_cast(al*bl)>>precision; + if ( half_size >= precision ) { + v += ((al*bh)+(ah*bl)+((ah*bh)<>(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(*this)*val; } + double operator*(double val) const { return static_cast(*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 FixedPoint operator *(char a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned char a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(short a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned short a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(int a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned int a, FixedPoint b) { return b*=a; } + +template float operator *(float a, FixedPoint b) { return b*a; } +template double operator *(double a, FixedPoint 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 + * + * 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 +#include +#include + +namespace Inkscape { + +namespace Util { + +template +class FixedPoint { +public: + FixedPoint() {} + FixedPoint(const FixedPoint& value) : v(value.v) {} + FixedPoint(char value) : v(static_cast(value)<(value)<(value)<(value)<(value)<(value)<(floor(value*(1<>half_size, bh = val.v>>half_size; + v = static_cast(al*bl)>>precision; + if ( half_size >= precision ) { + v += ((al*bh)+(ah*bl)+((ah*bh)<>(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(*this)*val; } + double operator*(double val) const { return static_cast(*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 FixedPoint operator *(char a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned char a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(short a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned short a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(int a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned int a, FixedPoint b) { return b*=a; } + +template float operator *(float a, FixedPoint b) { return b*a; } +template double operator *(double a, FixedPoint 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 + * + * 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 +#include +#include + +namespace Inkscape { + +namespace Util { + +template +class FixedPoint { +public: + FixedPoint() {} + FixedPoint(const FixedPoint& value) : v(value.v) {} + FixedPoint(char value) : v(static_cast(value)<(value)<(value)<(value)<(value)<(value)<(floor(value*(1<>half_size, bh = val.v>>half_size; + v = static_cast(al*bl)>>precision; + if ( half_size >= precision ) { + v += ((al*bh)+(ah*bl)+((ah*bh)<>(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(*this)*val; } + double operator*(double val) const { return static_cast(*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 FixedPoint operator *(char a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned char a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(short a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned short a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(int a, FixedPoint b) { return b*=a; } +template FixedPoint operator *(unsigned int a, FixedPoint b) { return b*=a; } + +template float operator *(float a, FixedPoint b) { return b*a; } +template double operator *(double a, FixedPoint 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 :