From 89a93a3c248c4fd116235137fffd50b192861821 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 15 Jan 2014 12:26:03 +0000 Subject: drop useless checks for hard Cairo version dependency (bzr r12933) --- src/extension/internal/cairo-ps-out.cpp | 4 ---- src/extension/internal/cairo-render-context.cpp | 4 ---- 2 files changed, 8 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp index 5f535dc64..055a30add 100644 --- a/src/extension/internal/cairo-ps-out.cpp +++ b/src/extension/internal/cairo-ps-out.cpp @@ -328,9 +328,7 @@ CairoPsOutput::init (void) "" SP_MODULE_KEY_PRINT_CAIRO_PS "\n" "\n" "<_item value='PS3'>" N_("PostScript level 3") "\n" -#if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2)) "<_item value='PS2'>" N_("PostScript level 2") "\n" -#endif "\n" "false\n" "false\n" @@ -369,9 +367,7 @@ CairoEpsOutput::init (void) "" SP_MODULE_KEY_PRINT_CAIRO_EPS "\n" "\n" "<_item value='PS3'>" N_("PostScript level 3") "\n" -#if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2)) "<_item value='PS2'>" N_("PostScript level 2") "\n" -#endif "\n" "false\n" "false\n" diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 4f9273cbb..47de62ac0 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -803,9 +803,7 @@ CairoRenderContext::setupSurface(double width, double height) #ifdef CAIRO_HAS_PDF_SURFACE case CAIRO_SURFACE_TYPE_PDF: surface = cairo_pdf_surface_create_for_stream(Inkscape::Extension::Internal::_write_callback, _stream, width, height); -#if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)) cairo_pdf_surface_restrict_to_version(surface, (cairo_pdf_version_t)_pdf_level); -#endif break; #endif #ifdef CAIRO_HAS_PS_SURFACE @@ -814,10 +812,8 @@ CairoRenderContext::setupSurface(double width, double height) if(CAIRO_STATUS_SUCCESS != cairo_surface_status(surface)) { return FALSE; } -#if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2)) cairo_ps_surface_restrict_to_level(surface, (cairo_ps_level_t)_ps_level); cairo_ps_surface_set_eps(surface, (cairo_bool_t) _eps); -#endif // Cairo calculates the bounding box itself, however we want to override this. See Launchpad bug #380501 #if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2)) // cairo_ps_dsc_comment(surface, os_bbox.str().c_str()); -- cgit v1.2.3 From 88d24fc0c21e087b6c460a0c1b58aac556c666e1 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 15 Jan 2014 17:33:48 +0100 Subject: Revert r12544. Fixes bug 1256449 (Clipping missing on Cairo-based exports). Note: 523285 is not a bug. (bzr r12935) --- src/extension/internal/cairo-renderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 0a4c86f0b..6fbc85c05 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -580,9 +580,9 @@ void CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item) setStateForItem(ctx, item); CairoRenderState *state = ctx->getCurrentState(); - state->need_layer = ( state->mask || state->opacity != 1.0 ); + state->need_layer = ( state->mask || state->clip_path || state->opacity != 1.0 ); - // Draw item on a temporary surface so a mask or opacity can be applied to it. + // Draw item on a temporary surface so a mask, clip-path, or opacity can be applied to it. if (state->need_layer) { state->merge_opacity = FALSE; ctx->pushLayer(); @@ -591,7 +591,7 @@ void CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item) sp_item_invoke_render(item, ctx); if (state->need_layer) - ctx->popLayer(); + ctx->popLayer(); // This applies clipping/masking ctx->popState(); } -- cgit v1.2.3 From 0564ac341f92d0d892d046a9096ac50fb0a9a27d Mon Sep 17 00:00:00 2001 From: David Mathog Date: Sat, 18 Jan 2014 00:24:11 +0100 Subject: libUEMF update; EMF linear gradient bug fixes (bug #1263242) Fixed bugs: - https://launchpad.net/bugs/1263242 (bzr r12953) --- src/extension/internal/Makefile_insert | 2 + src/extension/internal/emf-inout.cpp | 618 ++++++++++++++---------------- src/extension/internal/emf-inout.h | 43 +-- src/extension/internal/emf-print.cpp | 417 +++++++++++++++++--- src/extension/internal/emf-print.h | 5 + src/extension/internal/metafile-inout.cpp | 210 ++++++++++ src/extension/internal/metafile-inout.h | 93 +++++ src/extension/internal/metafile-print.cpp | 4 +- src/extension/internal/wmf-inout.cpp | 150 +------- src/extension/internal/wmf-inout.h | 39 +- src/extension/internal/wmf-print.cpp | 116 +++--- 11 files changed, 1033 insertions(+), 664 deletions(-) create mode 100644 src/extension/internal/metafile-inout.cpp create mode 100644 src/extension/internal/metafile-inout.h (limited to 'src/extension/internal') diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert index 726bca28f..a31843114 100644 --- a/src/extension/internal/Makefile_insert +++ b/src/extension/internal/Makefile_insert @@ -162,6 +162,8 @@ ink_common_sources += \ 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 \ diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index c8c708051..cca541c5b 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -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 bool clipset = false; 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; @@ -298,6 +150,7 @@ Emf::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena // reserve FixPPT2 for opacity bug. Currently EMF does not export opacity values bool new_FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); // dashed line bug bool new_FixPPTGrad2Polys = mod->get_param_bool("FixPPTGrad2Polys"); // gradient bug + bool new_FixPPTLinGrad = mod->get_param_bool("FixPPTLinGrad"); // allow native rectangular linear gradient bool new_FixPPTPatternAsHatch = mod->get_param_bool("FixPPTPatternAsHatch"); // force all patterns as standard EMF hatch bool new_FixImageRot = mod->get_param_bool("FixImageRot"); // remove rotations on images @@ -311,6 +164,7 @@ Emf::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena ext->set_param_bool("FixPPTCharPos",new_FixPPTCharPos); // Remember to add any new ones to PrintEmf::init or a mysterious failure will result! ext->set_param_bool("FixPPTDashLine",new_FixPPTDashLine); ext->set_param_bool("FixPPTGrad2Polys",new_FixPPTGrad2Polys); + ext->set_param_bool("FixPPTLinGrad",new_FixPPTLinGrad); ext->set_param_bool("FixPPTPatternAsHatch",new_FixPPTPatternAsHatch); ext->set_param_bool("FixImageRot",new_FixImageRot); ext->set_param_bool("textToPath", new_val); @@ -615,10 +469,10 @@ uint32_t Emf::add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint 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 +481,60 @@ uint32_t Emf::add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint 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 - )) - ){ + 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); + } + } - // 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); + 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 +572,7 @@ uint32_t Emf::add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint *(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 @@ -772,6 +612,115 @@ uint32_t Emf::add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint return(idx-1); } +/* Add another 100 blank slots to the gradients array. +*/ +void Emf::enlarge_gradients(PEMF_CALLBACK_DATA d){ + d->gradients.size += 100; + d->gradients.strings = (char **) realloc(d->gradients.strings,d->gradients.size * sizeof(char *)); +} + +/* See if the gradient name is already in the list. If it is return its position (1->n, not 1-n-1) +*/ +int Emf::in_gradients(PEMF_CALLBACK_DATA d, char *test){ + int i; + for(i=0; igradients.count; i++){ + if(strcmp(test,d->gradients.strings[i])==0)return(i+1); + } + return(0); +} + +U_COLORREF trivertex_to_colorref(U_TRIVERTEX tv){ + U_COLORREF uc; + uc.Red = tv.Red >> 8; + uc.Green = tv.Green >> 8; + uc.Blue = tv.Blue >> 8; + uc.Reserved = tv.Alpha >> 8; // Not used + return(uc); +} + +/* (Conditionally) add a gradient. If a matching gradient already exists nothing happens. If one + does not exist it is added to the gradients list and also entered into . + Only call this with H or V gradient, not a triangle. +*/ +uint32_t Emf::add_gradient(PEMF_CALLBACK_DATA d, uint32_t gradientType, U_TRIVERTEX tv1, U_TRIVERTEX tv2){ + char hgradname[64]; // big enough + char tmpcolor1[8]; + char tmpcolor2[8]; + char gradc; + uint32_t idx; + std::string x2,y2; + + U_COLORREF gradientColor1 = trivertex_to_colorref(tv1); + U_COLORREF gradientColor2 = trivertex_to_colorref(tv2); + + + sprintf(tmpcolor1,"%6.6X",sethexcolor(gradientColor1)); + sprintf(tmpcolor2,"%6.6X",sethexcolor(gradientColor2)); + switch(gradientType){ + case U_GRADIENT_FILL_RECT_H: + gradc='H'; + x2="100"; + y2="0"; + break; + case U_GRADIENT_FILL_RECT_V: + gradc='V'; + x2="0"; + y2="100"; + break; + default: // this should never happen, but fill these in to avoid compiler warnings + gradc='!'; + x2="0"; + y2="0"; + break; + } + + /* Even though the gradient was defined as Horizontal or Vertical if the rectangle is rotated it needs to + be at some other alignment, and that needs gradienttransform. Set the name using the same sort of hack + as for add_image. + */ + int tangle = round(current_rotation(d)*1000000.0); + sprintf(hgradname,"LinGrd%c_%s_%s_%d",gradc,tmpcolor1,tmpcolor2,tangle); + + idx = in_gradients(d,hgradname); + if(!idx){ // gradient does not yet exist + if(d->gradients.count == d->gradients.size){ enlarge_gradients(d); } + d->gradients.strings[d->gradients.count++]=strdup(hgradname); + idx = d->gradients.count; + SVGOStringStream stmp; + stmp << " \n"; + stmp << " \n"; + stmp << " \n"; + stmp << " \n"; + *(d->defs) += stmp.str().c_str(); + } + + return(idx-1); +} + + void Emf::output_style(PEMF_CALLBACK_DATA d, int iType) @@ -871,10 +820,11 @@ Emf::output_style(PEMF_CALLBACK_DATA d, int iType) snprintf(tmp, 1023, "fill:url(#%s); ",d->hatches.strings[d->dc[d->level].fill_idx]); tmp_style << tmp; break; - case DRAW_IMAGE: + case DRAW_IMAGE: snprintf(tmp, 1023, "fill:url(#EMFimage%d_ref); ",d->dc[d->level].fill_idx); tmp_style << tmp; break; + case DRAW_LINEAR_GRADIENT: case DRAW_PAINT: default: // <-- this should never happen, but just in case... snprintf( @@ -927,6 +877,7 @@ Emf::output_style(PEMF_CALLBACK_DATA d, int iType) snprintf(tmp, 1023, "stroke:url(#EMFimage%d_ref); ",d->dc[d->level].stroke_idx); tmp_style << tmp; break; + case DRAW_LINEAR_GRADIENT: case DRAW_PAINT: default: // <-- this should never happen, but just in case... snprintf( @@ -1343,7 +1294,7 @@ Emf::select_brush(PEMF_CALLBACK_DATA d, int index) 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 +1453,11 @@ void Emf::common_image_extraction(PEMF_CALLBACK_DATA d, void *pEmr, 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 outsvg) += tmp_image.str().c_str(); + tmp_image << "/> \n"; - *(d->outsvg) += "/> \n"; + *(d->outsvg) += tmp_image.str().c_str(); *(d->path) = ""; } @@ -1664,7 +1596,7 @@ int Emf::myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DA // 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 +1643,7 @@ std::cout << "BEFORE DRAW" */ 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 @@ -1726,7 +1658,7 @@ std::cout << "BEFORE DRAW" ) ){ // std::cout << "PATH DRAW at TOP" << std::endl; - *(d->outsvg) += " outsvg) += " drawtype){ // explicit draw type EMR record output_style(d, d->drawtype); } @@ -1737,7 +1669,7 @@ std::cout << "BEFORE DRAW" output_style(d, U_EMR_STROKEPATH); } *(d->outsvg) += "\n\t"; - *(d->outsvg) += "\n\td=\""; // this is the ONLY place d=" should be used!!!! + *(d->outsvg) += "\n\td=\""; // this is the ONLY place d=" should be used!!!! One exception, gradientfill. *(d->outsvg) += *(d->path); *(d->outsvg) += " \" /> \n"; *(d->path) = ""; @@ -2625,7 +2557,7 @@ std::cout << "BEFORE DRAW" 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 +2578,7 @@ std::cout << "BEFORE DRAW" 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 +2601,7 @@ std::cout << "BEFORE DRAW" 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 +2642,7 @@ std::cout << "BEFORE DRAW" 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 << " "; @@ -3332,13 +3264,64 @@ std::cout << "BEFORE DRAW" case U_EMR_SETLAYOUT: dbg_str << "\n"; break; case U_EMR_TRANSPARENTBLT: dbg_str << "\n"; break; case U_EMR_UNDEF117: dbg_str << "\n"; break; - case U_EMR_GRADIENTFILL: dbg_str << "\n"; break; - /* Gradient fill is doable for rectangles because those correspond to linear gradients. However, - the general case for the triangle fill, with a different color in each corner of the triangle, - has no SVG equivalent and cannot be easily emulated with SVG gradients. Except that so far - I (DM) have not been able to make an EMF with a rectangular gradientfill record which is not - completely toxic to other EMF readers. So far now, do nothing. - */ + case U_EMR_GRADIENTFILL: + { + /* Gradient fill is doable for rectangles because those correspond to linear gradients. However, + the general case for the triangle fill, with a different color in each corner of the triangle, + has no SVG equivalent and cannot be easily emulated with SVG gradients. So the linear gradient + is implemented, and the triangle fill just paints with the color of the first corner. + + This record can hold a series of gradients so we are forced to add path elements directly here, + it cannot wait for the top of the main loop. Any existing path is erased. + + */ + dbg_str << "\n"; + PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL) lpEMFR; + int nV = pEmr->nTriVert; // Number of TriVertex objects + int nG = pEmr->nGradObj; // Number of gradient triangle/rectangle objects + U_TRIVERTEX *tv = (U_TRIVERTEX *)(((char *)lpEMFR) + sizeof(U_EMRGRADIENTFILL)); + if( pEmr->ulMode == U_GRADIENT_FILL_RECT_H || + pEmr->ulMode == U_GRADIENT_FILL_RECT_V + ){ + SVGOStringStream tmp_rectangle; + int i,fill_idx; + U_GRADIENT4 *rcs = (U_GRADIENT4 *)(((char *)lpEMFR) + sizeof(U_EMRGRADIENTFILL) + sizeof(U_TRIVERTEX)*nV); + for(i=0;iulMode, tv[rcs[i].UpperLeft], tv[rcs[i].LowerRight]); + tmp_rectangle << "\n\tM " << pix_to_xy( d, tv[rcs[i].UpperLeft ].x , tv[rcs[i].UpperLeft ].y ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, tv[rcs[i].LowerRight].x , tv[rcs[i].UpperLeft ].y ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, tv[rcs[i].LowerRight].x , tv[rcs[i].LowerRight].y ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, tv[rcs[i].UpperLeft ].x , tv[rcs[i].LowerRight].y ) << " "; + tmp_rectangle << "\n\tz\""; + tmp_rectangle << "\n\tstyle=\"stroke:none;fill:url(#"; + tmp_rectangle << d->gradients.strings[fill_idx]; + tmp_rectangle << ");\"\n/>\n"; + } + *(d->outsvg) += tmp_rectangle.str().c_str(); + } + else if(pEmr->ulMode == U_GRADIENT_FILL_TRIANGLE){ + SVGOStringStream tmp_triangle; + char tmpcolor[8]; + int i; + U_GRADIENT3 *tris = (U_GRADIENT3 *)(((char *)lpEMFR) + sizeof(U_EMRGRADIENTFILL) + sizeof(U_TRIVERTEX)*nV); + for(i=0;i\n"; + } + *(d->outsvg) += tmp_triangle.str().c_str(); + } + *(d->path) = ""; + // if it is anything else the record is bogus, so ignore it + break; + } case U_EMR_SETLINKEDUFIS: dbg_str << "\n"; break; case U_EMR_SETTEXTJUSTIFICATION: dbg_str << "\n"; break; case U_EMR_COLORMATCHTOTARGETW: dbg_str << "\n"; break; @@ -3354,37 +3337,12 @@ std::cout << "BEFORE DRAW" } //end of while // When testing, uncomment the following to show the final SVG derived from the EMF -//std::cout << *(d->outsvg) << std::endl; +// std::cout << *(d->outsvg) << std::endl; (void) emr_properties(U_EMR_INVALID); // force the release of the lookup table memory, returned value is irrelevant return 1; } - -// Aldus Placeable Header =================================================== -// Since we are a 32bit app, we have to be sure this structure compiles to -// be identical to a 16 bit app's version. To do this, we use the #pragma -// to adjust packing, we use a uint16_t for the hmf handle, and a SMALL_RECT -// for the bbox rectangle. -#pragma pack( push ) -#pragma pack( 2 ) -typedef struct _SMALL_RECT { - int16_t Left; - int16_t Top; - int16_t Right; - int16_t Bottom; -} SMALL_RECT, *PSMALL_RECT; -typedef struct -{ - uint32_t dwKey; - uint16_t hmf; - SMALL_RECT bbox; - uint16_t wInch; - uint32_t dwReserved; - uint16_t wCheckSum; -} APMHEADER, *PAPMHEADER; -#pragma pack( pop ) - void Emf::free_emf_strings(EMF_STRINGS name){ if(name.count){ for(int i=0; i< name.count; i++){ free(name.strings[i]); } @@ -3438,6 +3396,9 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) d.images.size = 0; d.images.count = 0; d.images.strings = NULL; + d.gradients.size = 0; + d.gradients.count = 0; + d.gradients.strings = NULL; // set up the size default for patterns in defs. This might not be referenced if there are no patterns defined in the drawing. @@ -3478,6 +3439,7 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) delete d.defs; free_emf_strings(d.hatches); free_emf_strings(d.images); + free_emf_strings(d.gradients); if (d.emf_obj) { int i; @@ -3516,7 +3478,14 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) // Scale and translate objects double scale = Inkscape::Util::Quantity::convert(1, "px", doc_unit); ShapeEditor::blockSetItem(true); - doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, doc->getHeight().value("px"))); + double dh; + if(SP_ACTIVE_DOCUMENT){ // for file menu open or import, or paste from clipboard + dh = SP_ACTIVE_DOCUMENT->getHeight().value("px"); + } + else { // for open via --file on command line + dh = doc->getHeight().value("px"); + } + doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, dh)); ShapeEditor::blockSetItem(false); Inkscape::DocumentUndo::setUndoSensitive(doc, saved); @@ -3556,6 +3525,7 @@ Emf::init (void) "false\n" "false\n" "false\n" + "false\n" "false\n" "false\n" "\n" diff --git a/src/extension/internal/emf-inout.h b/src/extension/internal/emf-inout.h index 787a2fdb3..97f93e71b 100644 --- a/src/extension/internal/emf-inout.h +++ b/src/extension/internal/emf-inout.h @@ -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 @@ typedef struct emf_device_context { #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; @@ -126,6 +97,7 @@ typedef struct { // both of these end up in under the names shown here. These structures allow duplicates to be avoided. EMF_STRINGS hatches; // hold pattern names, all like EMFhatch#_$$$$$$ where # is the EMF hatch code and $$$$$$ is the color EMF_STRINGS images; // hold images, all like Image#, where # is the slot the image lives. + EMF_STRINGS gradients; // hold gradient names, all like EMF[HV]_$$$$$$_$$$$$$ where $$$$$$ are the colors TR_INFO *tri; // Text Reassembly data structure @@ -133,7 +105,8 @@ typedef struct { 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 +128,6 @@ public: 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); @@ -171,6 +139,9 @@ protected: static int in_images(PEMF_CALLBACK_DATA d, char *test); static uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t cbBmi, uint32_t iUsage, uint32_t offBits, uint32_t offBmi); + static void enlarge_gradients(PEMF_CALLBACK_DATA d); + static int in_gradients(PEMF_CALLBACK_DATA d, char *test); + static uint32_t add_gradient(PEMF_CALLBACK_DATA d, uint32_t gradientType, U_TRIVERTEX tv1, U_TRIVERTEX tv2); static void output_style(PEMF_CALLBACK_DATA d, int iType); static double _pix_x_to_point(PEMF_CALLBACK_DATA d, double px); static double _pix_y_to_point(PEMF_CALLBACK_DATA d, double py); diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 0df643130..3c27ac1b8 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -70,9 +70,8 @@ namespace Internal { /* globals */ -static double PX2WORLD = 20.0f; -static U_XFORM worldTransform; -static bool FixPPTCharPos, FixPPTDashLine, FixPPTGrad2Polys, FixPPTPatternAsHatch, FixImageRot; +static double PX2WORLD; +static bool FixPPTCharPos, FixPPTDashLine, FixPPTGrad2Polys, FixPPTLinGrad, FixPPTPatternAsHatch, FixImageRot; static EMFTRACK *et = NULL; static EMFHANDLES *eht = NULL; @@ -125,9 +124,12 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) char *rec; gchar const *utf8_fn = mod->get_param_string("destination"); + // Typially PX2WORLD is 1200/90, using inkscape's default dpi + PX2WORLD = 1200.0 / Inkscape::Util::Quantity::convert(1.0, "in", "px"); FixPPTCharPos = mod->get_param_bool("FixPPTCharPos"); FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); FixPPTGrad2Polys = mod->get_param_bool("FixPPTGrad2Polys"); + FixPPTLinGrad = mod->get_param_bool("FixPPTLinGrad"); FixPPTPatternAsHatch = mod->get_param_bool("FixPPTPatternAsHatch"); FixImageRot = mod->get_param_bool("FixImageRot"); @@ -179,12 +181,12 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) float dwInchesX = d.width(); float dwInchesY = d.height(); - // dwInchesX x dwInchesY in micrometer units, dpi=90 -> 3543.3 dpm - (void) drawing_size((int) ceil(dwInchesX * 25.4), (int) ceil(dwInchesY * 25.4), 3.543307, &rclBounds, &rclFrame); + // dwInchesX x dwInchesY in micrometer units, 1200 dpi/25.4 -> dpmm + (void) drawing_size((int) ceil(dwInchesX * 25.4), (int) ceil(dwInchesY * 25.4),1200.0/25.4, &rclBounds, &rclFrame); // set up the reference device as 100 X A4 horizontal, (1200 dpi/25.4 -> dpmm). Extra digits maintain dpi better in EMF - int MMX = 21600; - int MMY = 27900; + int MMX = 216; + int MMY = 279; (void) device_size(MMX, MMY, 1200.0 / 25.4, &szlDev, &szlMm); int PixelsX = szlDev.cx; int PixelsY = szlDev.cy; @@ -220,13 +222,16 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) } - // Correct for dpi in EMF (1200) vs dpi in Inkscape (always 90). - // Also correct for the scaling in PX2WORLD, which is set to 20. + // In earlier versions this was used to scale from inkscape's dpi of 90 to + // the files 1200 dpi, taking into account PX2WORLD which was 20. Now PX2WORLD + // is set so that this matrix is unitary. The usual value of PX2WORLD is 1200/90, + // but might be different if the internal dpi is changed. - worldTransform.eM11 = 1200. / (90.0 * PX2WORLD); + U_XFORM worldTransform; + worldTransform.eM11 = 1.0; worldTransform.eM12 = 0.0; worldTransform.eM21 = 0.0; - worldTransform.eM22 = 1200. / (90.0 * PX2WORLD); + worldTransform.eM22 = 1.0; worldTransform.eDx = 0; worldTransform.eDy = 0; @@ -420,7 +425,7 @@ int PrintEmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) hatchColor = avg_stop_color(rg); } } else if (lg) { - if (FixPPTGrad2Polys) { + if (FixPPTGrad2Polys || FixPPTLinGrad) { return hold_gradient(lg, fill_mode); } else { hatchColor = avg_stop_color(lg); @@ -696,7 +701,7 @@ int PrintEmf::create_pen(SPStyle const *style, const Geom::Affine &transform) n_dash = style->stroke_dash.n_dash; dash = new uint32_t[n_dash]; for (i = 0; i < style->stroke_dash.n_dash; i++) { - dash[i] = (uint32_t)(style->stroke_dash.dash[i]); + dash[i] = (uint32_t)(Inkscape::Util::Quantity::convert(1, "mm", "px") * style->stroke_dash.dash[i]); } } } @@ -780,6 +785,182 @@ void PrintEmf::destroy_pen() } } +/* Return a Path consisting of just the corner points of the single path in a a PathVector. If the +PathVector has more than one path, or that one path is open, or any of its segments are curved, then the +returned PathVector is . If the input path is already just straight lines and vertices the output will be the +same as the sole path in the input. */ + +Geom::Path PrintEmf::pathv_to_simple_polygon(Geom::PathVector const &pathv, int *vertices) +{ + Geom::Point P1_trail; + Geom::Point P1; + Geom::Point P1_lead; + Geom::Point v1,v2; + Geom::Path output; + Geom::Path bad; + Geom::PathVector pv = pathv_to_linear_and_cubic_beziers(pathv); + Geom::PathVector::const_iterator pit = pv.begin(); + Geom::PathVector::const_iterator pit2 = pv.begin(); + ++pit2; + *vertices = 0; + if(pit->end_closed() != pit->end_default())return(bad); // path must be closed + if(pit2 != pv.end())return(bad); // there may only be one path + P1_trail = pit->finalPoint(); + Geom::Path::const_iterator cit = pit->begin(); + P1 = cit->initialPoint(); + for(;cit != pit->end_closed();++cit) { + if (!is_straight_curve(*cit)) { + *vertices = 0; + return(bad); + } + P1_lead = cit->finalPoint(); + if(Geom::are_near(P1_lead,P1))continue; // duplicate points at the same coordinate + v1 = unit_vector(P1 - P1_trail); + v2 = unit_vector(P1_lead - P1 ); + if(Geom::are_near(dot(v1,v2),1.0)){ // P1 is within a straight line + P1 = P1_lead; + continue; + } + // P1 is the center point of a turn of some angle + if(!*vertices){ + output.start( P1 ); + output.close( pit->closed() ); + } + *vertices += 1; + Geom::LineSegment ls(P1_trail, P1); + output.append(ls); + P1_trail = P1; + P1 = P1_lead; + } + return(output); +} + +/* Returns the simplified PathVector (no matter what). + Sets is_rect if it is a rectangle. + Sets angle that will rotate side closest to horizontal onto horizontal. +*/ +Geom::Path PrintEmf::pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, double *angle) +{ + Geom::Point P1_trail; + Geom::Point P1; + Geom::Point P1_lead; + Geom::Point v1,v2; + int vertices; + Geom::Path pR = pathv_to_simple_polygon(pathv, &vertices); + *is_rect = false; + if(vertices==4){ // or else it cannot be a rectangle rectangle + int vertex_count=0; + /* Get the ends of the LAST line segment. + Find minimum rotation to align rectangle with X,Y axes. (Very degenerate if it is rotated 45 degrees.) */ + *angle = 10.0; /* must be > than the actual angle in radians. */ + for(Geom::Path::const_iterator cit = pR.begin(); cit != pR.end_open(); ++cit){ + P1_trail = cit->initialPoint(); + P1 = cit->finalPoint(); + v1 = unit_vector(P1 - P1_trail); + if(v1[Geom::X] > 0){ // only check the 1 or 2 points on vectors aimed the same direction as unit X + double ang = asin(v1[Geom::Y]); // because component is rotation by ang of {1,0| vector + if(fabs(ang) < fabs(*angle))*angle = -ang; // y increases down, flips sign on angle + } + } + + for(Geom::Path::const_iterator cit = pR.begin(); cit != pR.end_open();++cit) { + P1_lead = cit->finalPoint(); + v1 = unit_vector(P1 - P1_trail); + v2 = unit_vector(P1_lead - P1 ); + if(!Geom::are_near(dot(v1,v2),0.0))break; // P1 is center of a turn that is not 90 degrees + P1_trail = P1; + P1 = P1_lead; + vertex_count++; + } + if(vertex_count == 4){ + *is_rect=true; + } + } + return(pR); +} + +/* Compare a vector with a rectangle's orientation (angle needed to rotate side(s) + closest to horizontal to exactly horizontal) and return: + 0 none of the following + 1 parallel to horizontal + 2 parallel to vertical + 3 antiparallel to horizontal + 4 antiparallel to vertical +*/ +int PrintEmf::vector_rect_alignment(double angle, Geom::Point vtest){ + int stat = 0; + Geom::Point v1 = Geom::unit_vector(vtest); // unit vector to test alignment + Geom::Point v2 = Geom::Point(1,0) * Geom::Rotate(-angle); // unit horizontal side (sign change because Y increases DOWN) + if( Geom::are_near(dot(v1,v2), 1.0)){ stat = 1; } + else if(Geom::are_near(dot(v1,v2),-1.0)){ stat = 2; } + if(!stat){ + v2 = Geom::Point(0,1) * Geom::Rotate(-angle); // unit vertical side + if( Geom::are_near(dot(v1,v2), 1.0)){ stat = 3; } + else if(Geom::are_near(dot(v1,v2),-1.0)){ stat = 4; } + } + return(stat); +} + +/* retrieve the point at the indicated corner: + 0 UL (and default) + 1 UR + 2 LR + 3 LL + Needed because the start can be any point, and the direction could run either + clockwise or counterclockwise. This should work even if the corners of the rectangle + are slightly displaced. +*/ +Geom::Point PrintEmf::get_pathrect_corner(Geom::Path pathRect, double angle, int corner){ + Geom::Point v1 = Geom::Point(1,0) * Geom::Rotate(-angle); // unit horizontal side (sign change because Y increases DOWN) + Geom::Point v2 = Geom::Point(0,1) * Geom::Rotate(-angle); // unit vertical side (sign change because Y increases DOWN) + Geom::Point center, P1; + int LR; // 1 if Left, 0 if Right + int UL; // 1 if Lower, 0 if Upper (as viewed on screen, y coordinates increase downwards) + center = Geom::Point(0,0); + Geom::Path::const_iterator cit = pathRect.begin(); + for(; cit != pathRect.end_open();++cit) { + center += cit->initialPoint()/4.0; + } + + switch(corner){ + case 1: //UR + LR = 0; + UL = 0; + break; + case 2: //LR + LR = 0; + UL = 1; + break; + case 3: //LL + LR = 1; + UL = 1; + break; + default: //UL + LR = 1; + UL = 0; + break; + } + cit = pathRect.begin(); + for(int i; cit != pathRect.end_open();++cit,i++) { + P1 = cit->initialPoint(); + if((LR == (dot(P1 - center,v1)> 0 ? 0 : 1)) && + (UL == (dot(P1 - center,v2)> 0 ? 1 : 0)))break; + } + return(P1); +} + +U_TRIVERTEX PrintEmf::make_trivertex(Geom::Point Pt, U_COLORREF uc){ + U_TRIVERTEX tv; + using Geom::X; + using Geom::Y; + tv.x = (int32_t) round(Pt[X]); + tv.y = (int32_t) round(Pt[Y]); + tv.Red = uc.Red << 8; + tv.Green = uc.Green << 8; + tv.Blue = uc.Blue << 8; + tv.Alpha = uc.Reserved << 8; // EMF will ignore this + return(tv); +} unsigned int PrintEmf::fill( Inkscape::Extension::Print * /*mod*/, @@ -795,8 +976,27 @@ unsigned int PrintEmf::fill( use_stroke = false; fill_transform = tf; + + int brush_stat = create_brush(style, NULL); + + /* native linear gradients are only used if the object is a rectangle AND the gradient is parallel to the sides of the object */ + bool is_Rect = false; + double angle; + int rectDir=0; + Geom::Path pathRect; + if(FixPPTLinGrad && brush_stat && gv.mode == DRAW_LINEAR_GRADIENT){ + pathRect = pathv_to_rect(pathv, &is_Rect, &angle); + if(is_Rect){ + /* Gradientfill records can only be used if the gradient is parallel to the sides of the rectangle. + That must be checked here so that we can fall back to another form of gradient fill if it is not + the case. */ + rectDir = vector_rect_alignment(angle, gv.p2 - gv.p1); + if(!rectDir)is_Rect = false; + } + if(!is_Rect && !FixPPTGrad2Polys)brush_stat=0; // fall all the way back to a solid fill + } - if (create_brush(style, NULL)) { // only happens if the style is a gradient + if (brush_stat) { // only happens if the style is a gradient /* Handle gradients. Uses modified livarot as 2geom boolops is currently broken. Can handle gradients with multiple stops. @@ -819,10 +1019,10 @@ unsigned int PrintEmf::fill( SPRadialGradient *tg = (SPRadialGradient *)(gv.grad); // linear/radial are the same here nstops = tg->vector.stops.size(); sp_color_get_rgb_floatv(&tg->vector.stops[0].color, rgb); - opa = tg->vector.stops[0].opacity; + opa = tg->vector.stops[0].opacity; // first stop c1 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); sp_color_get_rgb_floatv(&tg->vector.stops[nstops - 1].color, rgb); - opa = tg->vector.stops[nstops - 1].opacity; + opa = tg->vector.stops[nstops - 1].opacity; // last stop c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); doff = 0.0; @@ -868,9 +1068,10 @@ unsigned int PrintEmf::fill( pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); print_pathv(pathvr, fill_transform); // show the intersection - if (doff >= doff_range - doff_base) { + if (doff >= doff_range) { istop++; if (istop >= nstops) { + istop = nstops - 1; continue; // could happen on a rounding error } doff_base = doff_range; @@ -882,56 +1083,145 @@ unsigned int PrintEmf::fill( } } } else if (gv.mode == DRAW_LINEAR_GRADIENT) { - Geom::Point uv = Geom::unit_vector(gv.p2 - gv.p1); // unit vector - Geom::Point puv = uv.cw(); // perp. to unit vector - double range = Geom::distance(gv.p1, gv.p2); // length along the gradient - double step = range / divisions; // adequate approximation for gradient - double overlap = step / 4.0; // overlap slices slightly - double start; - double stop; - Geom::PathVector pathvc, pathvr; - - /* before lower end of gradient, overlap first slice position */ - wc = weight_opacity(c1); - (void) create_brush(style, &wc); - pathvc = rect_cutter(gv.p1, uv * (overlap), uv * (-50000.0), puv * 50000.0); - pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); - print_pathv(pathvr, fill_transform); - - /* after high end of gradient, overlap last slice poosition */ - wc = weight_opacity(c2); - (void) create_brush(style, &wc); - pathvc = rect_cutter(gv.p2, uv * (-overlap), uv * (50000.0), puv * 50000.0); - pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); - print_pathv(pathvr, fill_transform); + if(is_Rect){ + char *rec; + int gMode; + Geom::Point ul, ur, lr; + Geom::Point outUL, outLR; // UL,LR corners of a stop rectangle, in OUTPUT coordinates + U_TRIVERTEX ut[2]; + U_GRADIENT4 ug4; + U_RECTL rcb; + Geom::Affine tf2; + U_XFORM tmpTransform; + double wRect, hRect; + + /* coordinates, w,h and transform for the ENTIRE retangle */ + ul = get_pathrect_corner(pathRect, angle, 0) * fill_transform * PX2WORLD; + ur = get_pathrect_corner(pathRect, angle, 1) * fill_transform * PX2WORLD; + lr = get_pathrect_corner(pathRect, angle, 2) * fill_transform * PX2WORLD; + wRect = Geom::distance(ul,ur); + hRect = Geom::distance(ur,lr); + + /* The basic rectangle for all of these is placed with its UL corner at 0,0 with a size wRect,hRect. + Apply a world transform to place/scale it into the appropriate position on the drawing. + Actual gradientfill records are either this entire rectangle or slices of it as defined by the stops. + */ + + tf2 = Geom::Rotate(-angle); + tmpTransform.eM11 = tf2[0]; + tmpTransform.eM12 = tf2[1]; + tmpTransform.eM21 = tf2[2]; + tmpTransform.eM22 = tf2[3]; + tmpTransform.eDx = (ul)[Geom::X]; + tmpTransform.eDy = (ul)[Geom::Y]; + + rec = U_EMRSAVEDC_set(); + if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { + g_error("Fatal programming error in PrintEmf::image at U_EMRSAVEDC_set"); + } - sp_color_get_rgb_floatv(&tg->vector.stops[istop].color, rgb); - opa = tg->vector.stops[istop].opacity; - c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); + rec = U_EMRMODIFYWORLDTRANSFORM_set(tmpTransform, U_MWT_LEFTMULTIPLY); + if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { + g_error("Fatal programming error in PrintEmf::image at EMRMODIFYWORLDTRANSFORM"); + } + + for(;istopvector.stops[istop].offset; // next or last stop + if(rectDir == 1 || rectDir == 2){ + outUL = Geom::Point(doff_base *wRect, 0 ); + outLR = Geom::Point(doff_range*wRect, hRect); + gMode = U_GRADIENT_FILL_RECT_H; + } + else { + outUL = Geom::Point(0, doff_base *hRect); + outLR = Geom::Point(wRect,doff_range*hRect); + gMode = U_GRADIENT_FILL_RECT_V; + } + doff_base = doff_range; + rcb.left = outUL[X]; + rcb.top = outUL[Y]; + rcb.right = outLR[X]; + rcb.bottom = outLR[Y]; + sp_color_get_rgb_floatv(&tg->vector.stops[istop].color, rgb); + opa = tg->vector.stops[istop].opacity; + c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); + + if(rectDir == 2 || rectDir == 4){ // gradient is reversed, so swap colors + ut[0] = make_trivertex(outUL, c2); + ut[1] = make_trivertex(outLR, c1); + } + else { + ut[0] = make_trivertex(outUL, c1); + ut[1] = make_trivertex(outLR, c2); + } + c1 = c2; // for next stop + ug4.UpperLeft = 0; + ug4.LowerRight= 1; + /* NEED to push world transform here for rotations */ + rec = U_EMRGRADIENTFILL_set(rcb, 2, 1, gMode, ut, (uint32_t *) &ug4 ); + if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { + g_error("Fatal programming error in PrintEmf::fill at U_EMRGRADIENTFILL_set"); + } + } - for (start = 0.0; start < range; start += step, doff += 1. / divisions) { - stop = start + step + overlap; - if (stop > range) { - stop = range; + rec = U_EMRRESTOREDC_set(-1); + if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { + g_error("Fatal programming error in PrintEmf::fill at U_EMRRESTOREDC_set"); } - pathvc = rect_cutter(gv.p1, uv * start, uv * stop, puv * 50000.0); + } + else { + Geom::Point uv = Geom::unit_vector(gv.p2 - gv.p1); // unit vector + Geom::Point puv = uv.cw(); // perp. to unit vector + double range = Geom::distance(gv.p1, gv.p2); // length along the gradient + double step = range / divisions; // adequate approximation for gradient + double overlap = step / 4.0; // overlap slices slightly + double start; + double stop; + Geom::PathVector pathvc, pathvr; + + /* before lower end of gradient, overlap first slice position */ + wc = weight_opacity(c1); + (void) create_brush(style, &wc); + pathvc = rect_cutter(gv.p1, uv * (overlap), uv * (-50000.0), puv * 50000.0); + pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); + print_pathv(pathvr, fill_transform); - wc = weight_colors(c1, c2, (doff - doff_base) / (doff_range - doff_base)); + /* after high end of gradient, overlap last slice position */ + wc = weight_opacity(c2); (void) create_brush(style, &wc); - Geom::PathVector pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); - print_pathv(pathvr, fill_transform); // show the intersection + pathvc = rect_cutter(gv.p2, uv * (-overlap), uv * (50000.0), puv * 50000.0); + pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); + print_pathv(pathvr, fill_transform); - if (doff >= doff_range - doff_base) { - istop++; - if (istop >= nstops) { - continue; // could happen on a rounding error + sp_color_get_rgb_floatv(&tg->vector.stops[istop].color, rgb); + opa = tg->vector.stops[istop].opacity; + c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); + + for (start = 0.0; start < range; start += step, doff += 1. / divisions) { + stop = start + step + overlap; + if (stop > range) { + stop = range; + } + pathvc = rect_cutter(gv.p1, uv * start, uv * stop, puv * 50000.0); + + wc = weight_colors(c1, c2, (doff - doff_base) / (doff_range - doff_base)); + (void) create_brush(style, &wc); + Geom::PathVector pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); + print_pathv(pathvr, fill_transform); // show the intersection + + if (doff >= doff_range) { + istop++; + if (istop >= nstops) { + istop = nstops - 1; + continue; // could happen on a rounding error + } + doff_base = doff_range; + doff_range = tg->vector.stops[istop].offset; // next or last stop + c1 = c2; + sp_color_get_rgb_floatv(&tg->vector.stops[istop].color, rgb); + opa = tg->vector.stops[istop].opacity; + c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); } - doff_base = doff_range; - doff_range = tg->vector.stops[istop].offset; // next or last stop - c1 = c2; - sp_color_get_rgb_floatv(&tg->vector.stops[istop].color, rgb); - opa = tg->vector.stops[istop].opacity; - c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); } } } else { @@ -1301,6 +1591,10 @@ unsigned int PrintEmf::image( U_POINTL cDest = pointl_set(round(dw * PX2WORLD), round(dh * PX2WORLD)); U_POINTL Src = pointl_set(0, 0); U_POINTL cSrc = pointl_set(w, h); + /* map the integer Dest coordinates back into pLL2, so that the rounded part does not destabilize the transform offset below */ + pLL2[Geom::X] = Dest.x; + pLL2[Geom::Y] = Dest.y; + pLL2 /= PX2WORLD; if (!FixImageRot) { /* Rotate images - some programs cannot read them in correctly if they are rotated */ tf[4] = tf[5] = 0.0; // get rid of the offset in the transform Geom::Point pLL2prime = pLL2 * tf; @@ -1309,7 +1603,7 @@ unsigned int PrintEmf::image( tmpTransform.eM12 = tf[1]; tmpTransform.eM21 = tf[2]; tmpTransform.eM22 = tf[3]; - tmpTransform.eDx = (pLL2[Geom::X] - pLL2prime[Geom::X]) * PX2WORLD; //map pLL2 (now in EMF coordinates) back onto itself after the rotation + tmpTransform.eDx = (pLL2[Geom::X] - pLL2prime[Geom::X]) * PX2WORLD; tmpTransform.eDy = (pLL2[Geom::Y] - pLL2prime[Geom::Y]) * PX2WORLD; rec = U_EMRSAVEDC_set(); @@ -1734,6 +2028,7 @@ void PrintEmf::init(void) "false\n" "false\n" "false\n" + "false\n" "false\n" "false\n" "\n" diff --git a/src/extension/internal/emf-print.h b/src/extension/internal/emf-print.h index 1546fcaea..8fc9908e3 100644 --- a/src/extension/internal/emf-print.h +++ b/src/extension/internal/emf-print.h @@ -68,6 +68,11 @@ public: protected: static void smuggle_adxkyrtl_out(const char *string, uint32_t **adx, double *ky, int *rtl, int *ndx, float scale); + Geom::Path pathv_to_simple_polygon(Geom::PathVector const &pathv, int *vertices); + Geom::Path pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, double *angle); + Geom::Point get_pathrect_corner(Geom::Path pathRect, double angle, int corner); + U_TRIVERTEX make_trivertex(Geom::Point Pt, U_COLORREF uc); + int vector_rect_alignment(double angle, Geom::Point vtest); int create_brush(SPStyle const *style, PU_COLORREF fcolor); void destroy_brush(); int create_pen(SPStyle const *style, const Geom::Affine &transform); diff --git a/src/extension/internal/metafile-inout.cpp b/src/extension/internal/metafile-inout.cpp new file mode 100644 index 000000000..c7ae53370 --- /dev/null +++ b/src/extension/internal/metafile-inout.cpp @@ -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 : diff --git a/src/extension/internal/metafile-inout.h b/src/extension/internal/metafile-inout.h new file mode 100644 index 000000000..968773a3a --- /dev/null +++ b/src/extension/internal/metafile-inout.h @@ -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: +*/ diff --git a/src/extension/internal/metafile-print.cpp b/src/extension/internal/metafile-print.cpp index 1e7735410..73d63f27d 100644 --- a/src/extension/internal/metafile-print.cpp +++ b/src/extension/internal/metafile-print.cpp @@ -187,7 +187,6 @@ U_COLORREF PrintMetafile::avg_stop_color(SPGradient *gr) return cr; } -#define clrweight(a,b,t) ((1-t)*((double) a) + (t)*((double) b)) U_COLORREF PrintMetafile::weight_opacity(U_COLORREF c1) { float opa = c1.Reserved / 255.0; @@ -199,9 +198,12 @@ U_COLORREF PrintMetafile::weight_opacity(U_COLORREF c1) return result; } +/* t between 0 and 1, values outside that range use the nearest limit */ U_COLORREF PrintMetafile::weight_colors(U_COLORREF c1, U_COLORREF c2, double t) { +#define clrweight(a,b,t) ((1-t)*((double) a) + (t)*((double) b)) U_COLORREF result; + t = ( t > 1.0 ? 1.0 : ( t < 0.0 ? 0.0 : t)); result.Red = clrweight(c1.Red, c2.Red, t); result.Green = clrweight(c1.Green, c2.Green, t); result.Blue = clrweight(c1.Blue, c2.Blue, t); diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 870e4061c..a72c16a88 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -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 U_RECT16 rc_old; 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; diff --git a/src/extension/internal/wmf-inout.h b/src/extension/internal/wmf-inout.h index 90f424c46..3d23ca749 100644 --- a/src/extension/internal/wmf-inout.h +++ b/src/extension/internal/wmf-inout.h @@ -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 @@ typedef struct wmf_device_context { #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 @@ typedef struct { 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 @@ public: 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); diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp index d60b2adf7..1c7b42c82 100644 --- a/src/extension/internal/wmf-print.cpp +++ b/src/extension/internal/wmf-print.cpp @@ -76,7 +76,7 @@ namespace Internal { /* globals */ -static double PX2WORLD = 1200.0 / 90.0; // inkscape is 90 dpi, WMF file is 1200 +static double PX2WORLD; // value set in begin() static bool FixPPTCharPos, FixPPTDashLine, FixPPTGrad2Polys, FixPPTPatternAsHatch; static WMFTRACK *wt = NULL; static WMFHANDLES *wht = NULL; @@ -128,6 +128,8 @@ unsigned int PrintWmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) char *rec; gchar const *utf8_fn = mod->get_param_string("destination"); + // Typically PX2WORLD is 1200/90, using inkscape's default dpi + PX2WORLD = 1200.0 / Inkscape::Util::Quantity::convert(1.0, "in", "px"); FixPPTCharPos = mod->get_param_bool("FixPPTCharPos"); FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); FixPPTGrad2Polys = mod->get_param_bool("FixPPTGrad2Polys"); @@ -188,39 +190,39 @@ unsigned int PrintWmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) int dwPxY = round(d.height() * 1200.0); #endif - PU_PAIRF ps = U_PAIRF_set(dwInchesX, dwInchesY); + U_PAIRF *ps = U_PAIRF_set(dwInchesX, dwInchesY); rec = U_WMRHEADER_set(ps, 1200); // Example: drawing is A4 horizontal, 1200 dpi if (!rec) { g_error("Fatal programming error in PrintWmf::begin at WMRSETMAPMODE"); } - (void) wmf_header_append((PU_METARECORD)rec, wt, 1); + (void) wmf_header_append((U_METARECORD *)rec, wt, 1); free(ps); rec = U_WMRSETWINDOWEXT_set(point16_set(dwPxX, dwPxY)); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at WMRSETWINDOWEXT"); } rec = U_WMRSETWINDOWORG_set(point16_set(0, 0)); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at WMRSETWINDOWORG"); } rec = U_WMRSETMAPMODE_set(U_MM_ANISOTROPIC); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at WMRSETMAPMODE"); } /* set some parameters, else the program that reads the WMF may default to other values */ rec = U_WMRSETBKMODE_set(U_TRANSPARENT); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at U_WMRSETBKMODE"); } hpolyfillmode = U_WINDING; rec = U_WMRSETPOLYFILLMODE_set(U_WINDING); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at U_WMRSETPOLYFILLMODE"); } @@ -229,24 +231,24 @@ unsigned int PrintWmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) // actually starts, and already takes into account the text object's alignment; // - for this reason, the WMF text alignment must always be TA_BASELINE|TA_LEFT. rec = U_WMRSETTEXTALIGN_set(U_TA_BASELINE | U_TA_LEFT); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at U_WMRSETTEXTALIGN_set"); } htextcolor_rgb[0] = htextcolor_rgb[1] = htextcolor_rgb[2] = 0.0; rec = U_WMRSETTEXTCOLOR_set(U_RGB(0, 0, 0)); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at U_WMRSETTEXTCOLOR_set"); } rec = U_WMRSETROP2_set(U_R2_COPYPEN); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at U_WMRSETROP2"); } hmiterlimit = 5; rec = wmiterlimit_set(5); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at wmiterlimit_set"); } @@ -255,14 +257,14 @@ unsigned int PrintWmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) U_PEN up = U_PEN_set(U_PS_SOLID, 1, colorref_set(0, 0, 0)); uint32_t Pen; rec = wcreatepenindirect_set(&Pen, wht, up); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at wcreatepenindirect_set"); } // create a null pen. If no specific pen is set, this is used up = U_PEN_set(U_PS_NULL, 1, colorref_set(0, 0, 0)); rec = wcreatepenindirect_set(&hpen_null, wht, up); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at wcreatepenindirect_set"); } destroy_pen(); // make this pen active @@ -270,7 +272,7 @@ unsigned int PrintWmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) // create a null brush. If no specific brush is set, this is used U_WLOGBRUSH lb = U_WLOGBRUSH_set(U_BS_NULL, U_RGB(0, 0, 0), U_HS_HORIZONTAL); rec = wcreatebrushindirect_set(&hbrush_null, wht, lb); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::begin at wcreatebrushindirect_set"); } destroy_brush(); // make this brush active @@ -288,25 +290,25 @@ unsigned int PrintWmf::finish(Inkscape::Extension::Print * /*mod*/) // get rid of null brush rec = wdeleteobject_set(&hbrush_null, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::finish at wdeleteobject_set null brush"); } // get rid of null pen rec = wdeleteobject_set(&hpen_null, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::finish at wdeleteobject_set null pen"); } // get rid of object 0, which was a pen that was used to shift the other object indices to >=1. hpen = 0; rec = wdeleteobject_set(&hpen, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::finish at wdeleteobject_set filler object"); } rec = U_WMREOF_set(); // generate the EOF record - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::finish"); } (void) wmf_finish(wt); // Finalize and write out the WMF @@ -330,7 +332,7 @@ unsigned int PrintWmf::comment(Inkscape::Extension::Print * /*module*/, const ch // fcolor is defined when gradients are being expanded, it is the color of one stripe or ring. -int PrintWmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) +int PrintWmf::create_brush(SPStyle const *style, U_COLORREF *fcolor) { float rgb[3]; char *rec; @@ -442,17 +444,17 @@ int PrintWmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) // SVG text has no background attribute, so OPAQUE mode ALWAYS cancels after the next draw, otherwise it would mess up future text output. if (usebk) { rec = U_WMRSETBKCOLOR_set(bkColor); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_brush at U_WMRSETBKCOLOR_set"); } rec = U_WMRSETBKMODE_set(U_OPAQUE); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_brush at U_WMRSETBKMODE_set"); } } lb = U_WLOGBRUSH_set(brushStyle, hatchColor, hatchType); rec = wcreatebrushindirect_set(&brush, wht, lb); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_brush at createbrushindirect_set"); } break; @@ -461,10 +463,10 @@ int PrintWmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) char *rgba_px; uint32_t cbPx; uint32_t colortype; - PU_RGBQUAD ct; + U_RGBQUAD *ct; int numCt; U_BITMAPINFOHEADER Bmih; - PU_BITMAPINFO Bmi; + U_BITMAPINFO *Bmi; rgba_px = (char *) pixbuf->pixels(); // Do NOT free this!!! colortype = U_BCBM_COLOR32; (void) RGBA_to_DIB(&px, &cbPx, &ct, &numCt, rgba_px, width, height, width * 4, colortype, 0, 1); @@ -474,7 +476,7 @@ int PrintWmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) Bmih = bitmapinfoheader_set(width, height, 1, colortype, U_BI_RGB, 0, PXPERMETER, PXPERMETER, numCt, 0); Bmi = bitmapinfo_set(Bmih, ct); rec = wcreatedibpatternbrush_srcdib_set(&brush, wht, U_DIB_RGB_COLORS, Bmi, cbPx, px); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_brush at createdibpatternbrushpt_set"); } free(px); @@ -484,14 +486,14 @@ int PrintWmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) hbrush = brush; // need this later for destroy_brush rec = wselectobject_set(brush, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_brush at wselectobject_set"); } if (fmode != hpolyfillmode) { hpolyfillmode = fmode; rec = U_WMRSETPOLYFILLMODE_set(fmode); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_brush at U_WMRSETPOLYFILLMODE_set"); } } @@ -506,7 +508,7 @@ void PrintWmf::destroy_brush() // WMF lets any object be deleted whenever, and the chips fall where they may... if (hbrush) { rec = wdeleteobject_set(&hbrush, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::destroy_brush"); } hbrush = 0; @@ -515,7 +517,7 @@ void PrintWmf::destroy_brush() // (re)select the null brush rec = wselectobject_set(hbrush_null, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::destroy_brush"); } } @@ -583,7 +585,7 @@ int PrintWmf::create_pen(SPStyle const *style, const Geom::Affine &transform) if ((uint32_t)miterlimit != hmiterlimit) { hmiterlimit = (uint32_t)miterlimit; rec = wmiterlimit_set((uint32_t) miterlimit); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_pen at wmiterlimit_set"); } } @@ -605,12 +607,12 @@ int PrintWmf::create_pen(SPStyle const *style, const Geom::Affine &transform) up = U_PEN_set(penstyle | modstyle, linewidth, penColor); rec = wcreatepenindirect_set(&pen, wht, up); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_pen at wcreatepenindirect_set"); } rec = wselectobject_set(pen, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::create_pen at wselectobject_set"); } hpen = pen; // need this later for destroy_pen @@ -625,7 +627,7 @@ void PrintWmf::destroy_pen() // WMF lets any object be deleted whenever, and the chips fall where they may... if (hpen) { rec = wdeleteobject_set(&hpen, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::destroy_pen"); } hpen = 0; @@ -634,7 +636,7 @@ void PrintWmf::destroy_pen() // (re)select the null pen rec = wselectobject_set(hpen_null, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::destroy_pen"); } } @@ -757,7 +759,7 @@ unsigned int PrintWmf::fill( pathvr = sp_pathvector_boolop(pathvc, pathv, bool_op_inters, (FillRule) fill_nonZero, frb); print_pathv(pathvr, fill_transform); - /* after high end of gradient, overlap last slice poosition */ + /* after high end of gradient, overlap last slice position */ wc = weight_opacity(c2); (void) create_brush(style, &wc); pathvc = rect_cutter(gv.p2, uv * (-overlap), uv * (50000.0), puv * 50000.0); @@ -898,7 +900,7 @@ unsigned int PrintWmf::stroke( if (usebk) { // OPAQUE was set, revert to TRANSPARENT usebk = false; rec = U_WMRSETBKMODE_set(U_TRANSPARENT); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::stroke at U_WMRSETBKMODE_set"); } } @@ -1066,7 +1068,7 @@ bool PrintWmf::print_simple_shape(Geom::PathVector const &pathv, const Geom::Aff }); rec = U_WMRELLIPSE_set(rcl); } - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::print_simple_shape at retangle/ellipse/polygon"); } @@ -1109,7 +1111,7 @@ unsigned int PrintWmf::image( Geom::Affine tf = m_tr_stack.top(); rec = U_WMRSETSTRETCHBLTMODE_set(U_COLORONCOLOR); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::image at EMRHEADER"); } @@ -1126,10 +1128,10 @@ unsigned int PrintWmf::image( char *px; uint32_t cbPx; uint32_t colortype; - PU_RGBQUAD ct; + U_RGBQUAD *ct; int numCt; U_BITMAPINFOHEADER Bmih; - PU_BITMAPINFO Bmi; + U_BITMAPINFO *Bmi; colortype = U_BCBM_COLOR32; (void) RGBA_to_DIB(&px, &cbPx, &ct, &numCt, (char *) rgba_px, w, h, w * 4, colortype, 0, 1); Bmih = bitmapinfoheader_set(w, h, 1, colortype, U_BI_RGB, 0, PXPERMETER, PXPERMETER, numCt, 0); @@ -1150,7 +1152,7 @@ unsigned int PrintWmf::image( h * rs, //! size in bytes of px px //! (Optional) bitmapbuffer (U_BITMAPINFO section) ); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::image at U_WMRSTRETCHDIB_set"); } free(px); @@ -1165,7 +1167,7 @@ unsigned int PrintWmf::image( unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform) { char *rec = NULL; - PU_POINT16 pt16hold, pt16ptr; + U_POINT16 *pt16hold, *pt16ptr; uint16_t *n16hold; uint16_t *n16ptr; @@ -1199,7 +1201,7 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af } if (nPolys > 1) { // a single polypolygon, a single polygon falls through to the else - pt16hold = pt16ptr = (PU_POINT16) malloc(totPoints * sizeof(U_POINT16)); + pt16hold = pt16ptr = (U_POINT16 *) malloc(totPoints * sizeof(U_POINT16)); if (!pt16ptr) { return(false); } @@ -1235,7 +1237,7 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af } rec = U_WMRPOLYPOLYGON_set(nPolys, n16hold, pt16hold); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRPOLYPOLYGON_set"); } free(pt16hold); @@ -1256,7 +1258,7 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af */ int nPoints = 1 + pit->size_default(); - pt16hold = pt16ptr = (PU_POINT16) malloc(nPoints * sizeof(U_POINT16)); + pt16hold = pt16ptr = (U_POINT16 *) malloc(nPoints * sizeof(U_POINT16)); if (!pt16ptr) { break; } @@ -1280,21 +1282,21 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af if (pit->end_default() == pit->end_closed()) { rec = U_WMRPOLYGON_set(nPoints, pt16hold); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRPOLYGON_set"); } } else if (nPoints > 2) { rec = U_WMRPOLYLINE_set(nPoints, pt16hold); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::print_pathv at U_POLYLINE_set"); } } else if (nPoints == 2) { rec = U_WMRMOVETO_set(pt16hold[0]); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRMOVETO_set"); } rec = U_WMRLINETO_set(pt16hold[1]); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRLINETO_set"); } } @@ -1348,7 +1350,7 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te if (textalignment != htextalignment) { htextalignment = textalignment; rec = U_WMRSETTEXTALIGN_set(textalignment); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::text at U_WMRSETTEXTALIGN_set"); } } @@ -1420,7 +1422,7 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te // it was streteched asymmetrically.) Few applications support text from WMF which is scaled // differently by height/width, so leave lfWidth alone. - PU_FONT puf = U_FONT_set( + U_FONT *puf = U_FONT_set( textheight, 0, round(rot), @@ -1438,14 +1440,14 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te free(facename); rec = wcreatefontindirect_set(&hfont, wht, puf); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::text at wcreatefontindirect_set"); } free(puf); } rec = wselectobject_set(hfont, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::text at wselectobject_set"); } @@ -1455,7 +1457,7 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te if (memcmp(htextcolor_rgb, rgb, 3 * sizeof(float))) { memcpy(htextcolor_rgb, rgb, 3 * sizeof(float)); rec = U_WMRSETTEXTCOLOR_set(U_RGB(255 * rgb[0], 255 * rgb[1], 255 * rgb[2])); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::text at U_WMRSETTEXTCOLOR_set"); } } @@ -1522,12 +1524,12 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te } free(latin1_text); free(adx); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::text at U_WMREXTTEXTOUTW_set"); } rec = wdeleteobject_set(&hfont, wht); - if (!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)) { + if (!rec || wmf_append((U_METARECORD *)rec, wt, U_REC_FREE)) { g_error("Fatal programming error in PrintWmf::text at wdeleteobject_set"); } -- cgit v1.2.3 From 61737a54a16f2434f26b1ccfa5e1e082464d65c0 Mon Sep 17 00:00:00 2001 From: David Mathog Date: Wed, 22 Jan 2014 00:44:34 +0100 Subject: EMF export: fix handling of transformed rectangular gradients (bug #1263242) Fixed bugs: - https://launchpad.net/bugs/1263242 (bzr r12968) --- src/extension/internal/emf-print.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 3c27ac1b8..2680718cf 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -814,10 +814,10 @@ Geom::Path PrintEmf::pathv_to_simple_polygon(Geom::PathVector const &pathv, int return(bad); } P1_lead = cit->finalPoint(); - if(Geom::are_near(P1_lead,P1))continue; // duplicate points at the same coordinate + if(Geom::are_near(P1_lead, P1, 1e-5))continue; // duplicate points at the same coordinate v1 = unit_vector(P1 - P1_trail); v2 = unit_vector(P1_lead - P1 ); - if(Geom::are_near(dot(v1,v2),1.0)){ // P1 is within a straight line + if(Geom::are_near(dot(v1,v2), 1.0, 1e-5)){ // P1 is within a straight line P1 = P1_lead; continue; } @@ -867,7 +867,7 @@ Geom::Path PrintEmf::pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, P1_lead = cit->finalPoint(); v1 = unit_vector(P1 - P1_trail); v2 = unit_vector(P1_lead - P1 ); - if(!Geom::are_near(dot(v1,v2),0.0))break; // P1 is center of a turn that is not 90 degrees + if(!Geom::are_near(dot(v1,v2), 0.0, 1e-5))break; // P1 is center of a turn that is not 90 degrees P1_trail = P1; P1 = P1_lead; vertex_count++; @@ -891,12 +891,12 @@ int PrintEmf::vector_rect_alignment(double angle, Geom::Point vtest){ int stat = 0; Geom::Point v1 = Geom::unit_vector(vtest); // unit vector to test alignment Geom::Point v2 = Geom::Point(1,0) * Geom::Rotate(-angle); // unit horizontal side (sign change because Y increases DOWN) - if( Geom::are_near(dot(v1,v2), 1.0)){ stat = 1; } - else if(Geom::are_near(dot(v1,v2),-1.0)){ stat = 2; } + if( Geom::are_near(dot(v1,v2), 1.0, 1e-5)){ stat = 1; } + else if(Geom::are_near(dot(v1,v2),-1.0, 1e-5)){ stat = 2; } if(!stat){ v2 = Geom::Point(0,1) * Geom::Rotate(-angle); // unit vertical side - if( Geom::are_near(dot(v1,v2), 1.0)){ stat = 3; } - else if(Geom::are_near(dot(v1,v2),-1.0)){ stat = 4; } + if( Geom::are_near(dot(v1,v2), 1.0, 1e-5)){ stat = 3; } + else if(Geom::are_near(dot(v1,v2),-1.0, 1e-5)){ stat = 4; } } return(stat); } @@ -1091,7 +1091,6 @@ unsigned int PrintEmf::fill( U_TRIVERTEX ut[2]; U_GRADIENT4 ug4; U_RECTL rcb; - Geom::Affine tf2; U_XFORM tmpTransform; double wRect, hRect; @@ -1107,7 +1106,8 @@ unsigned int PrintEmf::fill( Actual gradientfill records are either this entire rectangle or slices of it as defined by the stops. */ - tf2 = Geom::Rotate(-angle); + Geom::Affine tf2 = Geom::Rotate(-angle); // the rectangle may be drawn skewed to the coordinate system + tf2 *= tf; // the coordinate system of the rectangular path may be rotated tmpTransform.eM11 = tf2[0]; tmpTransform.eM12 = tf2[1]; tmpTransform.eM21 = tf2[2]; -- cgit v1.2.3 From ec4c32a8921fc72e855f2ca8ec608af499dc34d2 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 7 Feb 2014 21:08:10 +0100 Subject: Fix for Bug #1275443 (Including picture results in crash). Fixed bugs: - https://launchpad.net/bugs/1275443 (bzr r13006) --- src/extension/internal/image-resolution.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/extension/internal') diff --git a/src/extension/internal/image-resolution.cpp b/src/extension/internal/image-resolution.cpp index aee46aaba..18eb97f80 100644 --- a/src/extension/internal/image-resolution.cpp +++ b/src/extension/internal/image-resolution.cpp @@ -322,6 +322,12 @@ void ImageResolution::readjfif(char const *fn) { y_ = cinfo.Y_density * 2.54; ok_ = true; } + /* According to http://www.jpeg.org/public/jfif.pdf (page 7): + * "Xdensity and Ydensity should always be non-zero". + * but in some cases, they are (see LP bug #1275443) */ + if (x_ == 0 or y_ == 0) { + ok_ = false; + } } jpeg_destroy_decompress(&cinfo); fclose(ifd); -- cgit v1.2.3 From 042cc81dd7c3ca2f0d42b68356f4b450074c8473 Mon Sep 17 00:00:00 2001 From: David Mathog Date: Sat, 8 Feb 2014 08:17:30 +0100 Subject: EMF/WMF support: Various changes (see bug #1263242 c35 for details) EMF support: - linear gradients: improve numeric stability on round-trip editing - linear gradients: fix scaling issue libTERE/text_reassemble update: - improve handling of whitespace created with large x kerns - fix handling of absolute RTL-positioning of LTR text in EMF files WMF support: - fix support for 'textout' records and Placeable headers - add support for CREATEPATTERNBRUSH - fix offset on load if opened via GUI (bug #1250250) Fixed bugs: - https://launchpad.net/bugs/1263242 - https://launchpad.net/bugs/1250250 (bzr r13008) --- src/extension/internal/emf-inout.cpp | 2 + src/extension/internal/emf-inout.h | 1 + src/extension/internal/emf-print.cpp | 40 +++++---- src/extension/internal/emf-print.h | 3 +- src/extension/internal/text_reassemble.c | 137 ++++++++++++++++++++----------- src/extension/internal/text_reassemble.h | 7 +- src/extension/internal/wmf-inout.cpp | 44 +++++++++- 7 files changed, 163 insertions(+), 71 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index cca541c5b..276dee362 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -4,6 +4,7 @@ /* Authors: * Ulf Erikson * Jon A. Cruz + * David Mathog * Abhishek Sharma * * Copyright (C) 2006-2008 Authors @@ -1563,6 +1564,7 @@ int Emf::myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DA tsp.vadvance = 0.0; /* meaningful only when a complex contains two or more lines */ tsp.taln = ALILEFT + ALIBASE; tsp.ldir = LDIR_LR; + tsp.spaces = 0; // this field is only used for debugging tsp.color.Red = 0; /* RGB Black */ tsp.color.Green = 0; /* RGB Black */ tsp.color.Blue = 0; /* RGB Black */ diff --git a/src/extension/internal/emf-inout.h b/src/extension/internal/emf-inout.h index 97f93e71b..a97cb0a54 100644 --- a/src/extension/internal/emf-inout.h +++ b/src/extension/internal/emf-inout.h @@ -3,6 +3,7 @@ */ /* Authors: * Ulf Erikson + * David Mathog * * Copyright (C) 2006-2008 Authors * diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 2680718cf..6d5bb6f4b 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -124,7 +124,7 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) char *rec; gchar const *utf8_fn = mod->get_param_string("destination"); - // Typially PX2WORLD is 1200/90, using inkscape's default dpi + // Typically PX2WORLD is 1200/90, using inkscape's default dpi PX2WORLD = 1200.0 / Inkscape::Util::Quantity::convert(1.0, "in", "px"); FixPPTCharPos = mod->get_param_bool("FixPPTCharPos"); FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); @@ -848,7 +848,7 @@ Geom::Path PrintEmf::pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, int vertices; Geom::Path pR = pathv_to_simple_polygon(pathv, &vertices); *is_rect = false; - if(vertices==4){ // or else it cannot be a rectangle rectangle + if(vertices==4){ // or else it cannot be a rectangle int vertex_count=0; /* Get the ends of the LAST line segment. Find minimum rotation to align rectangle with X,Y axes. (Very degenerate if it is rotated 45 degrees.) */ @@ -862,12 +862,17 @@ Geom::Path PrintEmf::pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, if(fabs(ang) < fabs(*angle))*angle = -ang; // y increases down, flips sign on angle } } + + /* For increased numerical stability, snap the angle to the nearest 1/100th of a degree. */ + double convert = 36000.0/ (2.0 * M_PI); + *angle = round(*angle * convert)/convert; for(Geom::Path::const_iterator cit = pR.begin(); cit != pR.end_open();++cit) { P1_lead = cit->finalPoint(); v1 = unit_vector(P1 - P1_trail); v2 = unit_vector(P1_lead - P1 ); - if(!Geom::are_near(dot(v1,v2), 0.0, 1e-5))break; // P1 is center of a turn that is not 90 degrees + // P1 is center of a turn that is not 90 degrees. Limit comes from cos(89.9) = .001745 + if(!Geom::are_near(dot(v1,v2), 0.0, 2e-3))break; P1_trail = P1; P1 = P1_lead; vertex_count++; @@ -985,12 +990,13 @@ unsigned int PrintEmf::fill( int rectDir=0; Geom::Path pathRect; if(FixPPTLinGrad && brush_stat && gv.mode == DRAW_LINEAR_GRADIENT){ - pathRect = pathv_to_rect(pathv, &is_Rect, &angle); + Geom::PathVector pvr = pathv * fill_transform; + pathRect = pathv_to_rect(pvr, &is_Rect, &angle); if(is_Rect){ /* Gradientfill records can only be used if the gradient is parallel to the sides of the rectangle. That must be checked here so that we can fall back to another form of gradient fill if it is not the case. */ - rectDir = vector_rect_alignment(angle, gv.p2 - gv.p1); + rectDir = vector_rect_alignment(angle, (gv.p2 - gv.p1) * fill_transform); if(!rectDir)is_Rect = false; } if(!is_Rect && !FixPPTGrad2Polys)brush_stat=0; // fall all the way back to a solid fill @@ -1094,26 +1100,27 @@ unsigned int PrintEmf::fill( U_XFORM tmpTransform; double wRect, hRect; - /* coordinates, w,h and transform for the ENTIRE retangle */ - ul = get_pathrect_corner(pathRect, angle, 0) * fill_transform * PX2WORLD; - ur = get_pathrect_corner(pathRect, angle, 1) * fill_transform * PX2WORLD; - lr = get_pathrect_corner(pathRect, angle, 2) * fill_transform * PX2WORLD; + /* coordinates: upper left, upper right, and lower right corners of the rectangle. + inkscape transform already applied, but needs to be scaled to EMF coordinates. */ + ul = get_pathrect_corner(pathRect, angle, 0) * PX2WORLD; + ur = get_pathrect_corner(pathRect, angle, 1) * PX2WORLD; + lr = get_pathrect_corner(pathRect, angle, 2) * PX2WORLD; wRect = Geom::distance(ul,ur); hRect = Geom::distance(ur,lr); /* The basic rectangle for all of these is placed with its UL corner at 0,0 with a size wRect,hRect. Apply a world transform to place/scale it into the appropriate position on the drawing. Actual gradientfill records are either this entire rectangle or slices of it as defined by the stops. + This rectangle has already been transformed by tf (whatever rotation/scale) Inkscape had applied to it. */ Geom::Affine tf2 = Geom::Rotate(-angle); // the rectangle may be drawn skewed to the coordinate system - tf2 *= tf; // the coordinate system of the rectangular path may be rotated tmpTransform.eM11 = tf2[0]; tmpTransform.eM12 = tf2[1]; tmpTransform.eM21 = tf2[2]; tmpTransform.eM22 = tf2[3]; - tmpTransform.eDx = (ul)[Geom::X]; - tmpTransform.eDy = (ul)[Geom::Y]; + tmpTransform.eDx = round((ul)[Geom::X]); // use explicit round for better stability + tmpTransform.eDy = round((ul)[Geom::Y]); rec = U_EMRSAVEDC_set(); if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { @@ -1138,10 +1145,10 @@ unsigned int PrintEmf::fill( gMode = U_GRADIENT_FILL_RECT_V; } doff_base = doff_range; - rcb.left = outUL[X]; - rcb.top = outUL[Y]; - rcb.right = outLR[X]; - rcb.bottom = outLR[Y]; + rcb.left = round(outUL[X]); // use explicit round for better stability + rcb.top = round(outUL[Y]); + rcb.right = round(outLR[X]); + rcb.bottom = round(outLR[Y]); sp_color_get_rgb_floatv(&tg->vector.stops[istop].color, rgb); opa = tg->vector.stops[istop].opacity; c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); @@ -1157,7 +1164,6 @@ unsigned int PrintEmf::fill( c1 = c2; // for next stop ug4.UpperLeft = 0; ug4.LowerRight= 1; - /* NEED to push world transform here for rotations */ rec = U_EMRGRADIENTFILL_set(rcb, 2, 1, gMode, ut, (uint32_t *) &ug4 ); if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { g_error("Fatal programming error in PrintEmf::fill at U_EMRGRADIENTFILL_set"); diff --git a/src/extension/internal/emf-print.h b/src/extension/internal/emf-print.h index 8fc9908e3..1e4970a46 100644 --- a/src/extension/internal/emf-print.h +++ b/src/extension/internal/emf-print.h @@ -1,8 +1,9 @@ /** @file * @brief Enhanced Metafile printing - implementation */ -/* Author: +/* Authors: * Ulf Erikson + * David Mathog * * Copyright (C) 2006-2008 Authors * diff --git a/src/extension/internal/text_reassemble.c b/src/extension/internal/text_reassemble.c index cd84910fc..e28e5effb 100644 --- a/src/extension/internal/text_reassemble.c +++ b/src/extension/internal/text_reassemble.c @@ -67,11 +67,11 @@ Optional compiler switches for development: File: text_reassemble.c -Version: 0.0.10 -Date: 06-MAY-2013 +Version: 0.0.12 +Date: 07-FEB-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2013 David Mathog and California Institute of Technology (Caltech) +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -665,7 +665,7 @@ FT_INFO *ftinfo_clear(FT_INFO *fti){ free(fsp->file); /* release memory holding copies of paths */ free(fsp->fontspec); /* release memory holding copies of font names */ FcPatternDestroy(fsp->fpat); /* release memory for FontConfig fpats */ - FcFontSetDestroy(fti->fonts[i].fontset); + FcFontSetDestroy(fsp->fontset); if(fsp->alts){ free(fsp->alts); } } free(fti->fonts); @@ -726,9 +726,10 @@ int ftinfo_find_loaded_by_src(const FT_INFO *fti, const uint8_t *filename){ */ int ftinfo_load_fontname(FT_INFO *fti, const char *fontspec){ - FcPattern *pattern, *fpat; - FcFontSet *fontset; - FcResult result = FcResultMatch; + FcPattern *pattern = NULL; + FcPattern *fpat = NULL; + FcFontSet *fontset = NULL; + FcResult result = FcResultMatch; char *filename; double fd; FNT_SPECS *fsp; @@ -738,38 +739,45 @@ int ftinfo_load_fontname(FT_INFO *fti, const char *fontspec){ if(!fti)return(-1); /* If it is already loaded, do not load it again */ - if((status = ftinfo_find_loaded_by_spec(fti, (uint8_t *) fontspec))>=0){ - return(status); - } + status = ftinfo_find_loaded_by_spec(fti, (uint8_t *) fontspec); + if(status >= 0){ return(status); } + status = 0; /* was -1, reset to 0 */ ftinfo_make_insertable(fti); fi_idx = fti->used; - if(!(pattern = FcNameParse((const FcChar8 *)fontspec)) )return(2); - if(!FcConfigSubstitute(NULL, pattern, FcMatchPattern) )return(3); - FcDefaultSubstitute(pattern); - /* get a fontset, trimmed to only those with new glyphs as needed, so that missing glyph's may be handled */ - if(!(fontset = FcFontSort (NULL,pattern, FcTrue, NULL, &result)) - || result != FcResultMatch)return(4); - if(!(fpat = FcFontRenderPrepare(NULL, pattern, fontset->fonts[0])) )return(405); - if(FcPatternGetString( fpat, FC_FILE, 0, (FcChar8 **)&filename) != FcResultMatch)return(5); - if(FcPatternGetDouble( fpat, FC_SIZE, 0, &fd) != FcResultMatch)return(6); - - /* copy these into memory for external use */ - fsp = &(fti->fonts[fti->used]); - fsp->fontset = fontset; - fsp->alts = NULL; /* Initially no links to alternate fonts */ - fsp->space = 0; - fsp->file = (uint8_t *) U_strdup((char *) filename); - fsp->fontspec = (uint8_t *) U_strdup((char *) fontspec); - fsp->fpat = fpat; - fsp->fsize = fd; - + pattern = FcNameParse((const FcChar8 *)fontspec); + while(1) { /* this is NOT a loop, it uses breaks to avoid gotos and deep nesting */ + if(!(pattern)){ status = -2; break; } + if(!FcConfigSubstitute(NULL, pattern, FcMatchPattern)){ status = -3; break; }; + FcDefaultSubstitute(pattern); + /* get a fontset, trimmed to only those with new glyphs as needed, so that missing glyph's may be handled */ + if(!(fontset = FcFontSort (NULL,pattern, FcTrue, NULL, &result)) || (result != FcResultMatch)){ status = -4; break; } + if(!(fpat = FcFontRenderPrepare(NULL, pattern, fontset->fonts[0]))){ status = -405; break; } + if(FcPatternGetString( fpat, FC_FILE, 0, (FcChar8 **)&filename) != FcResultMatch){ status = -5; break; } + if(FcPatternGetDouble( fpat, FC_SIZE, 0, &fd) != FcResultMatch){ status = -6; break; } + + /* copy these into memory for external use */ + fsp = &(fti->fonts[fti->used]); + fsp->fontset = fontset; + fsp->alts = NULL; /* Initially no links to alternate fonts */ + fsp->space = 0; + fsp->file = (uint8_t *) U_strdup((char *) filename); + fsp->fontspec = (uint8_t *) U_strdup((char *) fontspec); + fsp->fpat = fpat; + fsp->fsize = fd; + break; + } /* release FC's own memory related to this call that does not need to be kept around so that face will work */ - FcPatternDestroy(pattern); + if(pattern)FcPatternDestroy(pattern); /* done with this memory */ + if(status<0){ + if(fontset)FcFontSetDestroy(fontset); + if(fpat)FcPatternDestroy(fpat); + return(status); + } /* get the current face */ - if(FT_New_Face( fti->library, (const char *) fsp->file, 0, &(fsp->face) )){ return(8); } + if(FT_New_Face( fti->library, (const char *) fsp->file, 0, &(fsp->face) )){ return(-8); } if(FT_Set_Char_Size( fsp->face, /* handle to face object */ @@ -777,12 +785,12 @@ int ftinfo_load_fontname(FT_INFO *fti, const char *fontspec){ fd*64, /* char_height in 1/64th of points */ 72, /* horizontal device resolution, DPI */ 72) /* vebrical device resolution, DPI */ - ){ return(9); } + ){ return(-9); } /* The space advance is needed in various places. Get it now, and get it in the font units, so that it can be scaled later with the text size */ status = TR_getadvance(fti, fsp,' ',0,FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP, FT_KERNING_UNSCALED, NULL, NULL); - if(status < 0)return(7); + if(status < 0)return(-7); fsp->spcadv = ((double) status)/(64.0); fti->used++; @@ -1380,7 +1388,7 @@ printf("Overlap rprect (LL,UR) dst:(%lf,%lf),(%lf,%lf) src:(%lf,%lf),(%lf,%lf)\n } /** - \brief Check for a text element upstream from the start element and in the reversed direction. + \brief Check for various sorts of invalid text elements upstream (language dir changes, draw order backwards from language direction) \returns 0 on success (not upstream), 1 if upstream, anything else is an error. \param bri pointer to the BR_INFO structure \param dst index of the destination bounding rectangle. @@ -1405,6 +1413,12 @@ int brinfo_upstream(BR_INFO *bri, int dst, int src, int ddir, int sdir){ else if( ddir == LDIR_LR && sdir == LDIR_RL){ if((br_src->xll + br_src->xur)/2.0 <= br_dst->xll ){ status = 1; } } + else if( ddir == LDIR_RL && sdir == LDIR_RL){ + if(br_dst->xur <= (br_src->xll + br_src->xur)/2.0){ status = 1; } + } + else if( ddir == LDIR_LR && sdir == LDIR_LR){ + if((br_src->xll + br_src->xur)/2.0 <= br_dst->xll ){ status = 1; } + } return(status); } @@ -1490,13 +1504,19 @@ TR_INFO *trinfo_init(TR_INFO *tri){ !(tri->bri = brinfo_init()) || !(tri->cxi = cxinfo_init()) ){ tri = trinfo_release(tri); } + tri->out = NULL; /* This will allocate as needed, it might not ever be needed. */ + tri->qe = 0.0; + tri->esc = 0.0; + tri->x = DBL_MAX; + tri->y = DBL_MAX; + tri->dirty = 0; tri->use_kern = 1; - tri->usebk = BKCLR_NONE; tri->load_flags = FT_LOAD_NO_SCALE; tri->kern_mode = FT_KERNING_UNSCALED; - tri->out = NULL; /* This will allocate as needed, it might not ever be needed. */ tri->outspace = 0; tri->outused = 0; + tri->usebk = BKCLR_NONE; + memset(&(tri->bkcolor),0,sizeof(TRCOLORREF)); return(tri); } @@ -1552,9 +1572,6 @@ TR_INFO *trinfo_release_except_FC(TR_INFO *tri){ */ TR_INFO *trinfo_clear(TR_INFO *tri){ if(tri){ - tri->dirty = 0; /* set these back to their defaults */ - tri->esc = 0.0; - /* Do NOT modify use_kern, usebk, load_flags, or kern_mode */ if(tri->bri)tri->bri=brinfo_release(tri->bri); if(tri->tpi)tri->tpi=tpinfo_release(tri->tpi); @@ -1565,6 +1582,11 @@ TR_INFO *trinfo_clear(TR_INFO *tri){ tri->outused = 0; tri->outspace = 0; }; + /* Do NOT modify: qe, use_kern, usebk, load_flags, kern_mode, or bkcolor. Set the rest back to their defaults */ + tri->esc = 0.0; + tri->x = DBL_MAX; + tri->y = DBL_MAX; + tri->dirty = 0; if(!(tri->tpi = tpinfo_init()) || /* re-init the pieces just released */ !(tri->bri = brinfo_init()) || !(tri->cxi = cxinfo_init()) @@ -1958,7 +1980,7 @@ void TR_layout_2_svg(TR_INFO *tri){ cutat=strcspn((char *)fti->fonts[tsp->fi_idx].fontspec,":"); sprintf(obuf,"font-family:%.*s;",cutat,fti->fonts[tsp->fi_idx].fontspec); TRPRINT(tri, obuf); - sprintf(obuf,"\n\">%s\n",tsp->string); + sprintf(obuf,"\n\">%s\n",&tsp->string[tsp->spaces]); TRPRINT(tri, obuf); #endif /* DBG_TR_INPUT debugging code, original text objects */ } @@ -2278,7 +2300,10 @@ int TR_layout_analyze(TR_INFO *tri){ next logical piece of text is "upstream" positionally of its logical predecessor. The meaning of such a construct is at best ambiguous. The test is only applied with respect to the first text chunk. This sort of construct may appear when a valid initial construct like [1->English][2<-Hebrew][3->English] is edited - and the leading chunk of text removed. + and the leading chunk of text removed. + + Also reject reversed order text as in (English) (draw order) arranged as . This happens + if the language direction field is incorrect, perhaps due to a corrupt or malformed input file. */ if(brinfo_upstream(bri, dst_rt, /* index into bri for dst */ @@ -2422,10 +2447,28 @@ int TR_layout_analyze(TR_INFO *tri){ } } - /* if x or y kern is less than the quantization error it is probably noise, set it to zero */ - if(fabs(tspj->xkern)qe)tspj->xkern = 0.0; - if(fabs(tspj->ykern)qe)tspj->ykern = 0.0; - + /* if x or y kern is less than twice the quantization error it is probably noise, set it to zero */ + if(fabs(tspj->xkern) <= 2.0*tri->qe)tspj->xkern = 0.0; + if(fabs(tspj->ykern) <= 2.0*tri->qe)tspj->ykern = 0.0; + + /* reintroduce spaces on the leading edge of text "j" if the kerning can be in part or in whole replaced + with 1 or 2 spaces */ + if(tspj->ykern == 0.0){ + double spaces = tspj->xkern/spcadv; /* negative on RL language, positive on LR */ + if((ldir == LDIR_RL && (spaces <= -0.9 && spaces >= -2.1)) || + (ldir == LDIR_LR && (spaces >= 0.9 && spaces <= 2.1)) ){ + int ispaces = lround(spaces); + tspj->xkern -= ((double)ispaces*spcadv); + if(ispaces<0)ispaces=-ispaces; + size_t slen = strlen((char *)tspj->string); + uint8_t *newstring = malloc(1 + ispaces + slen); + sprintf((char *)newstring," "); /* start with two spaces, possibly overwrite one in the next line */ + memcpy(newstring+ispaces,tspj->string,slen+1); /* copy existing string to proper position */ + free(tspj->string); + tspj->string = newstring; + tspj->spaces = ispaces; // only needed to fix optional debugging SVG output later + } + } tspi = tspj; lastldir = ldir; @@ -2699,7 +2742,7 @@ int main(int argc, char *argv[]){ tsp.weight = 80; tsp.condensed = 100; tsp.decoration = 0; /* none */ - tsp.co = 0; + tsp.spaces = 0; /* none */ tsp.fi_idx = -1; /* set to an invalid */ tsp.rt_tidx = -1; /* set to an invalid */ tsp.xkern = tsp.ykern = 0.0; diff --git a/src/extension/internal/text_reassemble.h b/src/extension/internal/text_reassemble.h index d85b233be..6c1acafe5 100644 --- a/src/extension/internal/text_reassemble.h +++ b/src/extension/internal/text_reassemble.h @@ -4,11 +4,11 @@ See text_reassemble.c for notes File: text_reassemble.h -Version: 0.0.12 -Date: 14-MAY-2013 +Version: 0.0.13 +Date: 06-FEB-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2013 David Mathog and California Institute of Technology (Caltech) +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) */ #ifndef _TEXT_REASSEMBLE_ @@ -189,6 +189,7 @@ typedef struct { int weight; /**< weight, as in FontConfig */ int condensed; /**< condensed, as in FontConfig */ int decoration; /**< text decorations, ignored during assembly, used during output */ + int spaces; /**< count of spaces converted from wide kerning (1 or 2) */ TRCOLORREF decColor; /**< text decoration color, ignored during assembly, used during output */ int co; /**< condensed override, if set Font name included narrow */ int rt_tidx; /**< index of rectangle that contains it */ diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index a72c16a88..fc54350df 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -4,6 +4,7 @@ /* Authors: * Ulf Erikson * Jon A. Cruz + * David Mathog * Abhishek Sharma * * Copyright (C) 2006-2008 Authors @@ -1079,6 +1080,28 @@ Wmf::select_brush(PWMF_CALLBACK_DATA d, int index) g_message("Please send WMF file to developers - select_brush U_WMR_DIBCREATEPATTERNBRUSH not bm16 or dib, not handled"); } } + else if(iType == U_WMR_CREATEPATTERNBRUSH){ + uint32_t tidx; + int cbPx; + U_BITMAP16 Bm16h; + const char *px; + if(U_WMRCREATEPATTERNBRUSH_get(record, &Bm16h, &cbPx, &px)){ + tidx = add_bm16_image(d, Bm16h, px); + if(tidx == 0xFFFFFFFF){ // 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)); + b = SP_COLOR_U_TO_F( U_RGBAGetB(d->dc[d->level].textColor)); + d->dc[d->level].style.fill.value.color.set( r, g, b ); + d->dc[d->level].fill_mode = DRAW_PAINT; + } + else { + d->dc[d->level].fill_idx = tidx; + d->dc[d->level].fill_mode = DRAW_IMAGE; + } + d->dc[d->level].fill_set = true; + } + } } @@ -1488,6 +1511,7 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK tsp.vadvance = 0.0; /* meaningful only when a complex contains two or more lines */ tsp.taln = ALILEFT + ALIBASE; tsp.ldir = LDIR_LR; + tsp.spaces = 0; // this field is only used for debugging tsp.color.Red = 0; /* RGB Black */ tsp.color.Green = 0; /* RGB Black */ tsp.color.Blue = 0; /* RGB Black */ @@ -1498,6 +1522,7 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK tsp.condensed = 100; tsp.co = 0; tsp.fi_idx = -1; /* set to an invalid */ + tsp.rt_tidx = -1; /* set to an invalid */ SVGOStringStream dbg_str; @@ -1568,7 +1593,10 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK d->dc[d->level].sizeView.x = d->dc[d->level].sizeWnd.x = 0; d->dc[d->level].sizeView.y = d->dc[d->level].sizeWnd.y = 0; - // Upper left corner in device units, usually both 0, but not always + /* Upper left corner in device units, usually both 0, but not always. + If a placeable header is used, and later a windoworg/windowext are found, then + the placeable information will be ignored. + */ d->ulCornerInX = Placeable.Dst.left; d->ulCornerInY = Placeable.Dst.top; @@ -1805,6 +1833,8 @@ std::cout << "BEFORE DRAW" { dbg_str << "\n"; nSize = U_WMRSETWINDOWORG_get(contents, &d->dc[d->level].winorg); + d->ulCornerOutX = 0.0; // In the examples seen to date if this record is used with a placeable header, that header is ignored + d->ulCornerOutY = 0.0; break; } case U_WMR_SETWINDOWEXT: @@ -2322,12 +2352,12 @@ std::cout << "BEFORE DRAW" break; case U_WMR_CREATEBRUSHINDIRECT: case U_WMR_DIBCREATEPATTERNBRUSH: + case U_WMR_CREATEPATTERNBRUSH: // <- this one did not display properly on XP, DIBCREATEPATTERNBRUSH works select_brush(d, index); break; case U_WMR_CREATEFONTINDIRECT: select_font(d, index); break; - case U_WMR_CREATEPATTERNBRUSH: // <- this one did not display properly on XP, DIBCREATEPATTERNBRUSH works case U_WMR_CREATEPALETTE: case U_WMR_CREATEBITMAPINDIRECT: case U_WMR_CREATEBITMAP: @@ -2376,6 +2406,7 @@ std::cout << "BEFORE DRAW" if(iType == U_WMR_TEXTOUT){ dbg_str << "\n"; nSize = U_WMRTEXTOUT_get(contents, &Dst, &tlen, &text); + Opts=0; } else { dbg_str << "\n"; @@ -3053,7 +3084,14 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) // Scale and translate objects double scale = Inkscape::Util::Quantity::convert(1, "px", doc_unit); ShapeEditor::blockSetItem(true); - doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, doc->getHeight().value("px"))); + double dh; + if(SP_ACTIVE_DOCUMENT){ // for file menu open or import, or paste from clipboard + dh = SP_ACTIVE_DOCUMENT->getHeight().value("px"); + } + else { // for open via --file on command line + dh = doc->getHeight().value("px"); + } + doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, dh)); ShapeEditor::blockSetItem(false); Inkscape::DocumentUndo::setUndoSensitive(doc, saved); -- cgit v1.2.3 From 17773c1d21bded8fe3f10f6a835dc11ea1910746 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Mon, 10 Feb 2014 06:24:25 -0500 Subject: Extensions->Render submenu. Scaling into document units for grid.cpp (Bug 1240455) (bzr r13018) --- src/extension/internal/grid.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index 2f9d0ff25..c2ef2b27c 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -112,11 +112,13 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc bounding_area = temprec; } - float spacings[2] = { module->get_param_float("xspacing"), - module->get_param_float("yspacing") }; - float line_width = module->get_param_float("lineWidth"); - float offsets[2] = { module->get_param_float("xoffset"), - module->get_param_float("yoffset") }; + gdouble scale = Inkscape::Util::Quantity::convert(1, "px", (document->doc())->getDefaultUnit()); + bounding_area *= Geom::Scale(scale); + float spacings[2] = { scale*module->get_param_float("xspacing"), + scale*module->get_param_float("yspacing") }; + float line_width = scale*module->get_param_float("lineWidth"); + float offsets[2] = { scale*module->get_param_float("xoffset"), + scale*module->get_param_float("yoffset") }; Glib::ustring path_data(""); -- cgit v1.2.3 From 1fcd3766d80f7ff8cc0fabc05c3923254ed86124 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 11 Feb 2014 12:35:04 +0100 Subject: Set 'preserveAspectRatio' to 'none' when importing an image. (bzr r13020) --- src/extension/internal/gdkpixbuf-input.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/extension/internal') diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index d7d692091..ec04b1dad 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -95,6 +95,11 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image"); sp_repr_set_svg_double(image_node, "width", width); sp_repr_set_svg_double(image_node, "height", height); + + // Added 11 Feb 2014 as we now honor "preserveAspectRatio" and this is + // what Inkscaper's expect. + image_node->setAttribute("preserveAspectRatio", "none"); + if( scale.compare( "auto" ) != 0 ) { SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "image-rendering", scale.c_str()); @@ -122,6 +127,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) // Set viewBox if it doesn't exist if (!doc->getRoot()->viewBox_set) { + std::cout << "Viewbox not set, setting" << std::endl; doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDefaultUnit()), doc->getHeight().value(doc->getDefaultUnit()))); } -- cgit v1.2.3 From 1f8800625995b03d29fc3e642f788581c93a874d Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 11 Feb 2014 14:56:11 +0100 Subject: Set 'preserveAspectRatio' to 'none' for PDF image input. Fixes #878984. (bzr r13023) --- src/extension/internal/pdfinput/svg-builder.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/extension/internal') diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index b3f15bbff..20cd74cdb 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -1657,6 +1657,10 @@ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height Inkscape::XML::Node *image_node = _xml_doc->createElement("svg:image"); sp_repr_set_svg_double(image_node, "width", 1); sp_repr_set_svg_double(image_node, "height", 1); + + // PS/PDF images are placed via a transformation matrix, no preserveAspectRatio used + image_node->setAttribute("preserveAspectRatio", "none"); + // Set transformation svgSetTransform(image_node, 1.0, 0.0, 0.0, -1.0, 0.0, 1.0); -- cgit v1.2.3 From e24b23c1189ab152ba877593e268b2cac1524903 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 12 Feb 2014 13:12:39 +0100 Subject: Set bitmap upscaling preference in Cairo based PS and PDF output. (bzr r13025) --- src/extension/internal/cairo-render-context.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 47de62ac0..2916d9fa9 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -1433,7 +1433,7 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con } bool CairoRenderContext::renderImage(Inkscape::Pixbuf *pb, - Geom::Affine const &image_transform, SPStyle const * /*style*/) + Geom::Affine const &image_transform, SPStyle const *style) { g_assert( _is_valid ); @@ -1468,6 +1468,27 @@ bool CairoRenderContext::renderImage(Inkscape::Pixbuf *pb, cairo_rectangle(_cr, 0, 0, w, h); cairo_clip(_cr); } + + // Cairo filter method will be mapped to PS/PDF 'interpolate' true/false). + // See cairo-pdf-surface.c + if (style) { + // See: http://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty + // http://www.w3.org/TR/css4-images/#the-image-rendering + // style.h/style.cpp + switch (style->image_rendering.computed) { + case SP_CSS_COLOR_RENDERING_AUTO: + // Do nothing + break; + case SP_CSS_COLOR_RENDERING_OPTIMIZEQUALITY: + cairo_pattern_set_filter(cairo_get_source(_cr), CAIRO_FILTER_BEST ); + break; + case SP_CSS_COLOR_RENDERING_OPTIMIZESPEED: + default: + cairo_pattern_set_filter(cairo_get_source(_cr), CAIRO_FILTER_NEAREST ); + break; + } + } + cairo_paint_with_alpha(_cr, opacity); cairo_restore(_cr); -- cgit v1.2.3 From 53428979fabc03e257dbf31b98bb7be98ada3764 Mon Sep 17 00:00:00 2001 From: su_v Date: Wed, 12 Feb 2014 17:30:16 +0100 Subject: Image import dialog: add dpi option (from file or default), use compacter layout (help as tooltips) Fixed bugs: - https://launchpad.net/bugs/1253051 (bzr r13026) --- src/extension/internal/gdkpixbuf-input.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index ec04b1dad..a384c7bde 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -30,22 +30,31 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool ask = prefs->getBool("/dialogs/import/ask"); Glib::ustring link = prefs->getString("/dialogs/import/link"); + bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); Glib::ustring scale = prefs->getString("/dialogs/import/scale"); // std::cout << "GkdpixbufInput::open: " // << " ask: " << ask // << ", link: " << link + // << ", forcexdpi: " << forcexdpi // << ", scale: " << scale << std::endl; // std::cout << " in preferences: " // << " ask: " << !mod->get_param_bool("do_not_ask") // << ", link: " << mod->get_param_optiongroup("link") + // << ", mod_dpi: " << mod->get_param_optiongroup("dpi") // << ", scale: " << mod->get_param_optiongroup("scale") << std::endl; if( ask ) { Glib::ustring mod_link = mod->get_param_optiongroup("link"); + Glib::ustring mod_dpi = mod->get_param_optiongroup("dpi"); + bool mod_forcexdpi = ( mod_dpi.compare( "from_default" ) == 0 ); Glib::ustring mod_scale = mod->get_param_optiongroup("scale"); if( link.compare( mod_link ) != 0 ) { link = mod_link; } prefs->setString("/dialogs/import/link", link ); + if( forcexdpi != mod_forcexdpi ) { + forcexdpi = mod_forcexdpi; + } + prefs->setBool("/dialogs/import/forcexdpi", forcexdpi ); if( scale.compare( mod_scale ) != 0 ) { scale = mod_scale; } @@ -68,7 +77,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) double width = pb->width(); double height = pb->height(); double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", Inkscape::Util::Quantity::convert(1, "in", "px")); - bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); + //bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); ImageResolution *ir = 0; double xscale = 1; double yscale = 1; @@ -179,18 +188,21 @@ GdkpixbufInput::init(void) "%s\n" "org.inkscape.input.gdkpixbuf.%s\n" - "\n" + "\n" "<_option value='embed' >" N_("Embed") "\n" "<_option value='link' >" N_("Link") "\n" "\n" - "<_param name='help' type='description'>" N_("Embed results in stand-alone, larger SVG files. Link references a file outside this SVG document and all files must be moved together.") "\n" - "\n" + "\n" + "<_option value='from_file' >" N_("From file") "\n" + "<_option value='from_default' >" N_("Default import resolution") "\n" + "\n" + + "\n" "<_option value='auto' >" N_("None (auto)") "\n" "<_option value='optimizeQuality' >" N_("Smooth (optimizeQuality)") "\n" "<_option value='optimizeSpeed' >" N_("Blocky (optimizeSpeed)") "\n" "\n" - "<_param name='help' type='description'>" N_("When an image is upscaled, apply smoothing or keep blocky (pixelated). (Will not work in all browsers.)") "\n" "false\n" "\n" -- cgit v1.2.3 From 12e03b939f58c6b6dc5495e0559fe47d7a73bb48 Mon Sep 17 00:00:00 2001 From: David Mathog Date: Sat, 22 Feb 2014 10:03:23 +0100 Subject: Fix 'preserveAspectRatio' attribute of bitmap images in EMF/WMF import/export (bug #1278645). Fixed bugs: - https://launchpad.net/bugs/1278645 (bzr r13049) --- src/extension/internal/emf-inout.cpp | 2 ++ src/extension/internal/emf-print.cpp | 10 +++++----- src/extension/internal/wmf-inout.cpp | 10 ++++++---- src/extension/internal/wmf-print.cpp | 16 ++++++++++------ 4 files changed, 23 insertions(+), 15 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index 276dee362..b73c5e9e5 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -554,6 +554,7 @@ uint32_t Emf::add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint else { *(d->defs) += " xlink:href=\"data:image/png;base64,"; } *(d->defs) += base64String; *(d->defs) += "\"\n"; + *(d->defs) += " preserveAspectRatio=\"none\"\n"; *(d->defs) += " />\n"; @@ -1531,6 +1532,7 @@ void Emf::common_image_extraction(PEMF_CALLBACK_DATA d, void *pEmr, tmp_image << "\"\n height=\"" << dh << "\"\n width=\"" << dw << "\"\n"; tmp_image << " transform=" << current_matrix(d, dx, dy, 1); // calculate appropriate offset + tmp_image << " preserveAspectRatio=\"none\"\n"; tmp_image << "/> \n"; *(d->outsvg) += tmp_image.str().c_str(); diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 6d5bb6f4b..c103100b3 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -1562,7 +1562,7 @@ unsigned int PrintEmf::image( unsigned int w, /** width of bitmap */ unsigned int h, /** height of bitmap */ unsigned int rs, /** row stride (normally w*4) */ - Geom::Affine const &/*tf_ignore*/, /** WRONG affine transform, use the one from m_tr_stack */ + Geom::Affine const &tf_rect, /** affine transform only used for defining location and size of rect, for all other tranforms, use the one from m_tr_stack */ SPStyle const *style) /** provides indirect link to image object */ { double x1, y1, dw, dh; @@ -1574,10 +1574,10 @@ unsigned int PrintEmf::image( g_error("Fatal programming error in PrintEmf::image at EMRHEADER"); } - x1 = atof(style->object->getAttribute("x")); - y1 = atof(style->object->getAttribute("y")); - dw = atof(style->object->getAttribute("width")); - dh = atof(style->object->getAttribute("height")); + x1 = tf_rect[4]; + y1 = tf_rect[5]; + dw = ((double) w) * tf_rect[0]; + dh = ((double) h) * tf_rect[3]; Geom::Point pLL(x1, y1); Geom::Point pLL2 = pLL * tf; //location of LL corner in Inkscape coordinates diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index fc54350df..3c348f5c4 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -525,6 +525,7 @@ uint32_t Wmf::add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsa else { *(d->defs) += " xlink:href=\"data:image/png;base64,"; } *(d->defs) += base64String; *(d->defs) += "\"\n"; + *(d->defs) += " preserveAspectRatio=\"none\"\n"; *(d->defs) += " />\n"; @@ -619,6 +620,7 @@ uint32_t Wmf::add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char * *(d->defs) += " xlink:href=\"data:image/png;base64,"; *(d->defs) += base64String; *(d->defs) += "\"\n"; + *(d->defs) += " preserveAspectRatio=\"none\"\n"; *(d->defs) += " />\n"; @@ -1269,6 +1271,7 @@ void Wmf::common_dib_to_image(PWMF_CALLBACK_DATA d, const char *dib, SVGOStringStream tmp_image; int dibparams; + tmp_image << "\n\t outsvg) += tmp_image.str().c_str(); + tmp_image << " preserveAspectRatio=\"none\"\n"; + tmp_image << "/> \n"; - *(d->outsvg) += "/> \n"; + *(d->outsvg) += tmp_image.str().c_str(); *(d->path) = ""; } diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp index 1c7b42c82..32c7ac0bd 100644 --- a/src/extension/internal/wmf-print.cpp +++ b/src/extension/internal/wmf-print.cpp @@ -1103,7 +1103,7 @@ unsigned int PrintWmf::image( unsigned int w, /** width of bitmap */ unsigned int h, /** height of bitmap */ unsigned int rs, /** row stride (normally w*4) */ - Geom::Affine const & /*tf_ignore*/, /** WRONG affine transform, use the one from m_tr_stack */ + Geom::Affine const &tf_rect, /** affine transform only used for defining location and size of rect, for all other tranforms, use the one from m_tr_stack */ SPStyle const *style) /** provides indirect link to image object */ { double x1, y1, dw, dh; @@ -1115,15 +1115,19 @@ unsigned int PrintWmf::image( g_error("Fatal programming error in PrintWmf::image at EMRHEADER"); } - x1 = g_ascii_strtod(style->object->getAttribute("x"), NULL); - y1 = g_ascii_strtod(style->object->getAttribute("y"), NULL); - dw = g_ascii_strtod(style->object->getAttribute("width"), NULL); - dh = g_ascii_strtod(style->object->getAttribute("height"), NULL); + x1 = tf_rect[4]; + y1 = tf_rect[5]; + dw = ((double) w) * tf_rect[0]; + dh = ((double) h) * tf_rect[3]; Geom::Point pLL(x1, y1); Geom::Point pLL2 = pLL * tf; //location of LL corner in Inkscape coordinates + /* adjust scale of w and h. This works properly when there is no rotation. The values are + a bit strange when there is rotation, but since WMF cannot handle rotation in any case, all + answers are equally wrong. + */ Geom::Point pWH(dw, dh); - Geom::Point pWH2 = pWH * tf.withoutTranslation(); //adjust scale + Geom::Point pWH2 = pWH * tf.withoutTranslation(); char *px; uint32_t cbPx; -- cgit v1.2.3 From 903d68d4df1de1ae21e124d6e9c12770085ea087 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 25 Feb 2014 17:08:30 +0100 Subject: Rewrite of symbol creation code. Partial fix for 1201325. Symbols cannot have 'tranform' attribute. The old code copied the group 'transform' attribute to the symbol. The new code creates an intermediate group with the required 'transform' if it is not a simple translation. A simple translation is removed and applied instead to the new element. Multiple objects can now be turned into a symbol without first grouping the objects. (At the cost that multiple groups can no longer be turned into multiple symbols at one go.) This better matches marker and pattern creation. (bzr r13057) --- src/extension/internal/cairo-renderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 6fbc85c05..aa47d8169 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -77,8 +77,8 @@ #include #endif -//#define TRACE(_args) g_printf _args -#define TRACE(_args) +#define TRACE(_args) g_printf _args +//#define TRACE(_args) //#define TEST(_args) _args #define TEST(_args) @@ -628,7 +628,7 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page ctx->_width = d.width(); ctx->_height = d.height(); - TRACE(("setupDocument: %f x %f\n", ctx->_width, ctx->_height)); + TRACE(("Cairo Renderer: setupDocument: %f x %f\n", ctx->_width, ctx->_height)); bool ret = ctx->setupSurface(ctx->_width, ctx->_height); -- cgit v1.2.3 From ba65200ce8e3225340d729902c26dce142c65e57 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 25 Feb 2014 17:12:22 +0100 Subject: Revert unintended checkin. (bzr r13058) --- src/extension/internal/cairo-renderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index aa47d8169..6fbc85c05 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -77,8 +77,8 @@ #include #endif -#define TRACE(_args) g_printf _args -//#define TRACE(_args) +//#define TRACE(_args) g_printf _args +#define TRACE(_args) //#define TEST(_args) _args #define TEST(_args) @@ -628,7 +628,7 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page ctx->_width = d.width(); ctx->_height = d.height(); - TRACE(("Cairo Renderer: setupDocument: %f x %f\n", ctx->_width, ctx->_height)); + TRACE(("setupDocument: %f x %f\n", ctx->_width, ctx->_height)); bool ret = ctx->setupSurface(ctx->_width, ctx->_height); -- cgit v1.2.3 From 6f844ef457690c841b0be91d70b1e54b61c04812 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Wed, 26 Feb 2014 10:31:28 -0500 Subject: Remove DOM directory and reduce size of inkscape. Use Inkscape::URI and save ziptool to utils. (bzr r13047.1.5) --- src/extension/internal/odf.cpp | 19 ++++++------------- src/extension/internal/odf.h | 9 +++------ 2 files changed, 9 insertions(+), 19 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index fcabcc4b2..52fabcf3c 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -77,12 +77,7 @@ #include "text-editing.h" #include "util/units.h" - -//# DOM-specific includes -#include "dom/dom.h" -#include "dom/util/ziptool.h" -//#include "dom/io/domstream.h" - +#include "uri.h" #include "inkscape-version.h" #include "document.h" @@ -90,6 +85,7 @@ #include "io/inkscapestream.h" #include "io/bufferstream.h" +#include #include namespace Inkscape { @@ -98,7 +94,6 @@ namespace Extension namespace Internal { //# Shorthand notation -typedef org::w3c::dom::DOMString DOMString; typedef Inkscape::IO::BufferOutputStream BufferOutputStream; typedef Inkscape::IO::OutputStreamWriter OutputStreamWriter; typedef Inkscape::IO::StringOutputStream StringOutputStream; @@ -1026,6 +1021,7 @@ static void gatherText(Inkscape::XML::Node *node, Glib::ustring &buf) } + /** * FIRST PASS. * Method descends into the repr tree, converting image, style, and gradient info @@ -1086,10 +1082,9 @@ void OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node) imageTable[oldName] = newName; Glib::ustring comment = "old name was: "; comment.append(oldName); - URI oldUri(oldName); + Inkscape::URI oldUri(oldName.c_str()); //# if relative to the documentURI, get proper path - URI resUri = documentUri.resolve(oldUri); - DOMString pathName = resUri.getNativePath(); + std::string pathName = documentUri.getFullPath(oldUri.getFullPath("")); ZipEntry *ze = zf.addFile(pathName, comment); if (ze) { @@ -2105,9 +2100,7 @@ void OdfOutput::save(Inkscape::Extension::Output */*mod*/, SPDocument *doc, gcha { reset(); - documentUri = URI(filename); - /* fixme: It looks like we really are using documentUri as a URI, so we ought to call - * g_filename_to_uri for the URI constructor. */ + documentUri = Inkscape::URI(filename); ZipFile zf; preprocess(zf, doc->rroot); diff --git a/src/extension/internal/odf.h b/src/extension/internal/odf.h index 6b915e347..f8712d5eb 100644 --- a/src/extension/internal/odf.h +++ b/src/extension/internal/odf.h @@ -23,18 +23,16 @@ #ifndef EXTENSION_INTERNAL_ODG_OUT_H #define EXTENSION_INTERNAL_ODG_OUT_H -#include #include -#include +#include #include "extension/implementation/implementation.h" #include - #include #include -#include +#include "uri.h" #include "sp-item.h" #include @@ -46,7 +44,6 @@ namespace Extension namespace Internal { -typedef org::w3c::dom::URI URI; typedef Inkscape::IO::Writer Writer; class StyleInfo @@ -279,7 +276,7 @@ public: private: - URI documentUri; + Inkscape::URI documentUri; void reset(); -- cgit v1.2.3 From ad5c6ceab1420aabbe4c751080bce8b2363abd11 Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Mon, 3 Mar 2014 22:44:59 +0100 Subject: More memory leak fixes (Bug #1275170) (bzr r13105) --- src/extension/internal/javafx-out.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp index 035a6f0aa..e51e8d539 100644 --- a/src/extension/internal/javafx-out.cpp +++ b/src/extension/internal/javafx-out.cpp @@ -396,12 +396,14 @@ bool JavaFXOutput::doStyle(SPStyle *style) } else if (fill.isPaintserver()){ if (fill.value.href && fill.value.href->getURI() ){ - String uri = fill.value.href->getURI()->toString(); + gchar *str = fill.value.href->getURI()->toString(); + String uri = (str ? str : ""); /* trim the anchor '#' from the front */ if (uri.size() > 0 && uri[0]=='#') { uri = uri.substr(1); } out(" fill: %s()\n", sanatize(uri).c_str()); + g_free(str); } } -- cgit v1.2.3 From 8e89252fde34ad313e96065fe41f9add90cda296 Mon Sep 17 00:00:00 2001 From: David Mathog Date: Thu, 6 Mar 2014 03:13:39 +0100 Subject: WMF: fix for files with swapped W, H in the SETWINDOWEXT record EMF: code cleanup Fixed bugs: - https://launchpad.net/bugs/1241783 (bzr r13119) --- src/extension/internal/wmf-inout.cpp | 167 +++++++++++++++++------------------ 1 file changed, 81 insertions(+), 86 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 3c348f5c4..3a62c9c16 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -455,58 +455,45 @@ uint32_t Wmf::add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsa 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 { // 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; @@ -545,7 +532,7 @@ uint32_t Wmf::add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsa *(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); } @@ -563,16 +550,16 @@ uint32_t Wmf::add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char * 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) @@ -582,8 +569,7 @@ uint32_t Wmf::add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char * 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 @@ -591,17 +577,18 @@ uint32_t Wmf::add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char * ); 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); } @@ -639,7 +626,7 @@ uint32_t Wmf::add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char * *(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); } @@ -883,16 +870,13 @@ double Wmf::pix_to_x_point(PWMF_CALLBACK_DATA d, double px, double /*py*/) { double x = _pix_x_to_point(d, px); - return x; } double Wmf::pix_to_y_point(PWMF_CALLBACK_DATA d, double /*px*/, double py) { - double y = _pix_y_to_point(d, py); - return y; } @@ -1054,7 +1038,6 @@ Wmf::select_brush(PWMF_CALLBACK_DATA d, int index) 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){ @@ -1064,7 +1047,7 @@ Wmf::select_brush(PWMF_CALLBACK_DATA d, int index) 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)); @@ -1384,10 +1367,9 @@ void Wmf::common_bm16_to_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char SVGOStringStream tmp_image; + tmp_image << "\n\t outsvg) += tmp_image.str().c_str(); + tmp_image << " preserveAspectRatio=\"none\"\n"; + tmp_image << "/> \n"; - *(d->outsvg) += "/> \n"; + *(d->outsvg) += tmp_image.str().c_str(); *(d->path) = ""; } @@ -1669,7 +1650,7 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK // 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; @@ -1712,7 +1693,7 @@ std::cout << "BEFORE DRAW" */ 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 @@ -1852,6 +1833,20 @@ std::cout << "BEFORE DRAW" d->dc[d->level].sizeWnd.y = d->PixelsOutY; } } + else { + /* There are a lot WMF files in circulation with the x,y values in the setwindowext reversed. If this is detected, swap them. + There is a remote possibility that the strange scaling this implies was intended, and those will be rendered incorrectly */ + double Ox = d->PixelsOutX; + double Oy = d->PixelsOutY; + double Wx = d->dc[d->level].sizeWnd.x; + double Wy = d->dc[d->level].sizeWnd.y; + if(Wx != Wy && Geom::are_near(Ox/Wy, Oy/Wx, 1.01/MIN(Wx,Wy)) ){ + int tmp; + tmp = d->dc[d->level].sizeWnd.x; + d->dc[d->level].sizeWnd.x = d->dc[d->level].sizeWnd.y; + d->dc[d->level].sizeWnd.y = tmp; + } + } if (!d->dc[d->level].sizeView.x || !d->dc[d->level].sizeView.y) { /* Previously it used sizeWnd, but that always resulted in scale = 1 if no viewport ever appeared, and in most files, it did not */ @@ -1984,7 +1979,7 @@ std::cout << "BEFORE DRAW" 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 << " "; @@ -2036,7 +2031,7 @@ std::cout << "BEFORE DRAW" 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 << " "; -- cgit v1.2.3 From eb89a74bb3f220bba82de3c7ce3a73df951fab77 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sat, 8 Mar 2014 22:44:03 -0500 Subject: Remove unused includes to tidy up the code. (bzr r13132) --- src/extension/internal/grid.cpp | 1 + src/extension/internal/metafile-inout.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'src/extension/internal') diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index c2ef2b27c..c120df719 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -29,6 +29,7 @@ #include "selection.h" #include "sp-object.h" #include "util/glib-list-iterators.h" +#include "2geom/geom.h" #include "svg/path-string.h" diff --git a/src/extension/internal/metafile-inout.cpp b/src/extension/internal/metafile-inout.cpp index c7ae53370..1d419a6a0 100644 --- a/src/extension/internal/metafile-inout.cpp +++ b/src/extension/internal/metafile-inout.cpp @@ -17,6 +17,7 @@ #include #include +#include "display/curve.h" #include "extension/internal/metafile-inout.h" // picks up PNG #include "extension/print.h" #include "path-prefix.h" -- cgit v1.2.3 From 1d31728fb7399f48d272560a290dc990b75a197e Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 11 Mar 2014 15:52:08 +0100 Subject: Change stroke-dasharray and stroke-dashoffset handling to match other properties. Split style.h into more manageable size files. (bzr r13135) --- src/extension/internal/cairo-render-context.cpp | 10 +++- src/extension/internal/emf-inout.cpp | 77 +++++++++++-------------- src/extension/internal/emf-print.cpp | 25 ++++---- src/extension/internal/javafx-out.cpp | 18 +++--- src/extension/internal/latex-pstricks.cpp | 9 +-- src/extension/internal/wmf-inout.cpp | 43 ++++++-------- src/extension/internal/wmf-print.cpp | 13 ++--- 7 files changed, 88 insertions(+), 107 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 2916d9fa9..4ec6ae1c8 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -1297,10 +1297,14 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p } } - if (style->stroke_dash.n_dash && - style->stroke_dash.dash ) + if (!style->stroke_dasharray.values.empty()) { - cairo_set_dash(_cr, style->stroke_dash.dash, style->stroke_dash.n_dash, style->stroke_dash.offset); + size_t ndashes = style->stroke_dasharray.values.size(); + double* dashes =(double*)malloc(ndashes*sizeof(double)); + for( unsigned i = 0; i < ndashes; ++i ) { + dashes[i] = style->stroke_dasharray.values[i]; + } + cairo_set_dash(_cr, dashes, ndashes, style->stroke_dashoffset.value); } else { cairo_set_dash(_cr, NULL, 0, 0.0); // disable dashing } diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index b73c5e9e5..bbbce46e7 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -915,14 +915,14 @@ Emf::output_style(PEMF_CALLBACK_DATA d, int iType) tmp_style << "stroke-miterlimit:" << MAX( 2.0, d->dc[d->level].style.stroke_miterlimit.value ) << ";"; - if (d->dc[d->level].style.stroke_dasharray_set && - d->dc[d->level].style.stroke_dash.n_dash && d->dc[d->level].style.stroke_dash.dash) + if (d->dc[d->level].style.stroke_dasharray.set && + !d->dc[d->level].style.stroke_dasharray.values.empty() ) { tmp_style << "stroke-dasharray:"; - for (int i=0; idc[d->level].style.stroke_dash.n_dash; i++) { + for (unsigned i=0; idc[d->level].style.stroke_dasharray.values.size(); i++) { if (i) tmp_style << ","; - tmp_style << d->dc[d->level].style.stroke_dash.dash[i]; + tmp_style << d->dc[d->level].style.stroke_dasharray.values[i]; } tmp_style << ";"; tmp_style << "stroke-dashoffset:0;"; @@ -1016,34 +1016,30 @@ Emf::select_pen(PEMF_CALLBACK_DATA d, int index) case U_PS_DASHDOT: case U_PS_DASHDOTDOT: { - int i = 0; int penstyle = (pEmr->lopn.lopnStyle & U_PS_STYLE_MASK); - d->dc[d->level].style.stroke_dash.n_dash = - penstyle == U_PS_DASHDOTDOT ? 6 : penstyle == U_PS_DASHDOT ? 4 : 2; - if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash))) - delete[] d->dc[d->level].style.stroke_dash.dash; - d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash]; + if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values))) + d->dc[d->level].style.stroke_dasharray.values.clear(); if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 3; - d->dc[d->level].style.stroke_dash.dash[i++] = 1; + d->dc[d->level].style.stroke_dasharray.values.push_back( 3 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); } if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 1; - d->dc[d->level].style.stroke_dash.dash[i++] = 1; + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); } if (penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 1; - d->dc[d->level].style.stroke_dash.dash[i++] = 1; + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); } - d->dc[d->level].style.stroke_dasharray_set = 1; + d->dc[d->level].style.stroke_dasharray.set = 1; break; } case U_PS_SOLID: default: { - d->dc[d->level].style.stroke_dasharray_set = 0; + d->dc[d->level].style.stroke_dasharray.set = 0; break; } } @@ -1105,10 +1101,8 @@ Emf::select_extpen(PEMF_CALLBACK_DATA d, int index) case U_PS_USERSTYLE: { if (pEmr->elp.elpNumEntries) { - d->dc[d->level].style.stroke_dash.n_dash = pEmr->elp.elpNumEntries; - if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash))) - delete[] d->dc[d->level].style.stroke_dash.dash; - d->dc[d->level].style.stroke_dash.dash = new double[pEmr->elp.elpNumEntries]; + if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values))) + d->dc[d->level].style.stroke_dasharray.values.clear(); for (unsigned int i=0; ielp.elpNumEntries; i++) { int cur_level = d->level; d->level = d->emf_obj[index].level; @@ -1117,11 +1111,11 @@ Emf::select_extpen(PEMF_CALLBACK_DATA d, int index) // double dash_length = pix_to_abs_size( d, pEmr->elp.elpStyleEntry[i] ); double dash_length = pEmr->elp.elpStyleEntry[i]; d->level = cur_level; - d->dc[d->level].style.stroke_dash.dash[i] = dash_length; + d->dc[d->level].style.stroke_dasharray.values[i] = dash_length; } - d->dc[d->level].style.stroke_dasharray_set = 1; + d->dc[d->level].style.stroke_dasharray.set = 1; } else { - d->dc[d->level].style.stroke_dasharray_set = 0; + d->dc[d->level].style.stroke_dasharray.set = 0; } break; } @@ -1131,27 +1125,23 @@ Emf::select_extpen(PEMF_CALLBACK_DATA d, int index) case U_PS_DASHDOT: case U_PS_DASHDOTDOT: { - int i = 0; int penstyle = (pEmr->elp.elpPenStyle & U_PS_STYLE_MASK); - d->dc[d->level].style.stroke_dash.n_dash = - penstyle == U_PS_DASHDOTDOT ? 6 : penstyle == U_PS_DASHDOT ? 4 : 2; - if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash))) - delete[] d->dc[d->level].style.stroke_dash.dash; - d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash]; + if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values))) + d->dc[d->level].style.stroke_dasharray.values.clear(); if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 3; - d->dc[d->level].style.stroke_dash.dash[i++] = 2; + d->dc[d->level].style.stroke_dasharray.values.push_back( 3 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 2 ); } if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 1; - d->dc[d->level].style.stroke_dash.dash[i++] = 2; + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 2 ); } if (penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 1; - d->dc[d->level].style.stroke_dash.dash[i++] = 2; + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 2 ); } - d->dc[d->level].style.stroke_dasharray_set = 1; + d->dc[d->level].style.stroke_dasharray.set = 1; break; } case U_PS_SOLID: @@ -1163,7 +1153,7 @@ Emf::select_extpen(PEMF_CALLBACK_DATA d, int index) */ default: { - d->dc[d->level].style.stroke_dasharray_set = 0; + d->dc[d->level].style.stroke_dasharray.set = 0; break; } } @@ -2209,8 +2199,8 @@ std::cout << "BEFORE DRAW" d->level = d->level + pEmr->iRelative; } while (old_level > d->level) { - if (d->dc[old_level].style.stroke_dash.dash && (old_level==0 || (old_level>0 && d->dc[old_level].style.stroke_dash.dash!=d->dc[old_level-1].style.stroke_dash.dash))){ - delete[] d->dc[old_level].style.stroke_dash.dash; + if (!d->dc[old_level].style.stroke_dasharray.values.empty() && (old_level==0 || (old_level>0 && d->dc[old_level].style.stroke_dasharray.values!=d->dc[old_level-1].style.stroke_dasharray.values))){ + d->dc[old_level].style.stroke_dasharray.values.clear(); } if(d->dc[old_level].font_name){ free(d->dc[old_level].font_name); // else memory leak @@ -2387,7 +2377,7 @@ std::cout << "BEFORE DRAW" case U_WHITE_PEN: { float val = index == U_BLACK_PEN ? 0 : 1; - d->dc[d->level].style.stroke_dasharray_set = 0; + d->dc[d->level].style.stroke_dasharray.set = 0; d->dc[d->level].style.stroke_width.value = 1.0; d->dc[d->level].style.stroke.value.color.set( val, val, val ); @@ -3452,8 +3442,7 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) delete[] d.emf_obj; } - if (d.dc[0].style.stroke_dash.dash) - delete[] d.dc[0].style.stroke_dash.dash; + d.dc[0].style.stroke_dasharray.values.clear(); for(int i=0; i<=d.level;i++){ if(d.dc[i].font_name)free(d.dc[i].font_name); diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index c103100b3..9cc662a27 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -683,25 +683,24 @@ int PrintEmf::create_pen(SPStyle const *style, const Geom::Affine &transform) linejoin = U_PS_JOIN_BEVEL; } - if (style->stroke_dash.n_dash && - style->stroke_dash.dash) { + if (!style->stroke_dasharray.values.empty()) { if (FixPPTDashLine) { // will break up line into many smaller lines. Override gradient if that was set, cannot do both. brushStyle = U_BS_SOLID; hatchType = U_HS_HORIZONTAL; } else { - int i = 0; - while ((linestyle != U_PS_USERSTYLE) && (i < style->stroke_dash.n_dash)) { - if (style->stroke_dash.dash[i] > 0.00000001) { + unsigned i = 0; + while ((linestyle != U_PS_USERSTYLE) && (i < style->stroke_dasharray.values.size())) { + if (style->stroke_dasharray.values[i] > 0.00000001) { linestyle = U_PS_USERSTYLE; } i++; } if (linestyle == U_PS_USERSTYLE) { - n_dash = style->stroke_dash.n_dash; + n_dash = style->stroke_dasharray.values.size(); dash = new uint32_t[n_dash]; - for (i = 0; i < style->stroke_dash.n_dash; i++) { - dash[i] = (uint32_t)(Inkscape::Util::Quantity::convert(1, "mm", "px") * style->stroke_dash.dash[i]); + for (i = 0; i < n_dash; i++) { + dash[i] = (uint32_t)(Inkscape::Util::Quantity::convert(1, "mm", "px") * style->stroke_dasharray.values[i]); } } } @@ -1259,7 +1258,7 @@ unsigned int PrintEmf::fill( } if ( (style->stroke.isNone() || style->stroke.noneSet || style->stroke_width.computed == 0.0) || - (style->stroke_dash.n_dash && style->stroke_dash.dash && FixPPTDashLine) || + (!style->stroke_dasharray.values.empty() && FixPPTDashLine) || !all_closed ) { print_pathv(pathv, fill_transform); // do any fills. side effect: clears fill_pathv @@ -1287,13 +1286,13 @@ unsigned int PrintEmf::stroke( return 0; } - if (style->stroke_dash.n_dash && style->stroke_dash.dash && FixPPTDashLine) { + if (!style->stroke_dasharray.values.empty() && FixPPTDashLine) { // convert the path, gets its complete length, and then make a new path with parameter length instead of t Geom::Piecewise > tmp_pathpw; // pathv-> sbasis Geom::Piecewise > tmp_pathpw2; // sbasis using arc length parameter Geom::Piecewise > tmp_pathpw3; // new (discontinuous) path, composed of dots/dashes Geom::Piecewise > first_frag; // first fragment, will be appended at end - int n_dash = style->stroke_dash.n_dash; + int n_dash = style->stroke_dasharray.values.size(); int i = 0; //dash index double tlength; // length of tmp_pathpw double slength = 0.0; // start of gragment @@ -1306,7 +1305,7 @@ unsigned int PrintEmf::stroke( // go around the dash array repeatedly until the entire path is consumed (but not beyond). while (slength < tlength) { - elength = slength + style->stroke_dash.dash[i++]; + elength = slength + style->stroke_dasharray.values[i++]; if (elength > tlength) { elength = tlength; } @@ -1317,7 +1316,7 @@ unsigned int PrintEmf::stroke( first_frag = fragment; } slength = elength; - slength += style->stroke_dash.dash[i++]; // the gap + slength += style->stroke_dasharray.values[i++]; // the gap if (i >= n_dash) { i = 0; } diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp index e51e8d539..19946022c 100644 --- a/src/extension/internal/javafx-out.cpp +++ b/src/extension/internal/javafx-out.cpp @@ -418,10 +418,8 @@ bool JavaFXOutput::doStyle(SPStyle *style) * SPIEnum stroke_linecap; * SPIEnum stroke_linejoin; * SPIFloat stroke_miterlimit; - * NRVpathDash stroke_dash; - * unsigned stroke_dasharray_set : 1; - * unsigned stroke_dasharray_inherit : 1; - * unsigned stroke_dashoffset_set : 1; + * SPIDashArray stroke_dasharray; + * SPILength stroke_dashoffset; * SPIScale24 stroke_opacity; */ if (style->stroke_opacity.value > 0) @@ -436,16 +434,16 @@ bool JavaFXOutput::doStyle(SPStyle *style) out(" strokeLineCap: %s\n", getStrokeLineCap(linecap).c_str()); out(" strokeLineJoin: %s\n", getStrokeLineJoin(linejoin).c_str()); out(" strokeMiterLimit: %s\n", DSTR(style->stroke_miterlimit.value)); - if (style->stroke_dasharray_set) { - if (style->stroke_dashoffset_set) { - out(" strokeDashOffset: %s\n", DSTR(style->stroke_dash.offset)); + if (style->stroke_dasharray.set) { + if (style->stroke_dashoffset.set) { + out(" strokeDashOffset: %s\n", DSTR(style->stroke_dashoffset.value)); } out(" strokeDashArray: [ "); - for(int i = 0; i < style->stroke_dash.n_dash; i++ ) { + for(unsigned i = 0; i < style->stroke_dasharray.values.size(); i++ ) { if (i > 0) { - out(", %.2lf", style->stroke_dash.dash[i]); + out(", %.2lf", style->stroke_dasharray.values[i]); }else { - out(" %.2lf", style->stroke_dash.dash[i]); + out(" %.2lf", style->stroke_dasharray.values[i]); } } out(" ]\n"); diff --git a/src/extension/internal/latex-pstricks.cpp b/src/extension/internal/latex-pstricks.cpp index c8e8e2f2e..6aaa1bca4 100644 --- a/src/extension/internal/latex-pstricks.cpp +++ b/src/extension/internal/latex-pstricks.cpp @@ -239,16 +239,13 @@ unsigned int PrintLatex::stroke(Inkscape::Extension::Print * /*mod*/, os<<",strokeopacity="<stroke_dasharray_set && - style->stroke_dash.n_dash && - style->stroke_dash.dash) { - int i; + if (style->stroke_dasharray.set && !style->stroke_dasharray.values.empty()) { os << ",linestyle=dashed,dash="; - for (i = 0; i < style->stroke_dash.n_dash; i++) { + for (unsigned i = 0; i < style->stroke_dasharray.values.size(); i++) { if ((i)) { os << " "; } - os << style->stroke_dash.dash[i]; + os << style->stroke_dasharray.values[i]; } } diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 3a62c9c16..906c40301 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -820,14 +820,14 @@ Wmf::output_style(PWMF_CALLBACK_DATA d) tmp_style << "stroke-miterlimit:" << MAX( 2.0, d->dc[d->level].style.stroke_miterlimit.value ) << ";"; - if (d->dc[d->level].style.stroke_dasharray_set && - d->dc[d->level].style.stroke_dash.n_dash && d->dc[d->level].style.stroke_dash.dash) + if (d->dc[d->level].style.stroke_dasharray.set && + !d->dc[d->level].style.stroke_dasharray.values.empty()) { tmp_style << "stroke-dasharray:"; - for (int i=0; idc[d->level].style.stroke_dash.n_dash; i++) { + for (unsigned i=0; idc[d->level].style.stroke_dasharray.values.size(); i++) { if (i) tmp_style << ","; - tmp_style << d->dc[d->level].style.stroke_dash.dash[i]; + tmp_style << d->dc[d->level].style.stroke_dasharray.values[i]; } tmp_style << ";"; tmp_style << "stroke-dashoffset:0;"; @@ -920,34 +920,30 @@ Wmf::select_pen(PWMF_CALLBACK_DATA d, int index) case U_PS_DASHDOT: case U_PS_DASHDOTDOT: { - int i = 0; int penstyle = (up.Style & U_PS_STYLE_MASK); - d->dc[d->level].style.stroke_dash.n_dash = - penstyle == U_PS_DASHDOTDOT ? 6 : penstyle == U_PS_DASHDOT ? 4 : 2; - if (d->dc[d->level].style.stroke_dash.dash && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dash.dash!=d->dc[d->level-1].style.stroke_dash.dash))) - delete[] d->dc[d->level].style.stroke_dash.dash; - d->dc[d->level].style.stroke_dash.dash = new double[d->dc[d->level].style.stroke_dash.n_dash]; + if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values))) + d->dc[d->level].style.stroke_dasharray.values.clear(); if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 3; - d->dc[d->level].style.stroke_dash.dash[i++] = 1; + d->dc[d->level].style.stroke_dasharray.values.push_back( 3 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); } if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 1; - d->dc[d->level].style.stroke_dash.dash[i++] = 1; + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); } if (penstyle==U_PS_DASHDOTDOT) { - d->dc[d->level].style.stroke_dash.dash[i++] = 1; - d->dc[d->level].style.stroke_dash.dash[i++] = 1; + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); + d->dc[d->level].style.stroke_dasharray.values.push_back( 1 ); } - d->dc[d->level].style.stroke_dasharray_set = 1; + d->dc[d->level].style.stroke_dasharray.set = 1; break; } case U_PS_SOLID: default: { - d->dc[d->level].style.stroke_dasharray_set = 0; + d->dc[d->level].style.stroke_dasharray.set = 0; break; } } @@ -1174,7 +1170,7 @@ Wmf::delete_object(PWMF_CALLBACK_DATA d, int index) // If the active object is deleted set default draw values if(index == d->dc[d->level].active_pen){ // Use default pen: solid, black, 1 pixel wide d->dc[d->level].active_pen = -1; - d->dc[d->level].style.stroke_dasharray_set = 0; + d->dc[d->level].style.stroke_dasharray.set = 0; d->dc[d->level].style.stroke_linecap.computed = 2; // U_PS_ENDCAP_SQUARE d->dc[d->level].style.stroke_linejoin.computed = 0; // U_PS_JOIN_MITER; d->dc[d->level].stroke_set = true; @@ -2310,8 +2306,8 @@ std::cout << "BEFORE DRAW" d->level = d->level + DC; } while (old_level > d->level) { - if (d->dc[old_level].style.stroke_dash.dash && (old_level==0 || (old_level>0 && d->dc[old_level].style.stroke_dash.dash!=d->dc[old_level-1].style.stroke_dash.dash))){ - delete[] d->dc[old_level].style.stroke_dash.dash; + if (!d->dc[old_level].style.stroke_dasharray.values.empty() && (old_level==0 || (old_level>0 && d->dc[old_level].style.stroke_dasharray.values!=d->dc[old_level-1].style.stroke_dasharray.values))){ + d->dc[old_level].style.stroke_dasharray.values.clear(); } if(d->dc[old_level].font_name){ free(d->dc[old_level].font_name); // else memory leak @@ -2976,7 +2972,7 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) d.dc[0].bkMode = U_TRANSPARENT; d.dc[0].dirty = 0; // Default pen, WMF files that do not specify a pen are unlikely to look very good! - d.dc[0].style.stroke_dasharray_set = 0; + d.dc[0].style.stroke_dasharray.set = 0; d.dc[0].style.stroke_linecap.computed = 2; // U_PS_ENDCAP_SQUARE; d.dc[0].style.stroke_linejoin.computed = 0; // U_PS_JOIN_MITER; d.dc[0].stroke_set = true; @@ -3051,8 +3047,7 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) delete[] d.wmf_obj; } - if (d.dc[0].style.stroke_dash.dash) - delete[] d.dc[0].style.stroke_dash.dash; + d.dc[0].style.stroke_dasharray.values.clear(); for(int i=0; i<=d.level;i++){ if(d.dc[i].font_name)free(d.dc[i].font_name); diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp index 32c7ac0bd..232891c9c 100644 --- a/src/extension/internal/wmf-print.cpp +++ b/src/extension/internal/wmf-print.cpp @@ -596,8 +596,7 @@ int PrintWmf::create_pen(SPStyle const *style, const Geom::Affine &transform) modstyle |= U_PS_JOIN_BEVEL; } - if (style->stroke_dash.n_dash && - style->stroke_dash.dash) { + if (!style->stroke_dasharray.values.empty()) { if (!FixPPTDashLine) { // if this is set code elsewhere will break dots/dashes into many smaller lines. penstyle = U_PS_DASH;// userstyle not supported apparently, for now map all Inkscape dot/dash to just dash } @@ -824,7 +823,7 @@ unsigned int PrintWmf::fill( } if ( (style->stroke.isNone() || style->stroke.noneSet || style->stroke_width.computed == 0.0) || - (style->stroke_dash.n_dash && style->stroke_dash.dash && FixPPTDashLine) || + (!style->stroke_dasharray.values.empty() && FixPPTDashLine) || !all_closed ) { print_pathv(pathv, fill_transform); // do any fills. side effect: clears fill_pathv @@ -852,13 +851,13 @@ unsigned int PrintWmf::stroke( return 0; } - if (style->stroke_dash.n_dash && style->stroke_dash.dash && FixPPTDashLine) { + if (!style->stroke_dasharray.values.empty() && FixPPTDashLine) { // convert the path, gets its complete length, and then make a new path with parameter length instead of t Geom::Piecewise > tmp_pathpw; // pathv-> sbasis Geom::Piecewise > tmp_pathpw2; // sbasis using arc length parameter Geom::Piecewise > tmp_pathpw3; // new (discontinuous) path, composed of dots/dashes Geom::Piecewise > first_frag; // first fragment, will be appended at end - int n_dash = style->stroke_dash.n_dash; + int n_dash = style->stroke_dasharray.values.size(); int i = 0; //dash index double tlength; // length of tmp_pathpw double slength = 0.0; // start of gragment @@ -871,7 +870,7 @@ unsigned int PrintWmf::stroke( // go around the dash array repeatedly until the entire path is consumed (but not beyond). while (slength < tlength) { - elength = slength + style->stroke_dash.dash[i++]; + elength = slength + style->stroke_dasharray.values[i++]; if (elength > tlength) { elength = tlength; } @@ -882,7 +881,7 @@ unsigned int PrintWmf::stroke( first_frag = fragment; } slength = elength; - slength += style->stroke_dash.dash[i++]; // the gap + slength += style->stroke_dasharray.values[i++]; // the gap if (i >= n_dash) { i = 0; } -- cgit v1.2.3 From b389a703003a324321822e6f0f991d7bbc4531e0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 13 Mar 2014 01:11:43 +0100 Subject: pdfinput: Do not use an extremely ugly static variable in SvgBuilder (bzr r13142) --- src/extension/internal/pdfinput/svg-builder.cpp | 56 ++++++++++++------------- src/extension/internal/pdfinput/svg-builder.h | 2 + 2 files changed, 30 insertions(+), 28 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index 20cd74cdb..680e6ca94 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -56,9 +56,6 @@ namespace Internal { #define TRACE(_args) IFTRACE(g_print _args) -static double ttm[6] = {1, 0, 0, 1, 0, 0}; // temporary transform matrix -static bool ttm_is_set = false; // flag to forbid setting ttm - /** * \struct SvgTransparencyGroup * \brief Holds information about a PDF transparency group @@ -94,6 +91,9 @@ SvgBuilder::SvgBuilder(SPDocument *document, gchar *docname, XRef *xref) _preferences = _xml_doc->createElement("svgbuilder:prefs"); _preferences->setAttribute("embedImages", "1"); _preferences->setAttribute("localFonts", "1"); + + _ttm[0] = 1; _ttm[1] = 0; _ttm[2] = 0; _ttm[3] = 1; _ttm[4] = 0; _ttm[5] = 0; + _ttm_is_set = false; } SvgBuilder::SvgBuilder(SvgBuilder *parent, Inkscape::XML::Node *root) { @@ -216,9 +216,9 @@ Inkscape::XML::Node *SvgBuilder::pushGroup() { } } if (_container->parent()->attribute("inkscape:groupmode") != NULL) { - ttm[0] = ttm[3] = 1.0; // clear ttm if parent is a layer - ttm[1] = ttm[2] = ttm[4] = ttm[5] = 0.0; - ttm_is_set = false; + _ttm[0] = _ttm[3] = 1.0; // clear ttm if parent is a layer + _ttm[1] = _ttm[2] = _ttm[4] = _ttm[5] = 0.0; + _ttm_is_set = false; } return _container; } @@ -570,14 +570,14 @@ bool SvgBuilder::getTransform(double *transform) { void SvgBuilder::setTransform(double c0, double c1, double c2, double c3, double c4, double c5) { // do not remember the group which is a layer - if ((_container->attribute("inkscape:groupmode") == NULL) && !ttm_is_set) { - ttm[0] = c0; - ttm[1] = c1; - ttm[2] = c2; - ttm[3] = c3; - ttm[4] = c4; - ttm[5] = c5; - ttm_is_set = true; + if ((_container->attribute("inkscape:groupmode") == NULL) && !_ttm_is_set) { + _ttm[0] = c0; + _ttm[1] = c1; + _ttm[2] = c2; + _ttm[3] = c3; + _ttm[4] = c4; + _ttm[5] = c5; + _ttm_is_set = true; } // Avoid transforming a group with an already set clip-path @@ -633,15 +633,15 @@ gchar *SvgBuilder::_createPattern(GfxPattern *pattern, GfxState *state, bool is_ // construct a (pattern space) -> (current space) transform matrix ptm = shading_pattern->getMatrix(); - det = ttm[0] * ttm[3] - ttm[1] * ttm[2]; + det = _ttm[0] * _ttm[3] - _ttm[1] * _ttm[2]; if (det) { double ittm[6]; // invert ttm - ittm[0] = ttm[3] / det; - ittm[1] = -ttm[1] / det; - ittm[2] = -ttm[2] / det; - ittm[3] = ttm[0] / det; - ittm[4] = (ttm[2] * ttm[5] - ttm[3] * ttm[4]) / det; - ittm[5] = (ttm[1] * ttm[4] - ttm[0] * ttm[5]) / det; + ittm[0] = _ttm[3] / det; + ittm[1] = -_ttm[1] / det; + ittm[2] = -_ttm[2] / det; + ittm[3] = _ttm[0] / det; + ittm[4] = (_ttm[2] * _ttm[5] - _ttm[3] * _ttm[4]) / det; + ittm[5] = (_ttm[1] * _ttm[4] - _ttm[0] * _ttm[5]) / det; m[0] = ptm[0] * ittm[0] + ptm[1] * ittm[2]; m[1] = ptm[0] * ittm[1] + ptm[1] * ittm[3]; m[2] = ptm[2] * ittm[0] + ptm[3] * ittm[2]; @@ -676,15 +676,15 @@ gchar *SvgBuilder::_createTilingPattern(GfxTilingPattern *tiling_pattern, double *p2u = tiling_pattern->getMatrix(); double m[6] = {1, 0, 0, 1, 0, 0}; double det; - det = ttm[0] * ttm[3] - ttm[1] * ttm[2]; // see LP Bug 1168908 + det = _ttm[0] * _ttm[3] - _ttm[1] * _ttm[2]; // see LP Bug 1168908 if (det) { double ittm[6]; // invert ttm - ittm[0] = ttm[3] / det; - ittm[1] = -ttm[1] / det; - ittm[2] = -ttm[2] / det; - ittm[3] = ttm[0] / det; - ittm[4] = (ttm[2] * ttm[5] - ttm[3] * ttm[4]) / det; - ittm[5] = (ttm[1] * ttm[4] - ttm[0] * ttm[5]) / det; + ittm[0] = _ttm[3] / det; + ittm[1] = -_ttm[1] / det; + ittm[2] = -_ttm[2] / det; + ittm[3] = _ttm[0] / det; + ittm[4] = (_ttm[2] * _ttm[5] - _ttm[3] * _ttm[4]) / det; + ittm[5] = (_ttm[1] * _ttm[4] - _ttm[0] * _ttm[5]) / det; m[0] = p2u[0] * ittm[0] + p2u[1] * ittm[2]; m[1] = p2u[0] * ittm[1] + p2u[1] * ittm[3]; m[2] = p2u[2] * ittm[0] + p2u[3] * ittm[2]; diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h index 610822959..f1ce02cf0 100644 --- a/src/extension/internal/pdfinput/svg-builder.h +++ b/src/extension/internal/pdfinput/svg-builder.h @@ -223,6 +223,8 @@ private: Inkscape::XML::Node *_preferences; // Preferences container node double _width; // Document size in px double _height; // Document size in px + double _ttm[6]; ///< temporary transform matrix + bool _ttm_is_set; }; -- cgit v1.2.3 From 11ed091ae647cd7e56ec5a60359b293b94a3bfec Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 13 Mar 2014 01:15:11 +0100 Subject: Render zero-width PDF lines as 1px lines compensated for current transform. Partially fixes import of some LibreOffice charts. See LP bug #1283537 Fixed bugs: - https://launchpad.net/bugs/1283537 (bzr r13143) --- src/extension/internal/pdfinput/pdf-parser.cpp | 5 +---- src/extension/internal/pdfinput/svg-builder.cpp | 17 ++++++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 7edb758fd..30e120d26 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -718,10 +718,7 @@ void PdfParser::opSetMiterLimit(Object args[], int /*numArgs*/) // TODO not good that numArgs is ignored but args[] is used: void PdfParser::opSetLineWidth(Object args[], int /*numArgs*/) { - if (args[0].getNum() > 0.0) - state->setLineWidth(args[0].getNum()); - else - state->setLineWidth(1.0); // default + state->setLineWidth(args[0].getNum()); builder->updateStyle(state); } diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index 680e6ca94..71e6dc6ae 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -298,14 +298,6 @@ static gchar *svgInterpretPath(GfxPath *path) { * Uses the given SPCSSAttr for storing the style properties */ void SvgBuilder::_setStrokeStyle(SPCSSAttr *css, GfxState *state) { - - // Check line width - if ( state->getLineWidth() <= 0.0 ) { - // Ignore stroke - sp_repr_css_set_property(css, "stroke", "none"); - return; - } - // Stroke color/pattern if ( state->getStrokeColorSpace()->getMode() == csPattern ) { gchar *urltext = _createPattern(state->getStrokePattern(), state, true); @@ -326,7 +318,14 @@ void SvgBuilder::_setStrokeStyle(SPCSSAttr *css, GfxState *state) { // Line width Inkscape::CSSOStringStream os_width; - os_width << state->getLineWidth(); + double lw = state->getLineWidth(); + if (lw > 0.0) { + os_width << lw; + } else { + // emit a stroke which is 1px in toplevel user units + double pxw = Inkscape::Util::Quantity::convert(1.0, "pt", "px"); + os_width << 1.0 / state->transformWidth(pxw); + } sp_repr_css_set_property(css, "stroke-width", os_width.str().c_str()); // Line cap -- cgit v1.2.3 From b74a8597149d17529201fb8c9d9a92e29cc821ad Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 17 Mar 2014 18:52:59 -0700 Subject: Warning cleanups. (bzr r13162) --- src/extension/internal/emf-print.cpp | 2 +- src/extension/internal/wmf-print.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 9cc662a27..4bb892821 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -1562,7 +1562,7 @@ unsigned int PrintEmf::image( unsigned int h, /** height of bitmap */ unsigned int rs, /** row stride (normally w*4) */ Geom::Affine const &tf_rect, /** affine transform only used for defining location and size of rect, for all other tranforms, use the one from m_tr_stack */ - SPStyle const *style) /** provides indirect link to image object */ + SPStyle const * /*style*/) /** provides indirect link to image object */ { double x1, y1, dw, dh; char *rec = NULL; diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp index 232891c9c..5a552ad83 100644 --- a/src/extension/internal/wmf-print.cpp +++ b/src/extension/internal/wmf-print.cpp @@ -1103,7 +1103,7 @@ unsigned int PrintWmf::image( unsigned int h, /** height of bitmap */ unsigned int rs, /** row stride (normally w*4) */ Geom::Affine const &tf_rect, /** affine transform only used for defining location and size of rect, for all other tranforms, use the one from m_tr_stack */ - SPStyle const *style) /** provides indirect link to image object */ + SPStyle const * /*style*/) /** provides indirect link to image object */ { double x1, y1, dw, dh; char *rec = NULL; -- cgit v1.2.3 From 165e7e7006b009a79ec27a68c513727905ef3442 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 17 Mar 2014 19:30:17 -0700 Subject: Cleanup datatypes for detailed checking of C++11. Fixes Bug #1293295. Fixed bugs: - https://launchpad.net/bugs/1293295 (bzr r13163) --- src/extension/internal/grid.cpp | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index c120df719..0059bbec2 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -59,31 +59,31 @@ Grid::load (Inkscape::Extension::Extension */*module*/) namespace { Glib::ustring build_lines(Geom::Rect bounding_area, - float offset[], float spacing[]) + Geom::Point const &offset, Geom::Point const &spacing) { Geom::Point point_offset(0.0, 0.0); SVG::PathString path_data; - for ( int axis = 0 ; axis < 2 ; ++axis ) { + for ( int axis = Geom::X ; axis <= Geom::Y ; ++axis ) { point_offset[axis] = offset[axis]; for (Geom::Point start_point = bounding_area.min(); - start_point[axis] + offset[axis] <= (bounding_area.max())[axis]; - start_point[axis] += spacing[axis]) { + start_point[axis] + offset[axis] <= (bounding_area.max())[axis]; + start_point[axis] += spacing[axis]) { Geom::Point end_point = start_point; end_point[1-axis] = (bounding_area.max())[1-axis]; path_data.moveTo(start_point + point_offset) - .lineTo(end_point + point_offset); + .lineTo(end_point + point_offset); } } - // std::cout << "Path data:" << path_data.c_str() << std::endl; - return path_data; - } - + // std::cout << "Path data:" << path_data.c_str() << std::endl; + return path_data; } +} // namespace + /** \brief This actually draws the grid. \param module The effect that was called (unused) @@ -115,16 +115,15 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc gdouble scale = Inkscape::Util::Quantity::convert(1, "px", (document->doc())->getDefaultUnit()); bounding_area *= Geom::Scale(scale); - float spacings[2] = { scale*module->get_param_float("xspacing"), - scale*module->get_param_float("yspacing") }; - float line_width = scale*module->get_param_float("lineWidth"); - float offsets[2] = { scale*module->get_param_float("xoffset"), - scale*module->get_param_float("yoffset") }; + Geom::Point spacings( scale * module->get_param_float("xspacing"), + scale * module->get_param_float("yspacing") ); + gdouble line_width = scale * module->get_param_float("lineWidth"); + Geom::Point offsets( scale * module->get_param_float("xoffset"), + scale * module->get_param_float("yoffset") ); Glib::ustring path_data(""); - path_data = build_lines(bounding_area, - offsets, spacings); + path_data = build_lines(bounding_area, offsets, spacings); Inkscape::XML::Document * xml_doc = document->doc()->getReprDoc(); //XML Tree being used directly here while it shouldn't be. @@ -144,9 +143,7 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc path->setAttribute("style", style.c_str()); current_layer->appendChild(path); - Inkscape::GC::release(path); - - return; + Inkscape::GC::release(path); } /** \brief A class to make an adjustment that uses Extension params */ -- cgit v1.2.3 From 6f05665abf781f0fb1c1baf5f6ac6662abf6ecfe Mon Sep 17 00:00:00 2001 From: David Mathog Date: Wed, 19 Mar 2014 19:08:48 +0100 Subject: EMF import: fix clipPath definition: move transform attribute into the element (bug #1294713) Fixed bugs: - https://launchpad.net/bugs/1294713 (bzr r13166) --- src/extension/internal/emf-inout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index bbbce46e7..a4d204472 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -2163,9 +2163,9 @@ std::cout << "BEFORE DRAW" tmp_rectangle << "\n x=\"" << dx << "\" "; tmp_rectangle << "\n y=\"" << dy << "\" "; tmp_rectangle << "\n width=\"" << dw << "\" "; - tmp_rectangle << "\n height=\"" << dh << "\" />"; + tmp_rectangle << "\n height=\"" << dh << "\" "; tmp_rectangle << "\n transform=" << current_matrix(d, dx, dy, 1); // calculate appropriate offset - tmp_rectangle << "\n"; + tmp_rectangle << "/>\n"; *(d->outdef) += tmp_rectangle.str().c_str(); *(d->path) = ""; -- cgit v1.2.3 From 47ccee249363ab2106aa0a07a669efdaea06a34f Mon Sep 17 00:00:00 2001 From: David Mathog Date: Wed, 19 Mar 2014 23:03:52 +0100 Subject: WMF support: last piece of the code cleanup from bug #1248753 Fixed bugs: - https://launchpad.net/bugs/1248753 (bzr r13167) --- src/extension/internal/wmf-inout.cpp | 113 +++++++++++++++-------------------- 1 file changed, 49 insertions(+), 64 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 906c40301..9980d9d6d 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -445,9 +445,9 @@ int Wmf::in_images(PWMF_CALLBACK_DATA d, char *test){ 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; @@ -480,6 +480,7 @@ uint32_t Wmf::add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsa } } } + 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 ); @@ -1248,13 +1249,11 @@ void Wmf::common_dib_to_image(PWMF_CALLBACK_DATA d, const char *dib, 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 Date: Thu, 20 Mar 2014 23:13:18 +0100 Subject: remove #pragma for 11 year old compiler that I cannot imagine anyone using at this point (bzr r13174) --- src/extension/internal/pdfinput/pdf-parser.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 30e120d26..b398486e6 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -76,10 +76,6 @@ extern "C" { // Operator table //------------------------------------------------------------------------ -#ifdef WIN32 // this works around a bug in the VC7 compiler -# pragma optimize("",off) -#endif - PdfOperator PdfParser::opTab[] = { {"\"", 3, {tchkNum, tchkNum, tchkString}, &PdfParser::opMoveSetShowText}, @@ -249,10 +245,6 @@ PdfOperator PdfParser::opTab[] = { &PdfParser::opCurveTo2} }; -#ifdef WIN32 // this works around a bug in the VC7 compiler -# pragma optimize("",on) -#endif - #define numOps (sizeof(opTab) / sizeof(PdfOperator)) //------------------------------------------------------------------------ -- cgit v1.2.3 From 2152c53fe2292956b122e1fab16775e4727ee516 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Fri, 21 Mar 2014 18:59:26 +0100 Subject: cairo-render-context: swap order of header inclusion to redefinition clash of #define STRICT in pangowin32.h with windef.h (pango should check if STRICT is already defined or not) (bzr r13180) --- src/extension/internal/cairo-render-context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 4ec6ae1c8..c09b8e9c8 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -72,8 +72,8 @@ #include #endif #ifdef CAIRO_HAS_WIN32_FONT -#include #include +#include #endif #include -- cgit v1.2.3 From de8450cc3161988edb0ffb713d94fe10bb5412e6 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sun, 23 Mar 2014 17:02:42 +0100 Subject: emf-print.cpp : fix coding... :'( (bzr r13189) --- src/extension/internal/emf-print.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 4bb892821..ed25bf767 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -915,17 +915,13 @@ int PrintEmf::vector_rect_alignment(double angle, Geom::Point vtest){ are slightly displaced. */ Geom::Point PrintEmf::get_pathrect_corner(Geom::Path pathRect, double angle, int corner){ - Geom::Point v1 = Geom::Point(1,0) * Geom::Rotate(-angle); // unit horizontal side (sign change because Y increases DOWN) - Geom::Point v2 = Geom::Point(0,1) * Geom::Rotate(-angle); // unit vertical side (sign change because Y increases DOWN) - Geom::Point center, P1; - int LR; // 1 if Left, 0 if Right - int UL; // 1 if Lower, 0 if Upper (as viewed on screen, y coordinates increase downwards) - center = Geom::Point(0,0); - Geom::Path::const_iterator cit = pathRect.begin(); - for(; cit != pathRect.end_open();++cit) { + Geom::Point center(0,0); + for(Geom::Path::const_iterator cit = pathRect.begin(); cit != pathRect.end_open(); ++cit) { center += cit->initialPoint()/4.0; } + int LR; // 1 if Left, 0 if Right + int UL; // 1 if Lower, 0 if Upper (as viewed on screen, y coordinates increase downwards) switch(corner){ case 1: //UR LR = 0; @@ -944,11 +940,15 @@ Geom::Point PrintEmf::get_pathrect_corner(Geom::Path pathRect, double angle, int UL = 0; break; } - cit = pathRect.begin(); - for(int i; cit != pathRect.end_open();++cit,i++) { + + Geom::Point v1 = Geom::Point(1,0) * Geom::Rotate(-angle); // unit horizontal side (sign change because Y increases DOWN) + Geom::Point v2 = Geom::Point(0,1) * Geom::Rotate(-angle); // unit vertical side (sign change because Y increases DOWN) + Geom::Point P1; + for(Geom::Path::const_iterator cit = pathRect.begin(); cit != pathRect.end_open(); ++cit) { P1 = cit->initialPoint(); - if((LR == (dot(P1 - center,v1)> 0 ? 0 : 1)) && - (UL == (dot(P1 - center,v2)> 0 ? 1 : 0)))break; + + if ( ( LR == (dot(P1 - center,v1) > 0 ? 0 : 1) ) + && ( UL == (dot(P1 - center,v2) > 0 ? 1 : 0) ) ) break; } return(P1); } -- cgit v1.2.3 From 2cadb5d282a9371129a28a142508120bd065454a Mon Sep 17 00:00:00 2001 From: David Mathog Date: Tue, 25 Mar 2014 21:14:20 +0100 Subject: Patch for several issues in libuemf. ----- The patch: 1. Removes half a dozen or so code lines that didn't do anything. 2. Fixes a couple of missing tests for pointers which cannot be NULL. (Note that in many instances the pseudoobject functions in upmf.c do accept null pointers because the objects being constructed have optional parts.) 3. There was one "real" potential memory leak (line 6276 in upmf.c, numbers before the patch). I fixed the others too, but they just never happen (iconv would have to fail in some strange way.) There are no (real) memory access violations or memory leaks in any of this either in standalone libUEMF testing or in use as part of Inkscape as determined from valgrind runs. (bzr r13211) --- src/extension/internal/emf-inout.cpp | 2 +- src/extension/internal/emf-print.cpp | 4 +++- src/extension/internal/text_reassemble.c | 5 ++--- src/extension/internal/wmf-inout.cpp | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index a4d204472..eae3bfb5a 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -123,7 +123,7 @@ Emf::print_document_to_file(SPDocument *doc, const gchar *filename) throw Inkscape::Extension::Output::save_failed(); } mod->base->invoke_print(&context); - ret = mod->finish(); + (void) mod->finish(); /* Release arena */ mod->base->invoke_hide(mod->dkey); mod->base = NULL; diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index ed25bf767..f4f7f08cb 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -366,11 +366,13 @@ int PrintEmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) if (!fcolor && style) { if (style->fill.isColor()) { fill_mode = DRAW_PAINT; +#if 0 +// opacity not supported by EMF float opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value); if (opacity <= 0.0) { opacity = 0.0; // basically the same as no fill } - +#endif sp_color_get_rgb_floatv(&style->fill.value.color, rgb); hatchColor = U_RGB(255 * rgb[0], 255 * rgb[1], 255 * rgb[2]); diff --git a/src/extension/internal/text_reassemble.c b/src/extension/internal/text_reassemble.c index e28e5effb..c62c83120 100644 --- a/src/extension/internal/text_reassemble.c +++ b/src/extension/internal/text_reassemble.c @@ -67,8 +67,8 @@ Optional compiler switches for development: File: text_reassemble.c -Version: 0.0.12 -Date: 07-FEB-2014 +Version: 0.0.13 +Date: 24-MAR-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2014 David Mathog and California Institute of Technology (Caltech) @@ -2055,7 +2055,6 @@ void TR_layout_2_svg(TR_INFO *tri){ } - tsp = tpi->chunks; /* over all complex members from phase2. Paragraphs == TR_PARA_* */ for(i=cxi->phase1; iused;i++){ csp = &(cxi->cx[i]); diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 9980d9d6d..ef95dbe45 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -1527,7 +1527,7 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK iType = *(uint8_t *)(contents + off + offsetof(U_METARECORD, iType ) ); if(iType == U_WMR_SETWINDOWEXT){ OK=0; - nSize = U_WMRSETWINDOWEXT_get(contents + off, &Dst); + (void) U_WMRSETWINDOWEXT_get(contents + off, &Dst); Placeable.Dst.right = Dst.x; Placeable.Dst.bottom = Dst.y; } -- cgit v1.2.3 From 9e0bf17c455a81983aeedb26203cfb80442bc630 Mon Sep 17 00:00:00 2001 From: David Mathog Date: Wed, 26 Mar 2014 21:36:31 +0100 Subject: Second patch for analyzer warnings in libuemf. (bzr r13214) --- src/extension/internal/text_reassemble.c | 39 ++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/text_reassemble.c b/src/extension/internal/text_reassemble.c index c62c83120..810e3f8cc 100644 --- a/src/extension/internal/text_reassemble.c +++ b/src/extension/internal/text_reassemble.c @@ -67,8 +67,8 @@ Optional compiler switches for development: File: text_reassemble.c -Version: 0.0.13 -Date: 24-MAR-2014 +Version: 0.0.14 +Date: 25-MAR-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2014 David Mathog and California Institute of Technology (Caltech) @@ -601,10 +601,13 @@ FT_INFO *ftinfo_init(void){ */ int ftinfo_make_insertable(FT_INFO *fti){ int status=0; + FNT_SPECS *tmp; if(!fti)return(2); if(fti->used >= fti->space){ fti->space += ALLOCINFO_CHUNK; - if((fti->fonts = (FNT_SPECS *) realloc(fti->fonts, fti->space * sizeof(FNT_SPECS) ))){ + tmp = (FNT_SPECS *) realloc(fti->fonts, fti->space * sizeof(FNT_SPECS) ); + if(tmp){ + fti->fonts = tmp; memset(&fti->fonts[fti->used],0,(fti->space - fti->used)*sizeof(FNT_SPECS)); } else { @@ -844,10 +847,13 @@ void ftinfo_dump(const FT_INFO *fti){ */ int fsp_alts_make_insertable(FNT_SPECS *fsp){ int status=0; + ALT_SPECS *tmp; if(!fsp)return(2); if(fsp->used >= fsp->space){ fsp->space += ALLOCINFO_CHUNK; - if((fsp->alts = (ALT_SPECS *) realloc(fsp->alts, fsp->space * sizeof(ALT_SPECS) ))){ + tmp = (ALT_SPECS *) realloc(fsp->alts, fsp->space * sizeof(ALT_SPECS) ); + if(tmp){ + fsp->alts = tmp; memset(&fsp->alts[fsp->used],0,(fsp->space - fsp->used)*sizeof(ALT_SPECS)); } else { @@ -912,10 +918,13 @@ int fsp_alts_weight(FNT_SPECS *fsp, uint32_t a_idx){ */ int csp_make_insertable(CHILD_SPECS *csp){ int status=0; + int *tmp; if(!csp)return(2); if(csp->used >= csp->space){ csp->space += ALLOCINFO_CHUNK; - if((csp->members = (int *) realloc(csp->members, csp->space * sizeof(int) ))){ + tmp = (int *) realloc(csp->members, csp->space * sizeof(int) ); + if(tmp){ + csp->members = tmp; memset(&csp->members[csp->used],0,(csp->space - csp->used)*sizeof(int)); } else { @@ -1007,9 +1016,12 @@ CX_INFO *cxinfo_init(void){ */ int cxinfo_make_insertable(CX_INFO *cxi){ int status=0; + CX_SPECS *tmp; if(cxi->used >= cxi->space){ cxi->space += ALLOCINFO_CHUNK; - if((cxi->cx = (CX_SPECS *) realloc(cxi->cx, cxi->space * sizeof(CX_SPECS) ))){ + tmp = (CX_SPECS *) realloc(cxi->cx, cxi->space * sizeof(CX_SPECS) ); + if(tmp){ + cxi->cx = tmp; memset(&cxi->cx[cxi->used],0,(cxi->space - cxi->used)*sizeof(CX_SPECS)); } else { @@ -1178,9 +1190,12 @@ TP_INFO *tpinfo_init(void){ */ int tpinfo_make_insertable(TP_INFO *tpi){ int status=0; + TCHUNK_SPECS *tmp; if(tpi->used >= tpi->space){ tpi->space += ALLOCINFO_CHUNK; - if((tpi->chunks = (TCHUNK_SPECS *) realloc(tpi->chunks, tpi->space * sizeof(TCHUNK_SPECS) ))){ + tmp = (TCHUNK_SPECS *) realloc(tpi->chunks, tpi->space * sizeof(TCHUNK_SPECS) ); + if(tmp){ + tpi->chunks = tmp; memset(&tpi->chunks[tpi->used],0,(tpi->space - tpi->used)*sizeof(TCHUNK_SPECS)); } else { @@ -1251,10 +1266,13 @@ BR_INFO *brinfo_init(void){ */ int brinfo_make_insertable(BR_INFO *bri){ int status=0; + BRECT_SPECS *tmp; if(!bri)return(2); if(bri->used >= bri->space){ bri->space += ALLOCINFO_CHUNK; - if(!(bri->rects = (BRECT_SPECS *) realloc(bri->rects, bri->space * sizeof(BRECT_SPECS) ))){ status = 1; } + tmp = (BRECT_SPECS *) realloc(bri->rects, bri->space * sizeof(BRECT_SPECS) ); + if(tmp){ bri->rects = tmp; } + else { status = 1;} } return(status); } @@ -1680,11 +1698,14 @@ int trinfo_load_ft_opts(TR_INFO *tri, int use_kern, int load_flags, int kern_mod */ int trinfo_append_out(TR_INFO *tri, const char *src){ size_t slen; + uint8_t *tmp; if(!src)return(-1); slen = strlen(src); if(tri->outused + (int) slen + 1 >= tri->outspace){ tri->outspace += TEREMAX(ALLOCOUT_CHUNK,slen+1); - if(!(tri->out = realloc(tri->out, tri->outspace )))return(-1); + tmp = realloc(tri->out, tri->outspace * sizeof(uint8_t) ); + if(tmp){ tri->out = tmp; } + else { return(-1); } } memcpy(tri->out + tri->outused, src, slen+1); /* copy the terminator */ tri->outused += slen; /* do not count the terminator in the length */ -- cgit v1.2.3 From b77af00c5d29d7a88d976530d3354052344151aa Mon Sep 17 00:00:00 2001 From: Markus Engel Date: Mon, 31 Mar 2014 00:01:25 +0200 Subject: Removed some operator keywords. (bzr r13237) --- src/extension/internal/filter/color.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/extension/internal') diff --git a/src/extension/internal/filter/color.h b/src/extension/internal/filter/color.h index 7059ad29b..19af6e969 100644 --- a/src/extension/internal/filter/color.h +++ b/src/extension/internal/filter/color.h @@ -941,7 +941,7 @@ Invert::get_filter_text (Inkscape::Extension::Extension * ext) std::ostringstream transparency; std::ostringstream hue; - if (ext->get_param_bool("hue") xor ext->get_param_bool("lightness")) { + if (ext->get_param_bool("hue") ^ ext->get_param_bool("lightness")) { hue << "\n"; } else { hue << ""; -- cgit v1.2.3