=== modified file 'src/extension/CMakeLists.txt' --- src/extension/CMakeLists.txt 2013-09-01 23:39:00 +0000 +++ src/extension/CMakeLists.txt 2013-11-13 19:25:31 +0000 @@ -45,6 +45,7 @@ internal/image-resolution.cpp internal/latex-pstricks.cpp internal/latex-pstricks-out.cpp + internal/metafile-inout.cpp internal/metafile-print.cpp internal/odf.cpp internal/latex-text-renderer.cpp === modified file 'src/extension/internal/Makefile_insert' --- src/extension/internal/Makefile_insert 2013-09-01 23:39:00 +0000 +++ src/extension/internal/Makefile_insert 2013-11-13 19:25:31 +0000 @@ -162,6 +162,8 @@ extension/internal/emf-print.cpp \ extension/internal/emf-inout.h \ extension/internal/emf-inout.cpp \ + extension/internal/metafile-inout.h \ + extension/internal/metafile-inout.cpp \ extension/internal/metafile-print.h \ extension/internal/metafile-print.cpp \ extension/internal/wmf-print.h \ === modified file 'src/extension/internal/emf-inout.cpp' --- src/extension/internal/emf-inout.cpp 2013-10-27 16:33:32 +0000 +++ src/extension/internal/emf-inout.cpp 2013-11-15 22:19:37 +0000 @@ -26,7 +26,7 @@ # include "config.h" #endif -#include //This must precede text_reassemble.h or it blows up in pngconf.h when compiling +//#include //This must precede text_reassemble.h or it blows up in pngconf.h when compiling #include #include #include @@ -69,154 +69,6 @@ static uint32_t ICMmode = 0; // not used yet, but code to read it from EMF implemented static uint32_t BLTmode = 0; -/** Construct a PNG in memory from an RGB from the EMF file - -from: -http://www.lemoda.net/c/write-png/ - -which was based on: -http://stackoverflow.com/questions/1821806/how-to-encode-png-to-buffer-using-libpng - -gcc -Wall -o testpng testpng.c -lpng - -Originally here, but moved up - -#include -#include -#include -#include -*/ - - -/* Given "bitmap", this returns the pixel of bitmap at the point - ("x", "y"). */ - -pixel_t * Emf::pixel_at (bitmap_t * bitmap, int x, int y) -{ - return bitmap->pixels + bitmap->width * y + x; -} - - -/* Write "bitmap" to a PNG file specified by "path"; returns 0 on - success, non-zero on error. */ - -void -Emf::my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - PMEMPNG p=(PMEMPNG)png_get_io_ptr(png_ptr); - - size_t nsize = p->size + length; - - /* allocate or grow buffer */ - if(p->buffer){ p->buffer = (char *) realloc(p->buffer, nsize); } - else{ p->buffer = (char *) malloc(nsize); } - - if(!p->buffer){ png_error(png_ptr, "Write Error"); } - - /* copy new bytes to end of buffer */ - memcpy(p->buffer + p->size, data, length); - p->size += length; -} - -void Emf::toPNG(PMEMPNG accum, int width, int height, const char *px){ - bitmap_t bmStore; - bitmap_t *bitmap = &bmStore; - accum->buffer=NULL; // PNG constructed in memory will end up here, caller must free(). - accum->size=0; - bitmap->pixels=(pixel_t *)px; - bitmap->width = width; - bitmap->height = height; - - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - size_t x, y; - png_byte ** row_pointers = NULL; - /* The following number is set by trial and error only. I cannot - see where it it is documented in the libpng manual. - */ - int pixel_size = 3; - int depth = 8; - - png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL){ - accum->buffer=NULL; - return; - } - - info_ptr = png_create_info_struct (png_ptr); - if (info_ptr == NULL){ - png_destroy_write_struct (&png_ptr, &info_ptr); - accum->buffer=NULL; - return; - } - - /* Set up error handling. */ - - if (setjmp (png_jmpbuf (png_ptr))) { - png_destroy_write_struct (&png_ptr, &info_ptr); - accum->buffer=NULL; - return; - } - - /* Set image attributes. */ - - png_set_IHDR ( - png_ptr, - info_ptr, - bitmap->width, - bitmap->height, - depth, - PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT - ); - - /* Initialize rows of PNG. */ - - row_pointers = (png_byte **) png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); - for (y = 0; y < bitmap->height; ++y) { - png_byte *row = - (png_byte *) png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size); - row_pointers[bitmap->height - y - 1] = row; // Row order in EMF is reversed. - for (x = 0; x < bitmap->width; ++x) { - pixel_t * pixel = pixel_at (bitmap, x, y); - *row++ = pixel->red; // R & B channels were set correctly by DIB_to_RGB - *row++ = pixel->green; - *row++ = pixel->blue; - } - } - - /* Write the image data to memory */ - - png_set_rows (png_ptr, info_ptr, row_pointers); - - png_set_write_fn(png_ptr, accum, my_png_write_data, NULL); - - png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - for (y = 0; y < bitmap->height; y++) { - png_free (png_ptr, row_pointers[y]); - } - png_free (png_ptr, row_pointers); - png_destroy_write_struct(&png_ptr, &info_ptr); - -} - - -/* convert an EMF RGB(A) color to 0RGB -inverse of gethexcolor() in emf-print.cpp -*/ -uint32_t Emf::sethexcolor(U_COLORREF color){ - - uint32_t out; - out = (U_RGBAGetR(color) << 16) + - (U_RGBAGetG(color) << 8 ) + - (U_RGBAGetB(color) ); - return(out); -} - - Emf::Emf (void) // The null constructor { return; @@ -615,10 +467,10 @@ uint32_t iUsage, uint32_t offBits, uint32_t offBmi){ uint32_t idx; - char imagename[64]; // big enough - char imrotname[64]; // big enough - char xywh[64]; // big enough - int dibparams; + char imagename[64]; // big enough + char imrotname[64]; // big enough + char xywh[64]; // big enough + int dibparams = U_BI_UNKNOWN; // type of image not yet determined MEMPNG mempng; // PNG in memory comes back in this mempng.buffer = NULL; @@ -627,74 +479,60 @@ const char *px = NULL; // DIB pixels const U_RGBQUAD *ct = NULL; // DIB color table U_RGBQUAD ct2[2]; - uint32_t width, height, colortype, numCt, invert; - if( !cbBits || - !cbBmi || - (iUsage != U_DIB_RGB_COLORS) || - !(dibparams = get_DIB_params( // this returns pointers and values, but allocates no memory - pEmr, - offBits, - offBmi, - &px, - (const U_RGBQUAD **) &ct, - &numCt, - &width, - &height, - &colortype, - &invert - )) - ){ - - // U_EMRCREATEMONOBRUSH uses text/bk colors instead of what is in the color map. - if(((PU_EMR)pEmr)->iType == U_EMR_CREATEMONOBRUSH){ - if(numCt==2){ - ct2[0] = U_RGB2BGR(d->dc[d->level].textColor); - ct2[1] = U_RGB2BGR(d->dc[d->level].bkColor); - ct = &ct2[0]; - } - else { // createmonobrush renders on other platforms this way - return(0xFFFFFFFF); - } - } - - if(!DIB_to_RGBA( - px, // DIB pixel array - ct, // DIB color table - numCt, // DIB color table number of entries - &rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free. - width, // Width of pixel array in record - height, // Height of pixel array in record - colortype, // DIB BitCount Enumeration - numCt, // Color table used if not 0 - invert // If DIB rows are in opposite order from RGBA rows - ) && - rgba_px - ){ - toPNG( // Get the image from the RGBA px into mempng - &mempng, - width, height, // of the SRC bitmap - rgba_px - ); - free(rgba_px); + uint32_t width, height, colortype, numCt, invert; // if needed these values will be set in get_DIB_params + if(cbBits && cbBmi && (iUsage == U_DIB_RGB_COLORS)){ + // next call returns pointers and values, but allocates no memory + dibparams = get_DIB_params(pEmr, offBits, offBmi, &px, (const U_RGBQUAD **) &ct, + &numCt, &width, &height, &colortype, &invert); + if(dibparams ==U_BI_RGB){ + // U_EMRCREATEMONOBRUSH uses text/bk colors instead of what is in the color map. + if(((PU_EMR)pEmr)->iType == U_EMR_CREATEMONOBRUSH){ + if(numCt==2){ + ct2[0] = U_RGB2BGR(d->dc[d->level].textColor); + ct2[1] = U_RGB2BGR(d->dc[d->level].bkColor); + ct = &ct2[0]; + } + else { // This record is invalid, nothing more to do here, let caller handle it + return(U_EMR_INVALID); + } + } + + if(!DIB_to_RGBA( + px, // DIB pixel array + ct, // DIB color table + numCt, // DIB color table number of entries + &rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free. + width, // Width of pixel array in record + height, // Height of pixel array in record + colortype, // DIB BitCount Enumeration + numCt, // Color table used if not 0 + invert // If DIB rows are in opposite order from RGBA rows + )){ + toPNG( // Get the image from the RGBA px into mempng + &mempng, + width, height, // of the SRC bitmap + rgba_px + ); + free(rgba_px); + } } } - gchar *base64String; - if(dibparams == U_BI_JPEG || dibparams==U_BI_PNG){ + + gchar *base64String=NULL; + if(dibparams == U_BI_JPEG || dibparams==U_BI_PNG){ // image was binary png or jpg in source file base64String = g_base64_encode((guchar*) px, numCt ); - idx = in_images(d, (char *) base64String); } - else if(mempng.buffer){ + else if(mempng.buffer){ // image was DIB in source file, converted to png in this routine base64String = g_base64_encode((guchar*) mempng.buffer, mempng.size ); free(mempng.buffer); - idx = in_images(d, (char *) base64String); } - else { - // insert a random 3x4 blotch otherwise + else { // unknown or unsupported image type or failed conversion, insert the common bad image picture width = 3; height = 4; - base64String = g_strdup("iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII="); - idx = in_images(d, (char *) base64String); + base64String = bad_image_png(); } + + idx = in_images(d, (char *) base64String); if(!idx){ // add it if not already present - we looked at the actual data for comparison if(d->images.count == d->images.size){ enlarge_images(d); } idx = d->images.count; @@ -732,7 +570,7 @@ *(d->defs) += " "; *(d->defs) += " \n"; } - g_free(base64String); + g_free(base64String);//wait until this point to free because it might be a duplicate image /* image allows the inner image to be rotated nicely, load this one second only if needed imagename retained from above @@ -1343,7 +1181,7 @@ else if(iType == U_EMR_CREATEDIBPATTERNBRUSHPT || iType == U_EMR_CREATEMONOBRUSH){ PU_EMRCREATEDIBPATTERNBRUSHPT pEmr = (PU_EMRCREATEDIBPATTERNBRUSHPT) d->emf_obj[index].lpEMFR; tidx = add_image(d, (void *) pEmr, pEmr->cbBits, pEmr->cbBmi, pEmr->iUsage, pEmr->offBits, pEmr->offBmi); - if(tidx == 0xFFFFFFFF){ // This happens if createmonobrush has a DIB that isn't monochrome + if(tidx == U_EMR_INVALID){ // This happens if createmonobrush has a DIB that isn't monochrome double r, g, b; r = SP_COLOR_U_TO_F( U_RGBAGetR(d->dc[d->level].textColor)); g = SP_COLOR_U_TO_F( U_RGBAGetG(d->dc[d->level].textColor)); @@ -1502,13 +1340,11 @@ uint32_t iUsage, uint32_t offBits, uint32_t cbBits, uint32_t offBmi, uint32_t cbBmi){ SVGOStringStream tmp_image; - int dibparams; + int dibparams = U_BI_UNKNOWN; // type of image not yet determined + tmp_image << "\n\t \n"; + *(d->outsvg) += tmp_image.str().c_str(); - - *(d->outsvg) += "/> \n"; *(d->path) = ""; } @@ -1664,7 +1483,7 @@ // incompatible change to text drawing detected (color or background change) forces out existing text // OR // next record is valid type and forces pending text to be drawn immediately - if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((emr_mask != 0xFFFFFFFF) && (emr_mask & U_DRAW_TEXT) && d->tri->dirty)){ + if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((emr_mask != U_EMR_INVALID) && (emr_mask & U_DRAW_TEXT) && d->tri->dirty)){ TR_layout_analyze(d->tri); TR_layout_2_svg(d->tri); SVGOStringStream ts; @@ -1711,7 +1530,7 @@ */ if( - (emr_mask != 0xFFFFFFFF) && // next record is valid type + (emr_mask != U_EMR_INVALID) && // next record is valid type (d->mask & U_DRAW_VISIBLE) && // Current set of objects are drawable ( (d->mask & U_DRAW_FORCE) || // This draw is forced by STROKE/FILL/STROKEANDFILL PATH @@ -2625,7 +2444,7 @@ int stat = emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size); if(!stat){ tmp_path << "\n\tM " << pix_to_xy(d, start.x, start.y); - tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0 ; + tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0; tmp_path << " "; tmp_path << 180.0 * current_rotation(d)/M_PI; tmp_path << " "; @@ -2646,7 +2465,7 @@ int f2 = (d->arcdir == U_AD_COUNTERCLOCKWISE ? 0 : 1); if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){ tmp_path << "\n\tM " << pix_to_xy(d, start.x, start.y); - tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0 ; + tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0; tmp_path << " "; tmp_path << 180.0 * current_rotation(d)/M_PI; tmp_path << " "; @@ -2669,7 +2488,7 @@ if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){ tmp_path << "\n\tM " << pix_to_xy(d, center.x, center.y); tmp_path << "\n\tL " << pix_to_xy(d, start.x, start.y); - tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0 ; + tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0; tmp_path << " "; tmp_path << 180.0 * current_rotation(d)/M_PI; tmp_path << " "; @@ -2710,7 +2529,7 @@ if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){ // draw a line from current position to start, arc from there tmp_path << "\n\tL " << pix_to_xy(d, start.x, start.y); - tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0 ; + tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0; tmp_path << " "; tmp_path << 180.0 * current_rotation(d)/M_PI; tmp_path << " "; === modified file 'src/extension/internal/emf-inout.h' --- src/extension/internal/emf-inout.h 2013-08-31 16:05:13 +0000 +++ src/extension/internal/emf-inout.h 2013-11-13 19:25:31 +0000 @@ -11,9 +11,8 @@ #ifndef SEEN_EXTENSION_INTERNAL_EMF_H #define SEEN_EXTENSION_INTERNAL_EMF_H -#define PNG_SKIP_SETJMP_CHECK // else any further png.h include blows up in the compiler -#include #include +#include "extension/internal/metafile-inout.h" // picks up PNG #include "extension/implementation/implementation.h" #include "style.h" #include "text_reassemble.h" @@ -67,34 +66,6 @@ #define EMF_MAX_DC 128 -/* - both emf-inout.h and wmf-inout.h are included by init.cpp, so whichever one goes in first defines these ommon types -*/ -#ifndef SEEN_EXTENSION_INTERNAL_METAFILECOMMON_ -#define SEEN_EXTENSION_INTERNAL_METAFILECOMMON_ -/* A coloured pixel. */ -typedef struct { - uint8_t red; - uint8_t green; - uint8_t blue; - uint8_t opacity; -} pixel_t; - -/* A picture. */ - -typedef struct { - pixel_t *pixels; - size_t width; - size_t height; -} bitmap_t; - -/* structure to store PNG image bytes */ -typedef struct { - char *buffer; - size_t size; -} MEMPNG, *PMEMPNG; -#endif - typedef struct { Glib::ustring *outsvg; Glib::ustring *path; @@ -133,7 +104,8 @@ PEMF_OBJECT emf_obj; } EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA; -class Emf : Inkscape::Extension::Implementation::Implementation { //This is a derived class +class Emf : public Metafile +{ public: @@ -155,11 +127,6 @@ private: protected: - - static pixel_t *pixel_at (bitmap_t * bitmap, int x, int y); - static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); - static void toPNG(PMEMPNG accum, int width, int height, const char *px); - static uint32_t sethexcolor(U_COLORREF color); static void print_document_to_file(SPDocument *doc, const gchar *filename); static double current_scale(PEMF_CALLBACK_DATA d); static std::string current_matrix(PEMF_CALLBACK_DATA d, double x, double y, int useoffset); === added file 'src/extension/internal/metafile-inout.cpp' --- src/extension/internal/metafile-inout.cpp 1970-01-01 00:00:00 +0000 +++ src/extension/internal/metafile-inout.cpp 2013-11-13 19:25:31 +0000 @@ -0,0 +1,210 @@ +/** @file + * @brief Metafile input - common routines + *//* + * Authors: + * David Mathog + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include "extension/internal/metafile-inout.h" // picks up PNG +#include "extension/print.h" +#include "path-prefix.h" +#include "sp-gradient.h" +#include "sp-image.h" +#include "sp-linear-gradient.h" +#include "sp-pattern.h" +#include "sp-radial-gradient.h" +#include "style.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { + +Metafile::~Metafile() +{ + return; +} + +/** Construct a PNG in memory from an RGB from the EMF file + +from: +http://www.lemoda.net/c/write-png/ + +which was based on: +http://stackoverflow.com/questions/1821806/how-to-encode-png-to-buffer-using-libpng + +gcc -Wall -o testpng testpng.c -lpng + +Originally here, but moved up + +#include +#include +#include +#include +*/ + + +/* Given "bitmap", this returns the pixel of bitmap at the point + ("x", "y"). */ + +pixel_t * Metafile::pixel_at (bitmap_t * bitmap, int x, int y) +{ + return bitmap->pixels + bitmap->width * y + x; +} + + +/* Write "bitmap" to a PNG file specified by "path"; returns 0 on + success, non-zero on error. */ + +void +Metafile::my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + PMEMPNG p=(PMEMPNG)png_get_io_ptr(png_ptr); + + size_t nsize = p->size + length; + + /* allocate or grow buffer */ + if(p->buffer){ p->buffer = (char *) realloc(p->buffer, nsize); } + else{ p->buffer = (char *) malloc(nsize); } + + if(!p->buffer){ png_error(png_ptr, "Write Error"); } + + /* copy new bytes to end of buffer */ + memcpy(p->buffer + p->size, data, length); + p->size += length; +} + +void Metafile::toPNG(PMEMPNG accum, int width, int height, const char *px){ + bitmap_t bmStore; + bitmap_t *bitmap = &bmStore; + accum->buffer=NULL; // PNG constructed in memory will end up here, caller must free(). + accum->size=0; + bitmap->pixels=(pixel_t *)px; + bitmap->width = width; + bitmap->height = height; + + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + size_t x, y; + png_byte ** row_pointers = NULL; + /* The following number is set by trial and error only. I cannot + see where it it is documented in the libpng manual. + */ + int pixel_size = 3; + int depth = 8; + + png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL){ + accum->buffer=NULL; + return; + } + + info_ptr = png_create_info_struct (png_ptr); + if (info_ptr == NULL){ + png_destroy_write_struct (&png_ptr, &info_ptr); + accum->buffer=NULL; + return; + } + + /* Set up error handling. */ + + if (setjmp (png_jmpbuf (png_ptr))) { + png_destroy_write_struct (&png_ptr, &info_ptr); + accum->buffer=NULL; + return; + } + + /* Set image attributes. */ + + png_set_IHDR ( + png_ptr, + info_ptr, + bitmap->width, + bitmap->height, + depth, + PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT + ); + + /* Initialize rows of PNG. */ + + row_pointers = (png_byte **) png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); + for (y = 0; y < bitmap->height; ++y) { + png_byte *row = + (png_byte *) png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size); + row_pointers[bitmap->height - y - 1] = row; // Row order in EMF is reversed. + for (x = 0; x < bitmap->width; ++x) { + pixel_t * pixel = pixel_at (bitmap, x, y); + *row++ = pixel->red; // R & B channels were set correctly by DIB_to_RGB + *row++ = pixel->green; + *row++ = pixel->blue; + } + } + + /* Write the image data to memory */ + + png_set_rows (png_ptr, info_ptr, row_pointers); + + png_set_write_fn(png_ptr, accum, my_png_write_data, NULL); + + png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + for (y = 0; y < bitmap->height; y++) { + png_free (png_ptr, row_pointers[y]); + } + png_free (png_ptr, row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + +} + + +/* convert an EMF RGB(A) color to 0RGB +inverse of gethexcolor() in emf-print.cpp +*/ +uint32_t Metafile::sethexcolor(U_COLORREF color){ + + uint32_t out; + out = (U_RGBAGetR(color) << 16) + + (U_RGBAGetG(color) << 8 ) + + (U_RGBAGetB(color) ); + return(out); +} + +/* Return the base64 encoded png which is shown for all bad images. +Currently a random 3x4 blotch. +Caller must free. +*/ +gchar *Metafile::bad_image_png(void){ + gchar *gstring = g_strdup("iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII="); + return(gstring); +} + + + +} // namespace Internal +} // 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:fileencoding=utf-8:textwidth=99 : === added file 'src/extension/internal/metafile-inout.h' --- src/extension/internal/metafile-inout.h 1970-01-01 00:00:00 +0000 +++ src/extension/internal/metafile-inout.h 2013-11-13 19:25:31 +0000 @@ -0,0 +1,93 @@ +/** @file + * @brief Metafile input - common functions + *//* + * Authors: + * David Mathog + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_INKSCAPE_EXTENSION_INTERNAL_METAFILE_INOUT_H +#define SEEN_INKSCAPE_EXTENSION_INTERNAL_METAFILE_INOUT_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define PNG_SKIP_SETJMP_CHECK // else any further png.h include blows up in the compiler +#include +#include +#include +#include +#include +#include +#include +#include +#include <2geom/affine.h> +#include <2geom/pathvector.h> + +#include "extension/implementation/implementation.h" + +class SPObject; + +namespace Inkscape { +class Pixbuf; + +namespace Extension { +namespace Internal { + +/* A coloured pixel. */ +typedef struct { + uint8_t red; + uint8_t green; + uint8_t blue; + uint8_t opacity; +} pixel_t; + +/* A picture. */ + typedef struct { + pixel_t *pixels; + size_t width; + size_t height; +} bitmap_t; + +/* structure to store PNG image bytes */ +typedef struct { + char *buffer; + size_t size; +} MEMPNG, *PMEMPNG; + +class Metafile + : public Inkscape::Extension::Implementation::Implementation +{ +public: + Metafile() {} + ~Metafile(); + +protected: + static uint32_t sethexcolor(U_COLORREF color); + static pixel_t *pixel_at (bitmap_t * bitmap, int x, int y); + static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); + static void toPNG(PMEMPNG accum, int width, int height, const char *px); + static gchar *bad_image_png(void); + + +private: +}; + +} // namespace Internal +} // namespace Extension +} // namespace Inkscape + +#endif // SEEN_INKSCAPE_EXTENSION_INTERNAL_METAFILE_INOUT_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: +*/ === modified file 'src/extension/internal/wmf-inout.cpp' --- src/extension/internal/wmf-inout.cpp 2013-10-27 16:33:32 +0000 +++ src/extension/internal/wmf-inout.cpp 2013-11-15 22:19:37 +0000 @@ -26,7 +26,7 @@ # include "config.h" #endif -#include //This must precede text_reassemble.h or it blows up in pngconf.h when compiling +//#include //This must precede text_reassemble.h or it blows up in pngconf.h when compiling #include #include #include @@ -70,154 +70,6 @@ static bool clipset = false; static uint32_t BLTmode=0; -/** Construct a PNG in memory from an RGB from the WMF file - -from: -http://www.lemoda.net/c/write-png/ - -which was based on: -http://stackoverflow.com/questions/1821806/how-to-encode-png-to-buffer-using-libpng - -gcc -Wall -o testpng testpng.c -lpng - -Originally here, but moved up - -#include -#include -#include -#include -*/ - - -/* Given "bitmap", this returns the pixel of bitmap at the point - ("x", "y"). */ - -pixel_t * Wmf::pixel_at (bitmap_t * bitmap, int x, int y) -{ - return bitmap->pixels + bitmap->width * y + x; -} - - -/* Write "bitmap" to a PNG file specified by "path"; returns 0 on - success, non-zero on error. */ - -void -Wmf::my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - PMEMPNG p=(PMEMPNG)png_get_io_ptr(png_ptr); - - size_t nsize = p->size + length; - - /* allocate or grow buffer */ - if(p->buffer){ p->buffer = (char *) realloc(p->buffer, nsize); } - else{ p->buffer = (char *) malloc(nsize); } - - if(!p->buffer){ png_error(png_ptr, "Write Error"); } - - /* copy new bytes to end of buffer */ - memcpy(p->buffer + p->size, data, length); - p->size += length; -} - -void Wmf::toPNG(PMEMPNG accum, int width, int height, const char *px){ - bitmap_t bmStore; - bitmap_t *bitmap = &bmStore; - accum->buffer=NULL; // PNG constructed in memory will end up here, caller must free(). - accum->size=0; - bitmap->pixels=(pixel_t *)px; - bitmap->width = width; - bitmap->height = height; - - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - size_t x, y; - png_byte ** row_pointers = NULL; - /* The following number is set by trial and error only. I cannot - see where it it is documented in the libpng manual. - */ - int pixel_size = 3; - int depth = 8; - - png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL){ - accum->buffer=NULL; - return; - } - - info_ptr = png_create_info_struct (png_ptr); - if (info_ptr == NULL){ - png_destroy_write_struct (&png_ptr, &info_ptr); - accum->buffer=NULL; - return; - } - - /* Set up error handling. */ - - if (setjmp (png_jmpbuf (png_ptr))) { - png_destroy_write_struct (&png_ptr, &info_ptr); - accum->buffer=NULL; - return; - } - - /* Set image attributes. */ - - png_set_IHDR ( - png_ptr, - info_ptr, - bitmap->width, - bitmap->height, - depth, - PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT - ); - - /* Initialize rows of PNG. */ - - row_pointers = (png_byte **) png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); - for (y = 0; y < bitmap->height; ++y) { - png_byte *row = - (png_byte *) png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size); - row_pointers[bitmap->height - y - 1] = row; // Row order in WMF is reversed. - for (x = 0; x < bitmap->width; ++x) { - pixel_t * pixel = pixel_at (bitmap, x, y); - *row++ = pixel->red; // R & B channels were set correctly by DIB_to_RGB - *row++ = pixel->green; - *row++ = pixel->blue; - } - } - - /* Write the image data to memory */ - - png_set_rows (png_ptr, info_ptr, row_pointers); - - png_set_write_fn(png_ptr, accum, my_png_write_data, NULL); - - png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - for (y = 0; y < bitmap->height; y++) { - png_free (png_ptr, row_pointers[y]); - } - png_free (png_ptr, row_pointers); - png_destroy_write_struct(&png_ptr, &info_ptr); - -} - - -/* convert an WMF RGB(A) color to 0RGB -inverse of gethexcolor() in emf-print.cpp -*/ -uint32_t Wmf::sethexcolor(U_COLORREF color){ - - uint32_t out; - out = (U_RGBAGetR(color) << 16) + - (U_RGBAGetG(color) << 8 ) + - (U_RGBAGetB(color) ); - return(out); -} - - Wmf::Wmf (void) // The null constructor { return; @@ -322,6 +174,7 @@ /* WMF has no worldTransform, so this always returns 1.0. Retain it to keep WMF and WMF in sync as much as possible.*/ double Wmf::current_scale(PWMF_CALLBACK_DATA d){ + (void) d; return 1.0; } @@ -342,6 +195,7 @@ /* WMF has no worldTransform, so this always returns 0. Retain it to keep WMF and WMF in sync as much as possible.*/ double Wmf::current_rotation(PWMF_CALLBACK_DATA d){ + (void) d; return 0.0; } @@ -592,9 +446,9 @@ uint32_t Wmf::add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsage){ uint32_t idx; - char imagename[64]; // big enough - char xywh[64]; // big enough - int dibparams; + char imagename[64]; // big enough + char xywh[64]; // big enough + int dibparams = U_BI_UNKNOWN; // type of image not yet determined MEMPNG mempng; // PNG in memory comes back in this mempng.buffer = NULL; @@ -602,58 +456,47 @@ char *rgba_px = NULL; // RGBA pixels const char *px = NULL; // DIB pixels const U_RGBQUAD *ct = NULL; // DIB color table - int32_t width, height, colortype, numCt, invert; - if((iUsage != U_DIB_RGB_COLORS) || - !(dibparams = wget_DIB_params( // this returns pointers and values, but allocates no memory - dib, - &px, - &ct, - &numCt, - &width, - &height, - &colortype, - &invert - )) - ){ - - if(!DIB_to_RGBA( - px, // DIB pixel array - ct, // DIB color table - numCt, // DIB color table number of entries - &rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free. - width, // Width of pixel array in record - height, // Height of pixel array in record - colortype, // DIB BitCount Enumeration - numCt, // Color table used if not 0 - invert // If DIB rows are in opposite order from RGBA rows - ) && - rgba_px - ){ - toPNG( // Get the image from the RGBA px into mempng - &mempng, - width, height, // of the SRC bitmap - rgba_px - ); - free(rgba_px); + int32_t width, height, colortype, numCt, invert; // if needed these values will be set by wget_DIB_params + if(iUsage == U_DIB_RGB_COLORS){ + // next call returns pointers and values, but allocates no memory + dibparams = wget_DIB_params(dib, &px, &ct, &numCt, &width, &height, &colortype, &invert); + if(dibparams == U_BI_RGB){ + if(!DIB_to_RGBA( + px, // DIB pixel array + ct, // DIB color table + numCt, // DIB color table number of entries + &rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free. + width, // Width of pixel array in record + height, // Height of pixel array in record + colortype, // DIB BitCount Enumeration + numCt, // Color table used if not 0 + invert // If DIB rows are in opposite order from RGBA rows + )){ + toPNG( // Get the image from the RGBA px into mempng + &mempng, + width, height, // of the SRC bitmap + rgba_px + ); + free(rgba_px); + } } } - gchar *base64String; - if(dibparams == U_BI_JPEG || dibparams==U_BI_PNG){ + + gchar *base64String=NULL; + if(dibparams == U_BI_JPEG || dibparams==U_BI_PNG){ // image was binary png or jpg in source file base64String = g_base64_encode((guchar*) px, numCt ); - idx = in_images(d, (char *) base64String); } - else if(mempng.buffer){ + else if(mempng.buffer){ // image was DIB in source file, converted to png in this routine base64String = g_base64_encode((guchar*) mempng.buffer, mempng.size ); free(mempng.buffer); - idx = in_images(d, (char *) base64String); } - else { - // insert a random 3x4 blotch otherwise + else { // unknown or unsupported image type or failed conversion, insert the common bad image picture width = 3; height = 4; - base64String = g_strdup("iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII="); - idx = in_images(d, (char *) base64String); + base64String = bad_image_png(); } + + idx = in_images(d, (char *) base64String); if(!idx){ // add it if not already present - we looked at the actual data for comparison if(d->images.count == d->images.size){ enlarge_images(d); } idx = d->images.count; @@ -691,7 +534,7 @@ *(d->defs) += " "; *(d->defs) += " \n"; } - g_free(base64String); + g_free(base64String); //wait until this point to free because it might be a duplicate image return(idx-1); } @@ -709,16 +552,16 @@ mempng.buffer = NULL; char *rgba_px = NULL; // RGBA pixels - const U_RGBQUAD *ct = NULL; // color table, always NULL here + const U_RGBQUAD *ct = NULL; // color table, always NULL here int32_t width, height, colortype, numCt, invert; numCt = 0; width = Bm16.Width; // bitmap width in pixels. height = Bm16.Height; // bitmap height in scan lines. colortype = Bm16.BitsPixel; // seems to be BitCount Enumeration invert = 0; - if(colortype < 16)return(0xFFFFFFFF); // these would need a colortable if they were a dib, no idea what bm16 is supposed to do instead. + if(colortype < 16)return(U_WMR_INVALID); // these would need a colortable if they were a dib, no idea what bm16 is supposed to do instead. - if(!DIB_to_RGBA(// This is not really a dib, but close enough... + if(!DIB_to_RGBA(// This is not really a dib, but close enough so that it still works. px, // DIB pixel array ct, // DIB color table (always NULL here) numCt, // DIB color table number of entries (always 0) @@ -728,8 +571,7 @@ colortype, // DIB BitCount Enumeration numCt, // Color table used if not 0 invert // If DIB rows are in opposite order from RGBA rows - ) && rgba_px) - { + )){ toPNG( // Get the image from the RGBA px into mempng &mempng, width, height, // of the SRC bitmap @@ -737,17 +579,18 @@ ); free(rgba_px); } - gchar *base64String; - if(mempng.buffer){ + + gchar *base64String=NULL; + if(mempng.buffer){ // image was Bm16 in source file, converted to png in this routine base64String = g_base64_encode((guchar*) mempng.buffer, mempng.size ); free(mempng.buffer); } - else { - // insert a random 3x4 blotch otherwise + else { // failed conversion, insert the common bad image picture width = 3; height = 4; - base64String = g_strdup("iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII="); + base64String = bad_image_png(); } + idx = in_images(d, (char *) base64String); if(!idx){ // add it if not already present - we looked at the actual data for comparison if(d->images.count == d->images.size){ enlarge_images(d); } @@ -784,7 +627,7 @@ *(d->defs) += "\" />\n"; *(d->defs) += " \n"; } - g_free(base64String); + g_free(base64String); //wait until this point to free because it might be a duplicate image return(idx-1); } @@ -1027,6 +870,7 @@ double Wmf::pix_to_x_point(PWMF_CALLBACK_DATA d, double px, double py) { + (void) py; double x = _pix_x_to_point(d, px); return x; @@ -1035,7 +879,7 @@ double Wmf::pix_to_y_point(PWMF_CALLBACK_DATA d, double px, double py) { - + (void) px; double y = _pix_y_to_point(d, py); return y; @@ -1199,7 +1043,6 @@ const char *Bm16h; // Pointer to Bitmap16 header (px follows) const char *dib; // Pointer to DIB (void) U_WMRDIBCREATEPATTERNBRUSH_get(record, &Style, &cUsage, &Bm16h, &dib); - // Bm16 not handled yet if(dib || Bm16h){ if(dib){ tidx = add_dib_image(d, dib, cUsage); } else if(Bm16h){ @@ -1209,7 +1052,7 @@ px = Bm16h + U_SIZE_BITMAP16; tidx = add_bm16_image(d, Bm16, px); } - if(tidx == 0xFFFFFFFF){ // Problem with the image, for instance, an unsupported bitmap16 type + if(tidx == U_WMR_INVALID){ // Problem with the image, for instance, an unsupported bitmap16 type double r, g, b; r = SP_COLOR_U_TO_F( U_RGBAGetR(d->dc[d->level].textColor)); g = SP_COLOR_U_TO_F( U_RGBAGetG(d->dc[d->level].textColor)); @@ -1392,12 +1235,11 @@ double dx, double dy, double dw, double dh, int sx, int sy, int sw, int sh, uint32_t iUsage){ SVGOStringStream tmp_image; - int dibparams; + int dibparams = U_BI_UNKNOWN; // type of image not yet determined + tmp_image << "\n\t \n"; + *(d->outsvg) += tmp_image.str().c_str(); - - *(d->outsvg) += "/> \n"; *(d->path) = ""; } @@ -1507,10 +1333,9 @@ SVGOStringStream tmp_image; + tmp_image << "\n\t \n"; + *(d->outsvg) += tmp_image.str().c_str(); - - *(d->outsvg) += "/> \n"; *(d->path) = ""; } @@ -1787,7 +1609,7 @@ // incompatible change to text drawing detected (color or background change) forces out existing text // OR // next record is valid type and forces pending text to be drawn immediately - if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((wmr_mask != 0xFFFFFFFF) && (wmr_mask & U_DRAW_TEXT) && d->tri->dirty)){ + if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((wmr_mask != U_WMR_INVALID) && (wmr_mask & U_DRAW_TEXT) && d->tri->dirty)){ TR_layout_analyze(d->tri); TR_layout_2_svg(d->tri); SVGOStringStream ts; @@ -1830,7 +1652,7 @@ */ if( - (wmr_mask != 0xFFFFFFFF) && // next record is valid type + (wmr_mask != U_WMR_INVALID) && // next record is valid type (d->mask & U_DRAW_VISIBLE) && // This record is drawable ( (d->mask & U_DRAW_FORCE) || // This draw is forced by STROKE/FILL/STROKEANDFILL PATH @@ -2100,7 +1922,7 @@ int stat = wmr_arc_points(rc, ArcStart, ArcEnd,&f1, f2, ¢er, &start, &end, &size); if(!stat){ tmp_path << "\n\tM " << pix_to_xy(d, start.x, start.y); - tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0 ; + tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0; tmp_path << " "; tmp_path << 180.0 * current_rotation(d)/M_PI; tmp_path << " "; @@ -2152,7 +1974,7 @@ if(!wmr_arc_points(rc, ArcStart, ArcEnd, &f1, f2, ¢er, &start, &end, &size)){ tmp_path << "\n\tM " << pix_to_xy(d, center.x, center.y); tmp_path << "\n\tL " << pix_to_xy(d, start.x, start.y); - tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0 ; + tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0; tmp_path << " "; tmp_path << 180.0 * current_rotation(d)/M_PI; tmp_path << " "; @@ -2503,7 +2325,7 @@ int f2 = (d->arcdir == U_AD_COUNTERCLOCKWISE ? 0 : 1); if(!wmr_arc_points(rc, ArcStart, ArcEnd, &f1, f2, ¢er, &start, &end, &size)){ tmp_path << "\n\tM " << pix_to_xy(d, start.x, start.y); - tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0 ; + tmp_path << " A " << pix_to_abs_size(d, size.x)/2.0 << "," << pix_to_abs_size(d, size.y)/2.0; tmp_path << " "; tmp_path << 180.0 * current_rotation(d)/M_PI; tmp_path << " "; === modified file 'src/extension/internal/wmf-inout.h' --- src/extension/internal/wmf-inout.h 2013-08-31 16:05:13 +0000 +++ src/extension/internal/wmf-inout.h 2013-11-13 19:25:31 +0000 @@ -11,9 +11,8 @@ #ifndef SEEN_EXTENSION_INTERNAL_WMF_H #define SEEN_EXTENSION_INTERNAL_WMF_H -#define PNG_SKIP_SETJMP_CHECK // else any further png.h include blows up in the compiler -#include #include +#include "extension/internal/metafile-inout.h" // picks up PNG #include "extension/implementation/implementation.h" #include "style.h" #include "text_reassemble.h" @@ -69,35 +68,6 @@ #define WMF_MAX_DC 128 -/* - both emf-inout.h and wmf-inout.h are included by init.cpp, so whichever one goes in first defines these ommon types -*/ -#ifndef SEEN_EXTENSION_INTERNAL_METAFILECOMMON_ -#define SEEN_EXTENSION_INTERNAL_METAFILECOMMON_ -/* A coloured pixel. */ -typedef struct { - uint8_t red; - uint8_t green; - uint8_t blue; - uint8_t opacity; -} pixel_t; - -/* A picture. */ - -typedef struct { - pixel_t *pixels; - size_t width; - size_t height; -} bitmap_t; - -/* structure to store PNG image bytes */ -typedef struct { - char *buffer; - size_t size; -} MEMPNG, *PMEMPNG; -#endif - - // like this causes a mysterious crash on the return from Wmf::open //typedef struct emf_callback_data { @@ -138,7 +108,8 @@ PWMF_OBJECT wmf_obj; } WMF_CALLBACK_DATA, *PWMF_CALLBACK_DATA; -class Wmf : Inkscape::Extension::Implementation::Implementation { //This is a derived class +class Wmf : public Metafile +{ public: Wmf(); // Empty constructor @@ -158,10 +129,6 @@ private: protected: - static pixel_t *pixel_at (bitmap_t * bitmap, int x, int y); - static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); - static void toPNG(PMEMPNG accum, int width, int height, const char *px); - static uint32_t sethexcolor(U_COLORREF color); static void print_document_to_file(SPDocument *doc, const gchar *filename); static double current_scale(PWMF_CALLBACK_DATA d); static std::string current_matrix(PWMF_CALLBACK_DATA d, double x, double y, int useoffset); === modified file 'src/libuemf/uemf.h' --- src/libuemf/uemf.h 2013-10-24 21:32:31 +0000 +++ src/libuemf/uemf.h 2013-11-13 19:25:31 +0000 @@ -257,12 +257,13 @@ For U_BITMAPINFOHEADER biCompression field @{ */ -#define U_BI_RGB 0 //!< This is the only one supported by UEMF at present +#define U_BI_UNKNOWN -1 +#define U_BI_RGB 0 //!< Supported by UEMF #define U_BI_RLE8 1 #define U_BI_RLE4 2 -#define U_BI_BITFIELDS 3 -#define U_BI_JPEG 4 -#define U_BI_PNG 5 +#define U_BI_BITFIELDS 3 //!< Supported by UEMF +#define U_BI_JPEG 4 //!< Supported by UEMF +#define U_BI_PNG 5 //!< Supported by UEMF /** @} */