diff options
| author | MenTaLguY <mental@rydia.net> | 2006-01-16 02:36:01 +0000 |
|---|---|---|
| committer | mental <mental@users.sourceforge.net> | 2006-01-16 02:36:01 +0000 |
| commit | 179fa413b047bede6e32109e2ce82437c5fb8d34 (patch) | |
| tree | a5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/helper | |
| download | inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip | |
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/helper')
| -rw-r--r-- | src/helper/.cvsignore | 9 | ||||
| -rw-r--r-- | src/helper/HACKING | 35 | ||||
| -rw-r--r-- | src/helper/Makefile_insert | 51 | ||||
| -rw-r--r-- | src/helper/action.cpp | 228 | ||||
| -rw-r--r-- | src/helper/action.h | 91 | ||||
| -rw-r--r-- | src/helper/gnome-utils.cpp | 108 | ||||
| -rw-r--r-- | src/helper/gnome-utils.h | 36 | ||||
| -rw-r--r-- | src/helper/helper-forward.h | 35 | ||||
| -rw-r--r-- | src/helper/makefile.in | 17 | ||||
| -rw-r--r-- | src/helper/png-write.cpp | 205 | ||||
| -rw-r--r-- | src/helper/png-write.h | 23 | ||||
| -rw-r--r-- | src/helper/sp-marshal.cpp.mingw | 520 | ||||
| -rw-r--r-- | src/helper/sp-marshal.h.mingw | 125 | ||||
| -rw-r--r-- | src/helper/sp-marshal.list | 16 | ||||
| -rw-r--r-- | src/helper/stlport.h | 26 | ||||
| -rw-r--r-- | src/helper/stock-items.cpp | 267 | ||||
| -rw-r--r-- | src/helper/stock-items.h | 20 | ||||
| -rw-r--r-- | src/helper/unit-menu.cpp | 372 | ||||
| -rw-r--r-- | src/helper/unit-menu.h | 59 | ||||
| -rw-r--r-- | src/helper/units-test.cpp | 115 | ||||
| -rw-r--r-- | src/helper/units.cpp | 260 | ||||
| -rw-r--r-- | src/helper/units.h | 146 | ||||
| -rw-r--r-- | src/helper/window.cpp | 47 | ||||
| -rw-r--r-- | src/helper/window.h | 28 |
24 files changed, 2839 insertions, 0 deletions
diff --git a/src/helper/.cvsignore b/src/helper/.cvsignore new file mode 100644 index 000000000..4a5454d13 --- /dev/null +++ b/src/helper/.cvsignore @@ -0,0 +1,9 @@ +Makefile +Makefile.in +.deps +.libs +sp-marshal.cpp +sp-marshal.h +makefile +.dirstamp +*-test diff --git a/src/helper/HACKING b/src/helper/HACKING new file mode 100644 index 000000000..2e3ddcbcd --- /dev/null +++ b/src/helper/HACKING @@ -0,0 +1,35 @@ +* +* Unsystematized and temporary helper things +* + +1. libspchelp + +Here you find: + +Useful add-ons to gnome-canvas, such as: + gnome_canvas_item_i2p_affine + +Canvas items useful for editing: +Ctrl - a small rectangle, which do no scale when parent is scaled +CtrlRect - 'rubberband' box +CtrlLine - simple straight line +Probably some of these will be rendered without libart at all - we do not +need antialias for rubberband. + +Yet to implement: +Guide - simple guideline. +FastSVP, FastVpath - not decided yet, but for node editing it seems to be +useful to have special rendering mode - fast stroking of single pixel wide +lines without antialias. + +2. libgt1 + +This is complete placeholder. All type1 parsing code is already included +in gnome-print development version and as soon as it will be more widely +available, I remove this. + +These programs are written mainly by Adobe and Raph Levien, probably others. +I modified gt1-parset1.c to force it to display most of iso-8859-1 characters. + +Lauris Kaplinski +<lauris@ariman.ee> diff --git a/src/helper/Makefile_insert b/src/helper/Makefile_insert new file mode 100644 index 000000000..9f061c090 --- /dev/null +++ b/src/helper/Makefile_insert @@ -0,0 +1,51 @@ +## Makefile.am fragment sourced by src/Makefile.am. + +# +# Miscellaneous unsystematized and temporary helper utilities +# +# libspchelp - canvas utilities, specific canvas items +# + +helper/all: helper/libspchelp.a + +helper/clean: + rm -f helper/libspchelp.a $(helper_libspchelp_a_OBJECTS) + +helper/unit-menu.$(OBJEXT): helper/sp-marshal.h + +helper_libspchelp_a_SOURCES = \ + helper/action.cpp \ + helper/action.h \ + helper/gnome-utils.cpp \ + helper/gnome-utils.h \ + helper/helper-forward.h \ + helper/png-write.cpp \ + helper/png-write.h \ + helper/sp-marshal.cpp \ + helper/sp-marshal.h \ + helper/stlport.h \ + helper/unit-menu.cpp \ + helper/unit-menu.h \ + helper/units.cpp \ + helper/units.h \ + helper/window.cpp \ + helper/window.h \ + helper/stock-items.cpp \ + helper/stock-items.h + + +# TODO: Check that the generated sp-marshal.h is the same as before. +helper/sp-marshal.h: helper/sp-marshal.list + glib-genmarshal --prefix=sp_marshal --header $(srcdir)/helper/sp-marshal.list > helper/tmp.$$$$ \ + && mv helper/tmp.$$$$ helper/sp-marshal.h + +helper/sp-marshal.cpp: helper/sp-marshal.list helper/sp-marshal.h + ( echo '#include "helper/sp-marshal.h"' && \ + glib-genmarshal --prefix=sp_marshal --body $(srcdir)/helper/sp-marshal.list ) \ + > helper/tmp.$$$$ \ + && mv helper/tmp.$$$$ helper/sp-marshal.cpp + +helper/sp-marshal.cpp helper/sp-marshal.h: Makefile + +helper_units_test_SOURCES = helper/units-test.cpp +helper_units_test_LDADD = helper/libspchelp.a -lglib-2.0 diff --git a/src/helper/action.cpp b/src/helper/action.cpp new file mode 100644 index 000000000..9584c5dae --- /dev/null +++ b/src/helper/action.cpp @@ -0,0 +1,228 @@ +#define __SP_ACTION_C__ + +/** \file + * SPAction implementation + * + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * Copyright (C) 2003 Lauris Kaplinski + * + * This code is in public domain + */ + +#include <string.h> + + +#include "helper/action.h" + +static void sp_action_class_init (SPActionClass *klass); +static void sp_action_init (SPAction *action); +static void sp_action_finalize (NRObject *object); + +static NRActiveObjectClass *parent_class; + +/** + * Register SPAction class and return its type. + */ +NRType +sp_action_get_type (void) +{ + static unsigned int type = 0; + if (!type) { + type = nr_object_register_type (NR_TYPE_ACTIVE_OBJECT, + "SPAction", + sizeof (SPActionClass), + sizeof (SPAction), + (void (*) (NRObjectClass *)) sp_action_class_init, + (void (*) (NRObject *)) sp_action_init); + } + return type; +} + +/** + * SPAction vtable initialization. + */ +static void +sp_action_class_init (SPActionClass *klass) +{ + NRObjectClass * object_class; + + object_class = (NRObjectClass *) klass; + + parent_class = (NRActiveObjectClass *) (((NRObjectClass *) klass)->parent); + + object_class->finalize = sp_action_finalize; + object_class->cpp_ctor = NRObject::invoke_ctor<SPAction>; +} + +/** + * Callback for SPAction object initialization. + */ +static void +sp_action_init (SPAction *action) +{ + action->sensitive = 0; + action->active = 0; + action->view = NULL; + action->id = action->name = action->tip = NULL; + action->image = NULL; +} + +/** + * Called before SPAction object destruction. + */ +static void +sp_action_finalize (NRObject *object) +{ + SPAction *action; + + action = (SPAction *) object; + + if (action->image) free (action->image); + if (action->tip) free (action->tip); + if (action->name) free (action->name); + if (action->id) free (action->id); + + ((NRObjectClass *) (parent_class))->finalize (object); +} + +/** + * Create new SPAction object and set its properties. + */ +SPAction * +sp_action_new(Inkscape::UI::View::View *view, + const gchar *id, + const gchar *name, + const gchar *tip, + const gchar *image, + Inkscape::Verb * verb) +{ + SPAction *action = (SPAction *)nr_object_new(SP_TYPE_ACTION); + + action->view = view; + action->sensitive = TRUE; + if (id) action->id = strdup (id); + if (name) action->name = strdup (name); + if (tip) action->tip = strdup (tip); + if (image) action->image = strdup (image); + action->verb = verb; + + return action; +} + +/** + \return None + \brief Executes an action + \param action The action to be executed + \param data Data that is passed into the action. This depends + on the situation that the action is used in. + + This function implements the 'action' in SPActions. It first validates + its parameters, making sure it got an action passed in. Then it + turns that action into its parent class of NRActiveObject. The + NRActiveObject allows for listeners to be attached to it. This + function goes through those listeners and calls them with the + vector that was attached to the listener. +*/ +void +sp_action_perform (SPAction *action, void * data) +{ + NRActiveObject *aobject; + + nr_return_if_fail (action != NULL); + nr_return_if_fail (SP_IS_ACTION (action)); + + aobject = NR_ACTIVE_OBJECT(action); + if (aobject->callbacks) { + unsigned int i; + for (i = 0; i < aobject->callbacks->length; i++) { + NRObjectListener *listener; + SPActionEventVector *avector; + + listener = &aobject->callbacks->listeners[i]; + avector = (SPActionEventVector *) listener->vector; + + if ((listener->size >= sizeof (SPActionEventVector)) && avector != NULL && avector->perform != NULL) { + avector->perform (action, listener->data, data); + } + } + } +} + +/** + * Change activation in all actions that can be taken with the action. + */ +void +sp_action_set_active (SPAction *action, unsigned int active) +{ + nr_return_if_fail (action != NULL); + nr_return_if_fail (SP_IS_ACTION (action)); + + if (active != action->active) { + NRActiveObject *aobject; + action->active = active; + aobject = (NRActiveObject *) action; + if (aobject->callbacks) { + unsigned int i; + for (i = 0; i < aobject->callbacks->length; i++) { + NRObjectListener *listener; + SPActionEventVector *avector; + listener = aobject->callbacks->listeners + i; + avector = (SPActionEventVector *) listener->vector; + if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_active) { + avector->set_active (action, active, listener->data); + } + } + } + } +} + +/** + * Change sensitivity in all actions that can be taken with the action. + */ +void +sp_action_set_sensitive (SPAction *action, unsigned int sensitive) +{ + nr_return_if_fail (action != NULL); + nr_return_if_fail (SP_IS_ACTION (action)); + + if (sensitive != action->sensitive) { + NRActiveObject *aobject; + action->sensitive = sensitive; + aobject = (NRActiveObject *) action; + if (aobject->callbacks) { + unsigned int i; + for (i = 0; i < aobject->callbacks->length; i++) { + NRObjectListener *listener; + SPActionEventVector *avector; + listener = aobject->callbacks->listeners + i; + avector = (SPActionEventVector *) listener->vector; + if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_sensitive) { + avector->set_sensitive (action, sensitive, listener->data); + } + } + } + } +} + +/** + * Return View associated with the action. + */ +Inkscape::UI::View::View * +sp_action_get_view (SPAction *action) +{ + g_return_val_if_fail (SP_IS_ACTION (action), NULL); + return action->view; +} + +/* + 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/helper/action.h b/src/helper/action.h new file mode 100644 index 000000000..1e3646439 --- /dev/null +++ b/src/helper/action.h @@ -0,0 +1,91 @@ +#ifndef __SP_ACTION_H__ +#define __SP_ACTION_H__ + +/** \file + * Inkscape UI action implementation + */ + +/* + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * Copyright (C) 2003 Lauris Kaplinski + * + * This code is in public domain + */ + +/** A macro to get the GType for actions */ +#define SP_TYPE_ACTION (sp_action_get_type()) +/** A macro to cast and check the cast of changing an object to an action */ +#define SP_ACTION(o) (NR_CHECK_INSTANCE_CAST((o), SP_TYPE_ACTION, SPAction)) +/** A macro to check whether or not something is an action */ +#define SP_IS_ACTION(o) (NR_CHECK_INSTANCE_TYPE((o), SP_TYPE_ACTION)) + +#include "helper/helper-forward.h" +#include "libnr/nr-object.h" +#include "forward.h" + +//class Inkscape::UI::View::View; + +namespace Inkscape { +class Verb; +} + + +/** This is a structure that is used to hold all the possible + actions that can be taken with an action. These are the + function pointers available. */ +struct SPActionEventVector { + NRObjectEventVector object_vector; /**< Parent class */ + void (* perform)(SPAction *action, void *ldata, void *pdata); /**< Actually do the action of the event. Called by sp_perform_action */ + void (* set_active)(SPAction *action, unsigned active, void *data); /**< Callback for activation change */ + void (* set_sensitive)(SPAction *action, unsigned sensitive, void *data); /**< Callback for a change in sensitivity */ + void (* set_shortcut)(SPAction *action, unsigned shortcut, void *data); /**< Callback for setting the shortcut for this function */ +}; + +/** All the data that is required to be an action. This + structure identifies the action and has the data to + create menus and toolbars for the action */ +struct SPAction : public NRActiveObject { + unsigned sensitive : 1; /**< Value to track whether the action is sensitive */ + unsigned active : 1; /**< Value to track whether the action is active */ + Inkscape::UI::View::View *view; /**< The View to which this action is attached */ + gchar *id; /**< The identifier for the action */ + gchar *name; /**< Full text name of the action */ + gchar *tip; /**< A tooltip to describe the action */ + gchar *image; /**< An image to visually identify the action */ + Inkscape::Verb *verb; /**< The verb that produced this action */ +}; + +/** The action class is the same as its parent. */ +struct SPActionClass { + NRActiveObjectClass parent_class; /**< Parent Class */ +}; + +NRType sp_action_get_type(); + +SPAction *sp_action_new(Inkscape::UI::View::View *view, + gchar const *id, + gchar const *name, + gchar const *tip, + gchar const *image, + Inkscape::Verb *verb); + +void sp_action_perform(SPAction *action, void *data); +void sp_action_set_active(SPAction *action, unsigned active); +void sp_action_set_sensitive(SPAction *action, unsigned sensitive); +Inkscape::UI::View::View *sp_action_get_view(SPAction *action); + +#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 : diff --git a/src/helper/gnome-utils.cpp b/src/helper/gnome-utils.cpp new file mode 100644 index 000000000..aa70dd1a2 --- /dev/null +++ b/src/helper/gnome-utils.cpp @@ -0,0 +1,108 @@ +#define __GNOME_UTILS_C__ + +/* + * Helpers + * + * Author: + * Mitsuru Oka + * Lauris Kaplinski <lauris@kaplinski.com> + * + * Copyright (C) 2002 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <string.h> +#include <ctype.h> +#include <glib.h> + +/** + * gnome_uri_list_extract_uris: + * @uri_list: an uri-list in the standard format. + * + * Returns a GList containing strings allocated with g_malloc + * that have been splitted from @uri-list. + */ +GList* +gnome_uri_list_extract_uris (const gchar* uri_list) +{ + const gchar *p, *q; + gchar *retval; + GList *result = NULL; + + g_return_val_if_fail (uri_list != NULL, NULL); + + p = uri_list; + + /* We don't actually try to validate the URI according to RFC + * 2396, or even check for allowed characters - we just ignore + * comments and trim whitespace off the ends. We also + * allow LF delimination as well as the specified CRLF. + */ + while (p) { + if (*p != '#') { + while (isspace(*p)) + p++; + + q = p; + while (*q && (*q != '\n') && (*q != '\r')) + q++; + + if (q > p) { + q--; + while (q > p && isspace(*q)) + q--; + + retval = (gchar*)g_malloc (q - p + 2); + strncpy (retval, p, q - p + 1); + retval[q - p + 1] = '\0'; + + result = g_list_prepend (result, retval); + } + } + p = strchr (p, '\n'); + if (p) + p++; + } + + return g_list_reverse (result); +} + +/** + * gnome_uri_list_extract_filenames: + * @uri_list: an uri-list in the standard format + * + * Returns a GList containing strings allocated with g_malloc + * that contain the filenames in the uri-list. + * + * Note that unlike gnome_uri_list_extract_uris() function, this + * will discard any non-file uri from the result value. + */ +GList* +gnome_uri_list_extract_filenames (const gchar* uri_list) +{ + GList *tmp_list, *node, *result; + + g_return_val_if_fail (uri_list != NULL, NULL); + + result = gnome_uri_list_extract_uris (uri_list); + + tmp_list = result; + while (tmp_list) { + gchar *s = (gchar*)tmp_list->data; + + node = tmp_list; + tmp_list = tmp_list->next; + + if (!strncmp (s, "file:", 5)) { + node->data = g_filename_from_uri (s, NULL, NULL); + /* not sure if this fallback is useful at all */ + if (!node->data) node->data = g_strdup (s+5); + } else { + result = g_list_remove_link(result, node); + g_list_free_1 (node); + } + g_free (s); + } + return result; +} diff --git a/src/helper/gnome-utils.h b/src/helper/gnome-utils.h new file mode 100644 index 000000000..0a28c95a9 --- /dev/null +++ b/src/helper/gnome-utils.h @@ -0,0 +1,36 @@ +/* + * GNOME Utils - Migration helper + * + * Author: + * GNOME Developer + * Mitsuru Oka <oka326@parkcity.ne.jp> + * Lauris Kaplinski <lauris@ximian.com> + * + * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc. + * + * Released under GNU GPL + */ + + +#ifndef __GNOME_UTILS_H__ +#define __GNOME_UTILS_H__ + +#include <glib/gtypes.h> +#include <glib/glist.h> + +GList *gnome_uri_list_extract_uris(gchar const *uri_list); + +GList *gnome_uri_list_extract_filenames(gchar const *uri_list); + +#endif /* __GNOME_UTILS_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/helper/helper-forward.h b/src/helper/helper-forward.h new file mode 100644 index 000000000..7cb0cddea --- /dev/null +++ b/src/helper/helper-forward.h @@ -0,0 +1,35 @@ +#ifndef __HELPER_FORWARD_H__ +#define __HELPER_FORWARD_H__ + +/* + * Forward declarations + * + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * Copyright (C) 2002 Lauris Kaplinski + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + +struct SPAction; +struct SPActionClass; +struct SPActionEventVector; + +struct SPUnit; +struct SPUnitSelector; +struct SPUnitSelectorClass; + +#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 : diff --git a/src/helper/makefile.in b/src/helper/makefile.in new file mode 100644 index 000000000..edb3951aa --- /dev/null +++ b/src/helper/makefile.in @@ -0,0 +1,17 @@ +# Convenience stub makefile to call the real Makefile. + +@SET_MAKE@ + +# Explicit so that it's the default rule. +all: + cd .. && $(MAKE) helper/all + +clean %.a %.o: + cd .. && $(MAKE) helper/$@ + +.PHONY: all clean + +OBJEXT = @OBJEXT@ + +.SUFFIXES: +.SUFFIXES: .a .$(OBJEXT) diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp new file mode 100644 index 000000000..21eca1efa --- /dev/null +++ b/src/helper/png-write.cpp @@ -0,0 +1,205 @@ +#define __SP_PNG_WRITE_C__ + +/* + * PNG file format utilities + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Whoever wrote this example in libpng documentation + * + * Copyright (C) 1999-2002 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glib/gmessages.h> +#include <png.h> +#include "png-write.h" +#include "io/sys.h" + +/* This is an example of how to use libpng to read and write PNG files. + * The file libpng.txt is much more verbose then this. If you have not + * read it, do so first. This was designed to be a starting point of an + * implementation. This is not officially part of libpng, and therefore + * does not require a copyright notice. + * + * This file does not currently compile, because it is missing certain + * parts, like allocating memory to hold an image. You will have to + * supply these parts to get it to compile. For an example of a minimal + * working PNG reader/writer, see pngtest.c, included in this distribution. + */ + +/* write a png file */ + +typedef struct SPPNGBD { + const guchar *px; + int rowstride; +} SPPNGBD; + +static int +sp_png_get_block_stripe (const guchar **rows, int row, int num_rows, void *data) +{ + SPPNGBD *bd = (SPPNGBD *) data; + + for (int r = 0; r < num_rows; r++) { + rows[r] = bd->px + (row + r) * bd->rowstride; + } + + return num_rows; +} + +int +sp_png_write_rgba (const gchar *filename, const guchar *px, int width, int height, int rowstride) +{ + SPPNGBD bd; + + bd.px = px; + bd.rowstride = rowstride; + + return sp_png_write_rgba_striped (filename, width, height, sp_png_get_block_stripe, &bd); +} + +int +sp_png_write_rgba_striped (const gchar *filename, int width, int height, + int (* get_rows) (const guchar **rows, int row, int num_rows, void *data), + void *data) +{ + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_color_8 sig_bit; + png_text text_ptr[3]; + png_uint_32 r; + + g_return_val_if_fail (filename != NULL, FALSE); + + /* open the file */ + + Inkscape::IO::dump_fopen_call(filename, "M"); + fp = Inkscape::IO::fopen_utf8name(filename, "wb"); + g_return_val_if_fail (fp != NULL, FALSE); + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (png_ptr == NULL) { + fclose(fp); + return FALSE; + } + + /* Allocate/initialize the image information data. REQUIRED */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + fclose(fp); + png_destroy_write_struct(&png_ptr, NULL); + return FALSE; + } + + /* Set error handling. REQUIRED if you aren't supplying your own + * error hadnling functions in the png_create_write_struct() call. + */ + if (setjmp(png_ptr->jmpbuf)) { + /* If we get here, we had a problem reading the file */ + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + return FALSE; + } + + /* set up the output control if you are using standard C streams */ + png_init_io(png_ptr, fp); + + /* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + */ + png_set_IHDR(png_ptr, info_ptr, + width, + height, + 8, /* bit_depth */ + PNG_COLOR_TYPE_RGB_ALPHA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + + /* otherwise, if we are dealing with a color image then */ + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + /* if the image has an alpha channel then */ + sig_bit.alpha = 8; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + + /* Made by Inkscape comment */ + text_ptr[0].key = "Software"; + text_ptr[0].text = "www.inkscape.org"; + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + png_set_text(png_ptr, info_ptr, text_ptr, 1); + + /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */ + /* note that if sRGB is present the cHRM chunk must be ignored + * on read and must be written in accordance with the sRGB profile */ + + /* Write the file header information. REQUIRED */ + png_write_info(png_ptr, info_ptr); + + /* Once we write out the header, the compression type on the text + * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or + * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again + * at the end. + */ + + /* set up the transformations you want. Note that these are + * all optional. Only call them if you want them. + */ + + /* --- CUT --- */ + + /* The easiest way to write the image (you may have a different memory + * layout, however, so choose what fits your needs best). You need to + * use the first method if you aren't handling interlacing yourself. + */ + + r = 0; + while (r < static_cast< png_uint_32 > (height) ) { + png_bytep row_pointers[64]; + int h, n; + + h = MIN (height - r, 64); + n = get_rows ((const unsigned char **) row_pointers, r, h, data); + if (!n) break; + png_write_rows (png_ptr, row_pointers, n); + r += n; + } + + /* You can write optional chunks like tEXt, zTXt, and tIME at the end + * as well. + */ + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + /* if you allocated any text comments, free them here */ + + /* clean up after the write, and free any memory allocated */ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* close the file */ + fclose(fp); + + /* that's it */ + return TRUE; +} + diff --git a/src/helper/png-write.h b/src/helper/png-write.h new file mode 100644 index 000000000..2d2c16544 --- /dev/null +++ b/src/helper/png-write.h @@ -0,0 +1,23 @@ +#ifndef __SP_PNG_WRITE_H__ +#define __SP_PNG_WRITE_H__ + +/* + * PNG file format utilities + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * Copyright (C) 1999-2002 Lauris Kaplinski + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <glib/gtypes.h> + +int sp_png_write_rgba(gchar const *filename, guchar const *px, int width, int height, int rowstride); + +int sp_png_write_rgba_striped(gchar const *filename, int width, int height, + int (* get_rows) (guchar const **rows, int row, int num_rows, void *data), + void *data); + +#endif diff --git a/src/helper/sp-marshal.cpp.mingw b/src/helper/sp-marshal.cpp.mingw new file mode 100644 index 000000000..8a7e7648c --- /dev/null +++ b/src/helper/sp-marshal.cpp.mingw @@ -0,0 +1,520 @@ +#include "helper/sp-marshal.h" + +#include <glib-object.h> + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_int +#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:NONE (sp-marshal.list:2) */ + +/* NONE:UINT (sp-marshal.list:3) */ + +/* NONE:POINTER (sp-marshal.list:4) */ + +/* NONE:POINTER,BOOLEAN (sp-marshal.list:5) */ +void +sp_marshal_VOID__POINTER_BOOLEAN (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__POINTER_BOOLEAN) (gpointer data1, + gpointer arg_1, + gboolean arg_2, + gpointer data2); + register GMarshalFunc_VOID__POINTER_BOOLEAN callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__POINTER_BOOLEAN) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_boolean (param_values + 2), + data2); +} + +/* NONE:POINTER,UINT (sp-marshal.list:6) */ +void +sp_marshal_VOID__POINTER_UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__POINTER_UINT) (gpointer data1, + gpointer arg_1, + guint arg_2, + gpointer data2); + register GMarshalFunc_VOID__POINTER_UINT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__POINTER_UINT) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_uint (param_values + 2), + data2); +} + +/* NONE:POINTER,DOUBLE (sp-marshal.list:7) */ +void +sp_marshal_VOID__POINTER_DOUBLE (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__POINTER_DOUBLE) (gpointer data1, + gpointer arg_1, + gdouble arg_2, + gpointer data2); + register GMarshalFunc_VOID__POINTER_DOUBLE callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__POINTER_DOUBLE) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_double (param_values + 2), + data2); +} + +/* NONE:DOUBLE,DOUBLE (sp-marshal.list:8) */ +void +sp_marshal_VOID__DOUBLE_DOUBLE (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__DOUBLE_DOUBLE) (gpointer data1, + gdouble arg_1, + gdouble arg_2, + gpointer data2); + register GMarshalFunc_VOID__DOUBLE_DOUBLE callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__DOUBLE_DOUBLE) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_double (param_values + 1), + g_marshal_value_peek_double (param_values + 2), + data2); +} + +/* NONE:STRING,BOOL (sp-marshal.list:9) */ +void +sp_marshal_VOID__STRING_BOOLEAN (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_BOOLEAN) (gpointer data1, + gpointer arg_1, + gboolean arg_2, + gpointer data2); + register GMarshalFunc_VOID__STRING_BOOLEAN callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_BOOLEAN) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_boolean (param_values + 2), + data2); +} + +/* BOOLEAN:NONE (sp-marshal.list:10) */ +void +sp_marshal_BOOLEAN__VOID (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (gpointer data1, + gpointer data2); + register GMarshalFunc_BOOLEAN__VOID callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 1); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:UINT (sp-marshal.list:11) */ +void +sp_marshal_BOOLEAN__UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__UINT) (gpointer data1, + guint arg_1, + gpointer data2); + register GMarshalFunc_BOOLEAN__UINT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__UINT) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_uint (param_values + 1), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:POINTER (sp-marshal.list:12) */ +void +sp_marshal_BOOLEAN__POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER) (gpointer data1, + gpointer arg_1, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:POINTER,UINT (sp-marshal.list:13) */ +void +sp_marshal_BOOLEAN__POINTER_UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_UINT) (gpointer data1, + gpointer arg_1, + guint arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER_UINT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER_UINT) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_uint (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:POINTER,POINTER (sp-marshal.list:14) */ +void +sp_marshal_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* INT:POINTER,POINTER (sp-marshal.list:15) */ +void +sp_marshal_INT__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gint (*GMarshalFunc_INT__POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_INT__POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gint v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_INT__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_int (return_value, v_return); +} + +/* DOUBLE:POINTER,UINT (sp-marshal.list:16) */ +void +sp_marshal_DOUBLE__POINTER_UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gdouble (*GMarshalFunc_DOUBLE__POINTER_UINT) (gpointer data1, + gpointer arg_1, + guint arg_2, + gpointer data2); + register GMarshalFunc_DOUBLE__POINTER_UINT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gdouble v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_DOUBLE__POINTER_UINT) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_uint (param_values + 2), + data2); + + g_value_set_double (return_value, v_return); +} + diff --git a/src/helper/sp-marshal.h.mingw b/src/helper/sp-marshal.h.mingw new file mode 100644 index 000000000..9b573c523 --- /dev/null +++ b/src/helper/sp-marshal.h.mingw @@ -0,0 +1,125 @@ + +#ifndef __sp_marshal_MARSHAL_H__ +#define __sp_marshal_MARSHAL_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/* NONE:NONE (sp-marshal.list:2) */ +#define sp_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID +#define sp_marshal_NONE__NONE sp_marshal_VOID__VOID + +/* NONE:UINT (sp-marshal.list:3) */ +#define sp_marshal_VOID__UINT g_cclosure_marshal_VOID__UINT +#define sp_marshal_NONE__UINT sp_marshal_VOID__UINT + +/* NONE:POINTER (sp-marshal.list:4) */ +#define sp_marshal_VOID__POINTER g_cclosure_marshal_VOID__POINTER +#define sp_marshal_NONE__POINTER sp_marshal_VOID__POINTER + +/* NONE:POINTER,BOOLEAN (sp-marshal.list:5) */ +extern void sp_marshal_VOID__POINTER_BOOLEAN (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define sp_marshal_NONE__POINTER_BOOLEAN sp_marshal_VOID__POINTER_BOOLEAN + +/* NONE:POINTER,UINT (sp-marshal.list:6) */ +extern void sp_marshal_VOID__POINTER_UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define sp_marshal_NONE__POINTER_UINT sp_marshal_VOID__POINTER_UINT + +/* NONE:POINTER,DOUBLE (sp-marshal.list:7) */ +extern void sp_marshal_VOID__POINTER_DOUBLE (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define sp_marshal_NONE__POINTER_DOUBLE sp_marshal_VOID__POINTER_DOUBLE + +/* NONE:DOUBLE,DOUBLE (sp-marshal.list:8) */ +extern void sp_marshal_VOID__DOUBLE_DOUBLE (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define sp_marshal_NONE__DOUBLE_DOUBLE sp_marshal_VOID__DOUBLE_DOUBLE + +/* NONE:STRING,BOOL (sp-marshal.list:9) */ +extern void sp_marshal_VOID__STRING_BOOLEAN (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define sp_marshal_NONE__STRING_BOOL sp_marshal_VOID__STRING_BOOLEAN + +/* BOOLEAN:NONE (sp-marshal.list:10) */ +extern void sp_marshal_BOOLEAN__VOID (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define sp_marshal_BOOLEAN__NONE sp_marshal_BOOLEAN__VOID + +/* BOOLEAN:UINT (sp-marshal.list:11) */ +extern void sp_marshal_BOOLEAN__UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* BOOLEAN:POINTER (sp-marshal.list:12) */ +extern void sp_marshal_BOOLEAN__POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* BOOLEAN:POINTER,UINT (sp-marshal.list:13) */ +extern void sp_marshal_BOOLEAN__POINTER_UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* BOOLEAN:POINTER,POINTER (sp-marshal.list:14) */ +extern void sp_marshal_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* INT:POINTER,POINTER (sp-marshal.list:15) */ +extern void sp_marshal_INT__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* DOUBLE:POINTER,UINT (sp-marshal.list:16) */ +extern void sp_marshal_DOUBLE__POINTER_UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +G_END_DECLS + +#endif /* __sp_marshal_MARSHAL_H__ */ diff --git a/src/helper/sp-marshal.list b/src/helper/sp-marshal.list new file mode 100644 index 000000000..15ddb1ec4 --- /dev/null +++ b/src/helper/sp-marshal.list @@ -0,0 +1,16 @@ +# marshallers for sodipodi +NONE:NONE +NONE:UINT +NONE:POINTER +NONE:POINTER,BOOLEAN +NONE:POINTER,UINT +NONE:POINTER,DOUBLE +NONE:DOUBLE,DOUBLE +NONE:STRING,BOOL +BOOLEAN:NONE +BOOLEAN:UINT +BOOLEAN:POINTER +BOOLEAN:POINTER,UINT +BOOLEAN:POINTER,POINTER +INT:POINTER,POINTER +DOUBLE:POINTER,UINT diff --git a/src/helper/stlport.h b/src/helper/stlport.h new file mode 100644 index 000000000..c9389e814 --- /dev/null +++ b/src/helper/stlport.h @@ -0,0 +1,26 @@ +#ifndef __STL_PORT_H__ +#define __STK_PORT_H__ + + +#include <list> +#include <glib/glist.h> +#include <glib/gslist.h> + +template <typename T> +class StlConv { +public : + static void slist(std::list<T> &stlList, const GSList *slist) { + for (const GSList *l = slist; l != NULL; l = l->next) { + T item = reinterpret_cast<T>(l->data); + stlList.push_back(item); + } + } + static void list(std::list<T> &stlList, const GList *list) { + for (const GList *l = list; l != NULL; l = l->next) { + T item = reinterpret_cast<T>(l->data); + stlList.push_back(item); + } + } +}; + +#endif diff --git a/src/helper/stock-items.cpp b/src/helper/stock-items.cpp new file mode 100644 index 000000000..fe2026043 --- /dev/null +++ b/src/helper/stock-items.cpp @@ -0,0 +1,267 @@ +#define __INK_STOCK_ITEMS__ + +/* + * Stock-items + * + * Stock Item management code + * + * Authors: + * John Cliff <simarilius@yahoo.com> + * + * Copyright 2004 John Cliff + * + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#define noSP_SS_VERBOSE + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "path-prefix.h" + + +#include <xml/repr.h> +#include "sp-gradient-fns.h" +#include "document-private.h" +#include "sp-pattern.h" +#include "sp-marker.h" +#include "desktop-handles.h" +#include "inkscape.h" + +#include "io/sys.h" + + + + +static SPObject *sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc); +static SPObject *sp_marker_load_from_svg(gchar const *name, SPDocument *current_doc); +static SPObject *sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc); + + +// FIXME: these should be merged with the icon loading code so they +// can share a common file/doc cache. This function should just +// take the dir to look in, and the file to check for, and cache +// against that, rather than the existing copy/paste code seen here. + +static SPObject * sp_marker_load_from_svg(gchar const *name, SPDocument *current_doc) +{ + static SPDocument *doc = NULL; + static unsigned int edoc = FALSE; + if (!current_doc) { + return NULL; + } + /* Try to load from document */ + if (!edoc && !doc) { + gchar *markers = g_build_filename(INKSCAPE_MARKERSDIR, "/markers.svg", NULL); + if (Inkscape::IO::file_test(markers, G_FILE_TEST_IS_REGULAR)) { + doc = sp_document_new(markers, FALSE); + } + g_free(markers); + if (doc) { + sp_document_ensure_up_to_date(doc); + } else { + edoc = TRUE; + } + } + if (!edoc && doc) { + /* Get the marker we want */ + SPObject *object = doc->getObjectById(name); + if (object && SP_IS_MARKER(object)) { + SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc); + Inkscape::XML::Node *mark_repr = SP_OBJECT_REPR(object)->duplicate(); + SP_OBJECT_REPR(defs)->addChild(mark_repr, NULL); + SPObject *cloned_item = current_doc->getObjectByRepr(mark_repr); + Inkscape::GC::release(mark_repr); + return cloned_item; + } + } + return NULL; +} + + +static SPObject * +sp_pattern_load_from_svg(gchar const *name, SPDocument *current_doc) +{ + static SPDocument *doc = NULL; + static unsigned int edoc = FALSE; + if (!current_doc) { + return NULL; + } + /* Try to load from document */ + if (!edoc && !doc) { + gchar *patterns = g_build_filename(INKSCAPE_PATTERNSDIR, "/patterns.svg", NULL); + if (Inkscape::IO::file_test(patterns, G_FILE_TEST_IS_REGULAR)) { + doc = sp_document_new(patterns, FALSE); + } + g_free(patterns); + if (doc) { + sp_document_ensure_up_to_date(doc); + } else { + edoc = TRUE; + } + } + if (!edoc && doc) { + /* Get the pattern we want */ + SPObject *object = doc->getObjectById(name); + if (object && SP_IS_PATTERN(object)) { + SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc); + Inkscape::XML::Node *pat_repr = SP_OBJECT_REPR(object)->duplicate(); + SP_OBJECT_REPR(defs)->addChild(pat_repr, NULL); + Inkscape::GC::release(pat_repr); + return object; + } + } + return NULL; +} + + +static SPObject * +sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc) +{ + static SPDocument *doc = NULL; + static unsigned int edoc = FALSE; + if (!current_doc) { + return NULL; + } + /* Try to load from document */ + if (!edoc && !doc) { + gchar *gradients = g_build_filename(INKSCAPE_GRADIENTSDIR, "/gradients.svg", NULL); + if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) { + doc = sp_document_new(gradients, FALSE); + } + g_free(gradients); + if (doc) { + sp_document_ensure_up_to_date(doc); + } else { + edoc = TRUE; + } + } + if (!edoc && doc) { + /* Get the gradient we want */ + SPObject *object = doc->getObjectById(name); + if (object && SP_IS_GRADIENT(object)) { + SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc); + Inkscape::XML::Node *pat_repr = SP_OBJECT_REPR(object)->duplicate(); + SP_OBJECT_REPR(defs)->addChild(pat_repr, NULL); + Inkscape::GC::release(pat_repr); + return object; + } + } + return NULL; +} + +// get_stock_item returns a pointer to an instance of the desired stock object in the current doc +// if necessary it will import the object. Copes with name clashes through use of the inkscape:stockid property +// This should be set to be the same as the id in the libary file. + +SPObject *get_stock_item(gchar const *urn) +{ + g_assert(urn != NULL); + + /* check its an inkscape URN */ + if (!strncmp (urn, "urn:inkscape:", 13)) { + + gchar const *e = urn + 13; + int a = 0; + gchar * name = g_strdup(e); + gchar *name_p = name; + while (*name_p != ':' && *name_p != '\0'){ + name_p++; + a++; + } + + if (*name_p ==':') { + name_p++; + } + + gchar * base = g_strndup(e, a); + + SPDesktop *desktop = inkscape_active_desktop(); + SPDocument *doc = SP_DT_DOCUMENT(desktop); + SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(doc); + + SPObject *object = NULL; + if (!strcmp(base, "marker")) { + for (SPObject *child = sp_object_first_child(SP_OBJECT(defs)); + child != NULL; + child = SP_OBJECT_NEXT(child)) + { + if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") && + !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) && + SP_IS_MARKER(child)) + { + object = child; + } + } + + } + else if (!strcmp(base,"pattern")) { + for (SPObject *child = sp_object_first_child(SP_OBJECT(defs)) ; + child != NULL; + child = SP_OBJECT_NEXT(child) ) + { + if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") && + !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) && + SP_IS_PATTERN(child)) + { + object = child; + } + } + + } + else if (!strcmp(base,"gradient")) { + for (SPObject *child = sp_object_first_child(SP_OBJECT(defs)); + child != NULL; + child = SP_OBJECT_NEXT(child)) + { + if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") && + !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) && + SP_IS_GRADIENT(child)) + { + object = child; + } + } + + } + + if (object == NULL) { + + if (!strcmp(base, "marker")) { + object = sp_marker_load_from_svg(name_p, doc); + } + else if (!strcmp(base, "pattern")) { + object = sp_pattern_load_from_svg(name_p, doc); + } + else if (!strcmp(base, "gradient")) { + object = sp_gradient_load_from_svg(name_p, doc); + } + } + + g_free(base); + g_free(name); + + return object; + } + + else { + + SPDesktop *desktop = inkscape_active_desktop(); + SPDocument *doc = SP_DT_DOCUMENT(desktop); + SPObject *object = doc->getObjectById(urn); + + return object; + } +} + +/* + 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/helper/stock-items.h b/src/helper/stock-items.h new file mode 100644 index 000000000..ddad55415 --- /dev/null +++ b/src/helper/stock-items.h @@ -0,0 +1,20 @@ +#define __INK_STOCK_ITEMS__ + +/* + * Stock-items + * + * Stock Item management code + * + * Authors: + * John Cliff <simarilius@yahoo.com> + * + * Copyright 2004 John Cliff + * + */ + +#include <glib/gtypes.h> + +#include <forward.h> + +SPObject *get_stock_item(gchar const *urn); + diff --git a/src/helper/unit-menu.cpp b/src/helper/unit-menu.cpp new file mode 100644 index 000000000..34a2b6344 --- /dev/null +++ b/src/helper/unit-menu.cpp @@ -0,0 +1,372 @@ +#define __SP_UNIT_MENU_C__ + +/* + * Unit selector with autupdate capability + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * + * Copyright (C) 2000-2002 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#define noUNIT_SELECTOR_VERBOSE + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include <gtk/gtksignal.h> +#include <gtk/gtkhbox.h> +#include <gtk/gtkmenu.h> +#include <gtk/gtkmenuitem.h> +#include "helper/sp-marshal.h" +#include "helper/units.h" +#include "unit-menu.h" +#include "widgets/spw-utilities.h" + +struct SPUnitSelector { + GtkHBox box; + + GtkWidget *menu; + + guint bases; + GSList *units; + SPUnit const *unit; + gdouble ctmscale; + guint plural : 1; + guint abbr : 1; + + guint update : 1; + + GSList *adjustments; +}; + +struct SPUnitSelectorClass { + GtkHBoxClass parent_class; + + gboolean (* set_unit)(SPUnitSelector *us, SPUnit const *old, SPUnit const *new_unit); +}; + +enum {SET_UNIT, LAST_SIGNAL}; + +static void sp_unit_selector_class_init(SPUnitSelectorClass *klass); +static void sp_unit_selector_init(SPUnitSelector *selector); +static void sp_unit_selector_finalize(GObject *object); + +static GtkHBoxClass *unit_selector_parent_class; +static guint signals[LAST_SIGNAL] = {0}; + +GtkType +sp_unit_selector_get_type(void) +{ + static GtkType type = 0; + if (!type) { + static GtkTypeInfo const info = { + "SPUnitSelector", + sizeof(SPUnitSelector), + sizeof(SPUnitSelectorClass), + (GtkClassInitFunc) sp_unit_selector_class_init, + (GtkObjectInitFunc) sp_unit_selector_init, + NULL, NULL, NULL + }; + type = gtk_type_unique(GTK_TYPE_HBOX, &info); + } + return type; +} + +static void +sp_unit_selector_class_init(SPUnitSelectorClass *klass) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = G_OBJECT_CLASS(klass); + widget_class = GTK_WIDGET_CLASS(klass); + + unit_selector_parent_class = (GtkHBoxClass*)gtk_type_class(GTK_TYPE_HBOX); + + signals[SET_UNIT] = g_signal_new("set_unit", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(SPUnitSelectorClass, set_unit), + NULL, NULL, + sp_marshal_BOOLEAN__POINTER_POINTER, + G_TYPE_BOOLEAN, 2, + G_TYPE_POINTER, G_TYPE_POINTER); + + object_class->finalize = sp_unit_selector_finalize; +} + +static void +sp_unit_selector_init(SPUnitSelector *us) +{ + us->ctmscale = 1.0; + us->abbr = FALSE; + us->plural = TRUE; + + us->menu = gtk_option_menu_new(); + + gtk_widget_show(us->menu); + gtk_box_pack_start(GTK_BOX(us), us->menu, TRUE, TRUE, 0); +} + +static void +sp_unit_selector_finalize(GObject *object) +{ + SPUnitSelector *selector = SP_UNIT_SELECTOR(object); + + if (selector->menu) { + selector->menu = NULL; + } + + while (selector->adjustments) { + gtk_object_unref(GTK_OBJECT(selector->adjustments->data)); + selector->adjustments = g_slist_remove(selector->adjustments, selector->adjustments->data); + } + + if (selector->units) { + sp_unit_free_list(selector->units); + } + + selector->unit = NULL; + + G_OBJECT_CLASS(unit_selector_parent_class)->finalize(object); +} + +GtkWidget * +sp_unit_selector_new(guint bases) +{ + SPUnitSelector *us = (SPUnitSelector*)gtk_type_new(SP_TYPE_UNIT_SELECTOR); + + sp_unit_selector_set_bases(us, bases); + + return (GtkWidget *) us; +} + +void +sp_unit_selector_setsize(GtkWidget *us, guint w, guint h) +{ + gtk_widget_set_size_request(((SPUnitSelector *) us)->menu, w, h); +} + +SPUnit const * +sp_unit_selector_get_unit(SPUnitSelector const *us) +{ + g_return_val_if_fail(us != NULL, NULL); + g_return_val_if_fail(SP_IS_UNIT_SELECTOR(us), NULL); + + return us->unit; +} + +static void +spus_unit_activate(GtkWidget *widget, SPUnitSelector *us) +{ + SPUnit const *unit = (SPUnit const *) gtk_object_get_data(GTK_OBJECT(widget), "unit"); + g_return_if_fail(unit != NULL); + +#ifdef UNIT_SELECTOR_VERBOSE + g_print("Old unit %s new unit %s\n", us->unit->name, unit->name); +#endif + + SPUnit const *old = us->unit; + us->unit = unit; + + us->update = TRUE; + + gboolean consumed = FALSE; + g_signal_emit(G_OBJECT(us), signals[SET_UNIT], 0, old, unit, &consumed); + + if ( !consumed + && ( unit->base == old->base + || ( unit->base == SP_UNIT_ABSOLUTE && old->base == SP_UNIT_DEVICE ) + || ( old->base == SP_UNIT_ABSOLUTE && unit->base == SP_UNIT_DEVICE ) ) ) { + // Either the same base, or absolute<->device: + /* Recalculate adjustments. */ + for (GSList *l = us->adjustments; l != NULL; l = g_slist_next(l)) { + GtkAdjustment *adj = GTK_ADJUSTMENT(l->data); + gdouble val = adj->value; +#ifdef UNIT_SELECTOR_VERBOSE + g_print("Old val %g ... ", val); +#endif + val = sp_convert_distance_full(val, *old, *unit); +#ifdef UNIT_SELECTOR_VERBOSE + g_print("new val %g\n", val); +#endif + adj->value = val; + } + /* need to separate the value changing from the notification + * or else the unit changes can break the calculations */ + for (GSList *l = us->adjustments; l != NULL; l = g_slist_next(l)) { + gtk_adjustment_value_changed(GTK_ADJUSTMENT(l->data)); + } + } else if (!consumed && unit->base != old->base) { + /* when the base changes, signal all the adjustments to get them + * to recalculate */ + for (GSList *l = us->adjustments; l != NULL; l = g_slist_next(l)) { + gtk_signal_emit_by_name(GTK_OBJECT(l->data), "value_changed"); + } + } + + us->update = FALSE; +} + +static void +spus_rebuild_menu(SPUnitSelector *us) +{ + if (GTK_OPTION_MENU(us->menu)->menu) { + gtk_option_menu_remove_menu(GTK_OPTION_MENU(us->menu)); + } + + GtkWidget *m = gtk_menu_new(); + + gtk_widget_show(m); + + gint pos = 0; + gint p = 0; + for (GSList *l = us->units; l != NULL; l = l->next) { + SPUnit const *u = (SPUnit*)l->data; + + // use only abbreviations in the menu + // i = gtk_menu_item_new_with_label((us->abbr) ? (us->plural) ? u->abbr_plural : u->abbr : (us->plural) ? u->plural : u->name); + GtkWidget *i = gtk_menu_item_new_with_label( u->abbr ); + + gtk_object_set_data(GTK_OBJECT(i), "unit", (gpointer) u); + gtk_signal_connect(GTK_OBJECT(i), "activate", GTK_SIGNAL_FUNC(spus_unit_activate), us); + + sp_set_font_size_smaller (i); + + gtk_widget_show(i); + + gtk_menu_shell_append(GTK_MENU_SHELL(m), i); + if (u == us->unit) pos = p; + p += 1; + } + + gtk_option_menu_set_menu(GTK_OPTION_MENU(us->menu), m); + + gtk_option_menu_set_history(GTK_OPTION_MENU(us->menu), pos); +} + +void +sp_unit_selector_set_bases(SPUnitSelector *us, guint bases) +{ + g_return_if_fail(us != NULL); + g_return_if_fail(SP_IS_UNIT_SELECTOR(us)); + + if (bases == us->bases) return; + + GSList *units = sp_unit_get_list(bases); + g_return_if_fail(units != NULL); + sp_unit_free_list(us->units); + us->units = units; + us->unit = (SPUnit*)units->data; + + spus_rebuild_menu(us); +} + +void +sp_unit_selector_add_unit(SPUnitSelector *us, SPUnit const *unit, int position) +{ + if (!g_slist_find(us->units, (gpointer) unit)) { + us->units = g_slist_insert(us->units, (gpointer) unit, position); + + spus_rebuild_menu(us); + } +} + +void +sp_unit_selector_set_unit(SPUnitSelector *us, SPUnit const *unit) +{ + g_return_if_fail(us != NULL); + g_return_if_fail(SP_IS_UNIT_SELECTOR(us)); + + if (unit == NULL) { + return; // silently return, by default a newly created selector uses pt + } + if (unit == us->unit) { + return; + } + + gint const pos = g_slist_index(us->units, (gpointer) unit); + g_return_if_fail(pos >= 0); + + gtk_option_menu_set_history(GTK_OPTION_MENU(us->menu), pos); + + SPUnit const *old = us->unit; + us->unit = unit; + + /* Recalculate adjustments */ + for (GSList *l = us->adjustments; l != NULL; l = l->next) { + GtkAdjustment *adj = GTK_ADJUSTMENT(l->data); + gdouble const val = sp_convert_distance_full(adj->value, *old, *unit); + gtk_adjustment_set_value(adj, val); + } +} + +void +sp_unit_selector_add_adjustment(SPUnitSelector *us, GtkAdjustment *adj) +{ + g_return_if_fail(us != NULL); + g_return_if_fail(SP_IS_UNIT_SELECTOR(us)); + g_return_if_fail(adj != NULL); + g_return_if_fail(GTK_IS_ADJUSTMENT(adj)); + + g_return_if_fail(!g_slist_find(us->adjustments, adj)); + + gtk_object_ref(GTK_OBJECT(adj)); + us->adjustments = g_slist_prepend(us->adjustments, adj); +} + +void +sp_unit_selector_remove_adjustment(SPUnitSelector *us, GtkAdjustment *adj) +{ + g_return_if_fail(us != NULL); + g_return_if_fail(SP_IS_UNIT_SELECTOR(us)); + g_return_if_fail(adj != NULL); + g_return_if_fail(GTK_IS_ADJUSTMENT(adj)); + + g_return_if_fail(g_slist_find(us->adjustments, adj)); + + us->adjustments = g_slist_remove(us->adjustments, adj); + gtk_object_unref(GTK_OBJECT(adj)); +} + +gboolean +sp_unit_selector_update_test(SPUnitSelector const *selector) +{ + g_return_val_if_fail(selector != NULL, FALSE); + g_return_val_if_fail(SP_IS_UNIT_SELECTOR(selector), FALSE); + + return selector->update; +} + +double +sp_unit_selector_get_value_in_pixels(SPUnitSelector const *selector, GtkAdjustment *adj) +{ + g_return_val_if_fail(selector != NULL, adj->value); + g_return_val_if_fail(SP_IS_UNIT_SELECTOR(selector), adj->value); + + return sp_units_get_pixels(adj->value, *(selector->unit)); +} + +void +sp_unit_selector_set_value_in_pixels(SPUnitSelector *selector, GtkAdjustment *adj, double value) +{ + g_return_if_fail(selector != NULL); + g_return_if_fail(SP_IS_UNIT_SELECTOR(selector)); + + gtk_adjustment_set_value(adj, sp_pixels_get_units(value, *(selector->unit))); +} + +/* + 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/helper/unit-menu.h b/src/helper/unit-menu.h new file mode 100644 index 000000000..bf5bb260e --- /dev/null +++ b/src/helper/unit-menu.h @@ -0,0 +1,59 @@ +#ifndef __SP_UNIT_MENU_H__ +#define __SP_UNIT_MENU_H__ + +/* + * SPUnitMenu + * + * Generic (and quite unintelligent) grid item for gnome canvas + * + * Copyright (C) Lauris Kaplinski 2000 + * + */ + +#include <glib/gtypes.h> +#include <gtk/gtkoptionmenu.h> + +#include <helper/helper-forward.h> + + +/* Unit selector Widget */ + +#define SP_TYPE_UNIT_SELECTOR (sp_unit_selector_get_type()) +#define SP_UNIT_SELECTOR(o) (GTK_CHECK_CAST((o), SP_TYPE_UNIT_SELECTOR, SPUnitSelector)) +#define SP_UNIT_SELECTOR_CLASS(k) (GTK_CHECK_CLASS_CAST((k), SP_TYPE_UNIT_SELECTOR, SPUnitSelectorClass)) +#define SP_IS_UNIT_SELECTOR(o) (GTK_CHECK_TYPE((o), SP_TYPE_UNIT_SELECTOR)) +#define SP_IS_UNIT_SELECTOR_CLASS(k) (GTK_CHECK_CLASS_TYPE((k), SP_TYPE_UNIT_SELECTOR)) + +GType sp_unit_selector_get_type(void); + +GtkWidget *sp_unit_selector_new(guint bases); +void sp_unit_selector_setsize(GtkWidget *us, guint w, guint h); + +SPUnit const *sp_unit_selector_get_unit(SPUnitSelector const *selector); + +void sp_unit_selector_set_bases(SPUnitSelector *selector, guint bases); +void sp_unit_selector_add_unit(SPUnitSelector *selector, SPUnit const *unit, int position); + +void sp_unit_selector_set_unit(SPUnitSelector *selector, SPUnit const *unit); +void sp_unit_selector_add_adjustment(SPUnitSelector *selector, GtkAdjustment *adjustment); +void sp_unit_selector_remove_adjustment(SPUnitSelector *selector, GtkAdjustment *adjustment); + +gboolean sp_unit_selector_update_test(SPUnitSelector const *selector); + +double sp_unit_selector_get_value_in_pixels(SPUnitSelector const *selector, GtkAdjustment *adj); +void sp_unit_selector_set_value_in_pixels(SPUnitSelector *selector, GtkAdjustment *adj, double value); + + + +#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 : diff --git a/src/helper/units-test.cpp b/src/helper/units-test.cpp new file mode 100644 index 000000000..1a983fece --- /dev/null +++ b/src/helper/units-test.cpp @@ -0,0 +1,115 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <math.h> + +#include <glibmm/i18n.h> +#include <helper/units.h> +#include <utest/utest.h> + + +/* N.B. Wrongly returns false if both near 0. (Not a problem for current users.) */ +static bool +approx_equal(double const x, double const y) +{ + return fabs(x / y - 1) < 1e-15; +} + +static double +sp_units_get_points(double const x, SPUnit const &unit) +{ + SPUnit const &pt_unit = sp_unit_get_by_id(SP_UNIT_PT); + double const px = sp_units_get_pixels(x, unit); + return sp_pixels_get_units(px, pt_unit); +} + +static double +sp_points_get_units(double const pts, SPUnit const &unit) +{ + SPUnit const &pt_unit = sp_unit_get_by_id(SP_UNIT_PT); + double const px = sp_units_get_pixels(pts, pt_unit); + return sp_pixels_get_units(px, unit); +} + +static bool +test_conversions() +{ + utest_start("sp_units_get_pixels, sp_pixels_get_units"); + + struct Case { double x; char const *abbr; double pts; } const tests[] = { + { 1.0, "pt", 1.0 }, + { 5.0, "pt", 5.0 }, + { 1.0, "in", 72.0 }, + { 2.0, "in", 144.0 }, + { 254., "mm", 720.0 }, + { 254., "cm", 7200. }, + { 254., "m", 720000. }, + { 1.5, "mm", (15 * 72. / 254) } + }; + for (unsigned i = 0; i < G_N_ELEMENTS(tests); ++i) { + char name[80]; + Case const &c = tests[i]; + SPUnit const &unit = *sp_unit_get_by_abbreviation(N_(c.abbr)); + + double const calc_pts = sp_units_get_points(c.x, unit); + snprintf(name, sizeof(name), "%.1f %s -> %.1f pt", c.x, c.abbr, c.pts); + UTEST_TEST(name) { + UTEST_ASSERT(approx_equal(calc_pts, c.pts)); + } + + double const calc_x = sp_points_get_units(c.pts, unit); + snprintf(name, sizeof(name), "%.1f pt -> %.1f %s", c.pts, c.x, c.abbr); + UTEST_TEST(name) { + UTEST_ASSERT(approx_equal(calc_x, c.x)); + } + + double tmp = c.x; + bool const converted_to_pts = sp_convert_distance(&tmp, &unit, SP_PS_UNIT); + snprintf(name, sizeof(name), "convert %.1f %s -> %.1f pt", c.x, c.abbr, c.pts); + UTEST_TEST(name) { + UTEST_ASSERT(converted_to_pts); + UTEST_ASSERT(approx_equal(tmp, c.pts)); + } + + tmp = c.pts; + bool const converted_from_pts = sp_convert_distance(&tmp, SP_PS_UNIT, &unit); + snprintf(name, sizeof(name), "convert %.1f pt -> %.1f %s", c.pts, c.x, c.abbr); + UTEST_TEST(name) { + UTEST_ASSERT(converted_from_pts); + UTEST_ASSERT(approx_equal(tmp, c.x)); + } + } + return utest_end(); +} + +static bool +test_unit_table() +{ + utest_start("unit table"); + UTEST_TEST("sp_units_table_sane") { + UTEST_ASSERT(sp_units_table_sane()); + } + return utest_end(); +} + +int +main(int argc, char *argv[]) +{ + int const ret = ( ( test_conversions() + && test_unit_table() ) + ? EXIT_SUCCESS + : EXIT_FAILURE ); + return ret; +} + + +/* + 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/helper/units.cpp b/src/helper/units.cpp new file mode 100644 index 000000000..448f60302 --- /dev/null +++ b/src/helper/units.cpp @@ -0,0 +1,260 @@ +#define __SP_PAPER_C__ + +/* + * SPUnit + * + * Ported from libgnomeprint + * + * Authors: + * Dirk Luetjens <dirk@luedi.oche.de> + * Yves Arrouye <Yves.Arrouye@marin.fdn.fr> + * Lauris Kaplinski <lauris@ximian.com> + * bulia byak <buliabyak@users.sf.net> + * + * Copyright 1999-2001 Ximian, Inc. and authors + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "helper/units.h" +#include <glibmm/i18n.h> +#include "unit-constants.h" +#include "svg/svg-length.h" + +/* todo: use some fancy unit program */ + +/* The order determines the order of the list returned by sp_unit_get_list. + * (It can also affect string lookups if there are any duplicates in the + * current locale... hopefully none.) If you re-order this list, then you must + * also re-order the SPUnitId enum values accordingly. Run `make check' (which + * calls sp_unit_table_sane) to ensure that the two are in sync. + */ +SPUnit const sp_units[] = { + {SP_UNIT_SCALE, SP_UNIT_DIMENSIONLESS, 1.0, NONE, SVGLength::NONE, N_("Unit"), "", N_("Units"), ""}, + {SP_UNIT_PT, SP_UNIT_ABSOLUTE, PX_PER_PT, SP_PT, SVGLength::PT, N_("Point"), N_("pt"), N_("Points"), N_("Pt")}, + {SP_UNIT_PX, SP_UNIT_DEVICE, PX_PER_PX, SP_PX, SVGLength::PX, N_("Pixel"), N_("px"), N_("Pixels"), N_("Px")}, + /* You can add new elements from this point forward */ + {SP_UNIT_PERCENT, SP_UNIT_DIMENSIONLESS, 0.01, NONE, SVGLength::PERCENT, N_("Percent"), N_("%"), N_("Percents"), N_("%")}, + {SP_UNIT_MM, SP_UNIT_ABSOLUTE, PX_PER_MM, SP_MM, SVGLength::MM, N_("Millimeter"), N_("mm"), N_("Millimeters"), N_("mm")}, + {SP_UNIT_CM, SP_UNIT_ABSOLUTE, PX_PER_CM, SP_CM, SVGLength::CM, N_("Centimeter"), N_("cm"), N_("Centimeters"), N_("cm")}, + {SP_UNIT_M, SP_UNIT_ABSOLUTE, PX_PER_M, SP_M, SVGLength::NONE, N_("Meter"), N_("m"), N_("Meters"), N_("m")}, // no svg_unit + {SP_UNIT_IN, SP_UNIT_ABSOLUTE, PX_PER_IN, SP_IN, SVGLength::INCH, N_("Inch"), N_("in"), N_("Inches"), N_("in")}, + /* Volatiles do not have default, so there are none here */ + // TRANSLATORS: for info, see http://www.w3.org/TR/REC-CSS2/syndata.html#length-units + {SP_UNIT_EM, SP_UNIT_VOLATILE, 1.0, NONE, SVGLength::EM, N_("Em square"), N_("em"), N_("Em squares"), N_("em")}, + // TRANSLATORS: for info, see http://www.w3.org/TR/REC-CSS2/syndata.html#length-units + {SP_UNIT_EX, SP_UNIT_VOLATILE, 1.0, NONE, SVGLength::EX, N_("Ex square"), N_("ex"), N_("Ex squares"), N_("ex")}, +}; + +#define sp_num_units G_N_ELEMENTS(sp_units) + +SPUnit const * +sp_unit_get_by_abbreviation(gchar const *abbreviation) +{ + g_return_val_if_fail(abbreviation != NULL, NULL); + + for (unsigned i = 0 ; i < sp_num_units ; i++) { + if (!g_strcasecmp(abbreviation, sp_units[i].abbr)) return &sp_units[i]; + if (!g_strcasecmp(abbreviation, sp_units[i].abbr_plural)) return &sp_units[i]; + } + + return NULL; +} + +gchar const * +sp_unit_get_abbreviation(SPUnit const *unit) +{ + g_return_val_if_fail(unit != NULL, NULL); + + return unit->abbr; +} + +gchar const * +sp_unit_get_plural (SPUnit const *unit) +{ + g_return_val_if_fail(unit != NULL, NULL); + + return unit->plural; +} + +SPMetric +sp_unit_get_metric(SPUnit const *unit) +{ + g_return_val_if_fail(unit != NULL, NONE); + + return unit->metric; +} + +guint +sp_unit_get_svg_unit(SPUnit const *unit) +{ + g_return_val_if_fail(unit != NULL, NONE); + + return unit->svg_unit; +} + +GSList * +sp_unit_get_list(guint bases) +{ + g_return_val_if_fail((bases & ~SP_UNITS_ALL) == 0, NULL); + + GSList *units = NULL; + for (unsigned i = sp_num_units ; i--; ) { + if (bases & sp_units[i].base) { + units = g_slist_prepend(units, (gpointer) &sp_units[i]); + } + } + + return units; +} + +void +sp_unit_free_list(GSList *units) +{ + g_slist_free(units); +} + +/* These are pure utility */ +/* Return TRUE if conversion is possible */ +gboolean +sp_convert_distance(gdouble *distance, SPUnit const *from, SPUnit const *to) +{ + g_return_val_if_fail(distance != NULL, FALSE); + g_return_val_if_fail(from != NULL, FALSE); + g_return_val_if_fail(to != NULL, FALSE); + + if (from == to) return TRUE; + if ((from->base == SP_UNIT_DIMENSIONLESS) || (to->base == SP_UNIT_DIMENSIONLESS)) { + *distance = *distance * from->unittobase / to->unittobase; + return TRUE; + } + if ((from->base == SP_UNIT_VOLATILE) || (to->base == SP_UNIT_VOLATILE)) return FALSE; + + if ((from->base == to->base) + || (from->base == SP_UNIT_DEVICE) && (to->base == SP_UNIT_ABSOLUTE) + || (from->base == SP_UNIT_ABSOLUTE) && (to->base == SP_UNIT_DEVICE)) + { + *distance = *distance * from->unittobase / to->unittobase; + return TRUE; + } + + return FALSE; +} + +/** @param devicetransform for device units. */ +/* TODO: Remove the ctmscale parameter given that we no longer have SP_UNIT_USERSPACE. */ +gdouble +sp_convert_distance_full(gdouble const from_dist, SPUnit const &from, SPUnit const &to) +{ + if (&from == &to) { + return from_dist; + } + if (from.base == to.base) { + gdouble ret = from_dist; + bool const succ = sp_convert_distance(&ret, &from, &to); + g_assert(succ); + return ret; + } + if ((from.base == SP_UNIT_DIMENSIONLESS) + || (to.base == SP_UNIT_DIMENSIONLESS)) + { + return from_dist * from.unittobase / to.unittobase; + } + g_return_val_if_fail(((from.base != SP_UNIT_VOLATILE) + && (to.base != SP_UNIT_VOLATILE)), + from_dist); + + gdouble absolute; + switch (from.base) { + case SP_UNIT_ABSOLUTE: + case SP_UNIT_DEVICE: + absolute = from_dist * from.unittobase; + break; + default: + g_warning("file %s: line %d: Illegal unit (base 0x%x)", __FILE__, __LINE__, from.base); + return from_dist; + } + + gdouble ret; + switch (to.base) { + default: + g_warning("file %s: line %d: Illegal unit (base 0x%x)", __FILE__, __LINE__, to.base); + /* FALL-THROUGH */ + case SP_UNIT_ABSOLUTE: + case SP_UNIT_DEVICE: + ret = absolute / to.unittobase; + break; + } + + return ret; +} + +/* Some more convenience */ + +gdouble +sp_units_get_pixels(gdouble const units, SPUnit const &unit) +{ + if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) { + return units * unit.unittobase; + } else { + g_warning("Different unit bases: No exact unit conversion available"); + return units * unit.unittobase; + } +} + +gdouble +sp_pixels_get_units(gdouble const pixels, SPUnit const &unit) +{ + if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) { + return pixels / unit.unittobase; + } else { + g_warning("Different unit bases: No exact unit conversion available"); + return pixels / unit.unittobase; + } +} + +bool +sp_units_table_sane() +{ + for (unsigned i = 0; i < G_N_ELEMENTS(sp_units); ++i) { + if (unsigned(sp_units[i].unit_id) != i) { + return false; + } + } + return true; +} + +/** Converts angle (in deg) to compass display */ +double +angle_to_compass(double angle) +{ + double ret = 90 - angle; + if (ret < 0) + ret = 360 + ret; + return ret; +} + +/** Converts angle (in deg) to compass display */ +double +angle_from_compass(double angle) +{ + double ret = 90 - angle; + if (ret > 180) + ret = ret - 180; + return ret; +} + + +/* + 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/helper/units.h b/src/helper/units.h new file mode 100644 index 000000000..3acb65828 --- /dev/null +++ b/src/helper/units.h @@ -0,0 +1,146 @@ +#ifndef __SP_UNIT_H__ +#define __SP_UNIT_H__ + +/* + * SPUnit + * + * Ported from libgnomeprint + * + * Authors: + * Dirk Luetjens <dirk@luedi.oche.de> + * Yves Arrouye <Yves.Arrouye@marin.fdn.fr> + * Lauris Kaplinski <lauris@ximian.com> + * + * Copyright 1999-2001 Ximian, Inc. and authors + * + */ + +#include <glib/gmessages.h> +#include <glib/gslist.h> +#include <glib/gtypes.h> +#include "sp-metric.h" + + +/* + * Units and conversion methods used by libgnomeprint. + * + * You need those for certain config keys (like paper size), if you are + * interested in using these (look at gnome-print-config.h for discussion, + * why you may NOT be interested in paper size). + * + * Unit bases define set of mutually unrelated measuring systems (numbers, + * paper, screen and dimesionless user coordinates). Still, you can convert + * between those, specifying scaling factors explicitly. + * + * Paper (i.e. output) coordinates are taken as absolute real world units. + * It has some justification, because screen unit (pixel) size changes, + * if you change screen resolution, while you cannot change output on paper + * as easily (unless you have thermally contracting paper, of course). + * + */ + +struct SPUnit; +struct SPDistance; + +/* + * The base linear ("absolute") unit is 1/72th of an inch, i.e. the base unit of postscript. + */ + +/* + * Unit bases + */ +enum SPUnitBase { + SP_UNIT_DIMENSIONLESS = (1 << 0), /* For percentages and like */ + SP_UNIT_ABSOLUTE = (1 << 1), /* Real world distances - i.e. mm, cm... */ + SP_UNIT_DEVICE = (1 << 2), /* Pixels in the SVG/CSS sense. */ + SP_UNIT_VOLATILE = (1 << 3) /* em and ex */ +}; + +/* + * Units: indexes into sp_units. + */ +enum SPUnitId { + SP_UNIT_SCALE, // 1.0 == 100% + SP_UNIT_PT, // Postscript points: exactly 72 per inch + SP_UNIT_PX, // "Pixels" in the CSS sense; though Inkscape assumes a constant 90 per inch. + SP_UNIT_PERCENT, /* Note: In Inkscape this often means "relative to current value" (for + users to edit a value), rather than the SVG/CSS use of percentages. */ + SP_UNIT_MM, // millimetres + SP_UNIT_CM, // centimetres + SP_UNIT_M, // metres + SP_UNIT_IN, // inches + SP_UNIT_EM, // font-size of relevant font + SP_UNIT_EX, // x-height of relevant font + sp_max_unit_id = SP_UNIT_EX // For bounds-checking in sp_unit_get_by_id. +}; + +/* + * Notice, that for correct menus etc. you have to use + * ngettext method family yourself. For that reason we + * do not provide translations in unit names. + * I also do not know, whether to allow user-created units, + * because this would certainly confuse textdomain. + */ + +struct SPUnit { + SPUnitId unit_id; /* used as sanity check */ + SPUnitBase base; + gdouble unittobase; /* how many base units in this unit */ + SPMetric metric; // the corresponding SPMetric from sp-metrics.h + guint svg_unit; // the corresponding SVGLengthUnit + + /* When using, you must call "gettext" on them so they're translated */ + gchar const *name; + gchar const *abbr; + gchar const *plural; + gchar const *abbr_plural; +}; + +const SPUnit *sp_unit_get_by_abbreviation (const gchar *abbreviation); +/* When using, you must call "gettext" on them so they're translated */ +const gchar *sp_unit_get_abbreviation (const SPUnit *unit); +gchar const *sp_unit_get_plural (SPUnit const *unit); + +SPMetric sp_unit_get_metric(SPUnit const *unit); +guint sp_unit_get_svg_unit(SPUnit const *unit); + +extern SPUnit const sp_units[]; + +inline SPUnit const & +sp_unit_get_by_id(SPUnitId const id) +{ + /* inline because the compiler should optimize away the g_return_val_if_fail test in the + usual case that the argument value is known at compile-time, leaving just + "return sp_units[constant]". */ + unsigned const ix = unsigned(id); + g_return_val_if_fail(ix <= sp_max_unit_id, sp_units[SP_UNIT_PX]); + return sp_units[ix]; +} + +#define SP_PS_UNIT (&sp_unit_get_by_id(SP_UNIT_PT)) + + +/** Used solely by units-test.cpp. */ +bool sp_units_table_sane(); + +#define SP_UNITS_ALL (SP_UNIT_DIMENSIONLESS | SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE | SP_UNIT_VOLATILE) + +GSList *sp_unit_get_list (guint bases); +void sp_unit_free_list (GSList *units); + +/* These are pure utility */ +/* Return TRUE if conversion is possible, FALSE if unit bases differ */ +gboolean sp_convert_distance (gdouble *distance, const SPUnit *from, const SPUnit *to); + +/* If either one is NULL, transconverting to/from that base fails */ +/* Generic conversion between volatile units would be useless anyways */ +gdouble sp_convert_distance_full(gdouble const from_dist, SPUnit const &from, SPUnit const &to); + +/* Some more convenience */ +gdouble sp_units_get_pixels(gdouble const units, SPUnit const &unit); +gdouble sp_pixels_get_units(gdouble const pixels, SPUnit const &unit); + +double angle_to_compass(double angle); +double angle_from_compass(double angle); + +#endif diff --git a/src/helper/window.cpp b/src/helper/window.cpp new file mode 100644 index 000000000..346bd19f1 --- /dev/null +++ b/src/helper/window.cpp @@ -0,0 +1,47 @@ +#define __SP_WINDOW_C__ + +/* + * Generic window implementation + * + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * This code is in public domain + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <gtk/gtkwindow.h> + +#include "inkscape.h" +#include "shortcuts.h" +#include "desktop.h" +#include "event-context.h" + +static gboolean +sp_window_key_press (GtkWidget *widget, GdkEventKey *event) +{ + unsigned int shortcut; + shortcut = get_group0_keyval (event) | + ( event->state & GDK_SHIFT_MASK ? + SP_SHORTCUT_SHIFT_MASK : 0 ) | + ( event->state & GDK_CONTROL_MASK ? + SP_SHORTCUT_CONTROL_MASK : 0 ) | + ( event->state & GDK_MOD1_MASK ? + SP_SHORTCUT_ALT_MASK : 0 ); + return sp_shortcut_invoke (shortcut, SP_ACTIVE_DESKTOP); +} + +GtkWidget * +sp_window_new (const gchar *title, unsigned int resizeable) +{ + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title ((GtkWindow *) window, title); + gtk_window_set_resizable ((GtkWindow *) window, resizeable); + g_signal_connect_after ((GObject *) window, "key_press_event", (GCallback) sp_window_key_press, NULL); + + return window; +} + + diff --git a/src/helper/window.h b/src/helper/window.h new file mode 100644 index 000000000..764cb0413 --- /dev/null +++ b/src/helper/window.h @@ -0,0 +1,28 @@ +#ifndef __SP_WINDOW_H__ +#define __SP_WINDOW_H__ + +/* + * Generic window implementation + * + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * This code is in public domain + */ + +#include <gtk/gtkwidget.h> + +GtkWidget *sp_window_new (const gchar *title, unsigned int resizeable); + +#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 : |
