diff options
Diffstat (limited to 'src/extension/internal/emf-inout.cpp')
| -rw-r--r-- | src/extension/internal/emf-inout.cpp | 716 |
1 files changed, 422 insertions, 294 deletions
diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index 06a64f875..eab47c5c8 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -117,11 +117,10 @@ static pixel_t * 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. */ +/* Write "bitmap" to a PNG file specified by "path"; returns 0 on + success, non-zero on error. */ void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) @@ -323,6 +322,7 @@ Emf::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena bool new_FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); // dashed line bug bool new_FixPPTGrad2Polys = mod->get_param_bool("FixPPTGrad2Polys"); // gradient bug 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 TableGen( //possibly regenerate the unicode-convert tables mod->get_param_bool("TnrToSymbol"), @@ -335,6 +335,7 @@ Emf::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena ext->set_param_bool("FixPPTDashLine",new_FixPPTDashLine); ext->set_param_bool("FixPPTGrad2Polys",new_FixPPTGrad2Polys); ext->set_param_bool("FixPPTPatternAsHatch",new_FixPPTPatternAsHatch); + ext->set_param_bool("FixImageRot",new_FixImageRot); ext->set_param_bool("textToPath", new_val); emf_print_document_to_file(doc, filename); @@ -374,9 +375,7 @@ typedef struct emf_device_context { double ScaleInX, ScaleInY; double ScaleOutX, ScaleOutY; U_COLORREF textColor; - bool textColorSet; U_COLORREF bkColor; - bool bkColorSet; uint32_t textAlign; U_XFORM worldTransform; U_POINTL cur; @@ -423,6 +422,49 @@ typedef struct emf_callback_data { PEMF_OBJECT emf_obj; } EMF_CALLBACK_DATA, *PEMF_CALLBACK_DATA; +/* given the transformation matrix from worldTranform return the scale in the matrix part. Assumes that the + matrix is not used to skew, invert, or make another distorting transformation. */ +double current_scale(PEMF_CALLBACK_DATA d){ + double scale = d->dc[d->level].worldTransform.eM11 * d->dc[d->level].worldTransform.eM22 - + d->dc[d->level].worldTransform.eM12 * d->dc[d->level].worldTransform.eM21; + if(scale <= 0.0)scale=1.0; /* something is dreadfully wrong with the matrix, but do not crash over it */ + scale=sqrt(scale); + return(scale); +} + +/* given the transformation matrix from worldTranform and the current x,y position in inkscape coordinates, + generate an SVG transform that gives the same amount of rotation, no scaling, and maps x,y back onto x,y. This is used for + rotating objects when the location of at least one point in that object is known. Returns: + "matrix(a,b,c,d,e,f)" (WITH the double quotes) +*/ +static std::string current_matrix(PEMF_CALLBACK_DATA d, double x, double y, int useoffset){ + std::stringstream cxform; + double scale = current_scale(d); + cxform << "\"matrix("; + cxform << d->dc[d->level].worldTransform.eM11/scale; cxform << ","; + cxform << d->dc[d->level].worldTransform.eM12/scale; cxform << ","; + cxform << d->dc[d->level].worldTransform.eM21/scale; cxform << ","; + cxform << d->dc[d->level].worldTransform.eM22/scale; cxform << ","; + if(useoffset){ + /* for the "new" coordinates drop the worldtransform translations, not used here */ + double newx = x * d->dc[d->level].worldTransform.eM11/scale + y * d->dc[d->level].worldTransform.eM21/scale; + double newy = x * d->dc[d->level].worldTransform.eM12/scale + y * d->dc[d->level].worldTransform.eM22/scale; + cxform << x - newx; cxform << ","; + cxform << y - newy; + } + else { + cxform << "0,0"; + } + cxform << ")\""; + return(cxform.str()); +} + +/* given the transformation matrix from worldTranform return the rotation angle in radians. + counter clocwise from the x axis. */ +double current_rotation(PEMF_CALLBACK_DATA d){ + return -std::atan2(d->dc[d->level].worldTransform.eM12, d->dc[d->level].worldTransform.eM11); +} + /* Add another 100 blank slots to the hatches array. */ void enlarge_hatches(PEMF_CALLBACK_DATA d){ @@ -445,6 +487,7 @@ int in_hatches(PEMF_CALLBACK_DATA d, char *test){ */ uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchColor){ char hatchname[64]; // big enough + char hrotname[64]; // big enough char tmpcolor[8]; uint32_t idx; @@ -457,15 +500,11 @@ uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchCol switch(hatchType){ case U_HS_SOLIDTEXTCLR: case U_HS_DITHEREDTEXTCLR: - if(d->dc[d->level].textColorSet){ - sprintf(tmpcolor,"%6.6X",sethexcolor(d->dc[d->level].textColor)); - } + sprintf(tmpcolor,"%6.6X",sethexcolor(d->dc[d->level].textColor)); break; case U_HS_SOLIDBKCLR: case U_HS_DITHEREDBKCLR: - if(d->dc[d->level].bkColorSet){ - sprintf(tmpcolor,"%6.6X",sethexcolor(d->dc[d->level].bkColor)); - } + sprintf(tmpcolor,"%6.6X",sethexcolor(d->dc[d->level].bkColor)); break; default: break; @@ -476,7 +515,8 @@ uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchCol // on export the background/text might not match at the time this is written, and the colors will shift. if(hatchType > U_HS_SOLIDCLR)hatchType = U_HS_SOLIDCLR; - sprintf(hatchname,"EMFhatch%d_%s",hatchType,tmpcolor); + // pattern defines hatch when there is no rotation. Load this one first. + sprintf(hatchname,"EMFhatch%d_%s",hatchType,tmpcolor); /* name of pattern BEFORE rotation*/ idx = in_hatches(d,hatchname); if(!idx){ // add it if not already present if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); } @@ -492,14 +532,12 @@ uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchCol *(d->defs) += " <path d=\"M 0 0 6 0\" style=\"fill:none;stroke:#"; *(d->defs) += tmpcolor; *(d->defs) += "\" />\n"; - *(d->defs) += " </pattern>\n"; break; case U_HS_VERTICAL: *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" >\n"; *(d->defs) += " <path d=\"M 0 0 0 6\" style=\"fill:none;stroke:#"; *(d->defs) += tmpcolor; *(d->defs) += "\" />\n"; - *(d->defs) += " </pattern>\n"; break; case U_HS_FDIAGONAL: *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" viewBox=\"0 0 6 6\" preserveAspectRatio=\"none\" >\n"; @@ -514,7 +552,6 @@ uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchCol *(d->defs) += " <use xlink:href=\"#sub"; *(d->defs) += hatchname; *(d->defs) += "\" transform=\"translate(-6,0)\"/>\n"; - *(d->defs) += " </pattern>\n"; break; case U_HS_BDIAGONAL: *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" viewBox=\"0 0 6 6\" preserveAspectRatio=\"none\" >\n"; @@ -529,26 +566,23 @@ uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchCol *(d->defs) += " <use xlink:href=\"#sub"; *(d->defs) += hatchname; *(d->defs) += "\" transform=\"translate(-6,0)\"/>\n"; - *(d->defs) += " </pattern>\n"; break; case U_HS_CROSS: *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" >\n"; *(d->defs) += " <path d=\"M 0 0 6 0 M 0 0 0 6\" style=\"fill:none;stroke:#"; *(d->defs) += tmpcolor; *(d->defs) += "\" />\n"; - *(d->defs) += " </pattern>\n"; break; case U_HS_DIAGCROSS: *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" viewBox=\"0 0 6 6\" preserveAspectRatio=\"none\" >\n"; *(d->defs) += " <use xlink:href=\"#sub"; - sprintf(hatchname,"EMFhatch%d_%6.6X",U_HS_FDIAGONAL,sethexcolor(hatchColor)); - *(d->defs) += hatchname; + sprintf(hrotname,"EMFhatch%d_%6.6X",U_HS_FDIAGONAL,sethexcolor(hatchColor)); // keep hatchname intact for later, hrotname will overwrite this + *(d->defs) += hrotname; *(d->defs) += "\" transform=\"translate(0,0)\"/>\n"; *(d->defs) += " <use xlink:href=\"#sub"; - sprintf(hatchname,"EMFhatch%d_%6.6X",U_HS_BDIAGONAL,sethexcolor(hatchColor)); - *(d->defs) += hatchname; + sprintf(hrotname,"EMFhatch%d_%6.6X",U_HS_BDIAGONAL,sethexcolor(hatchColor)); + *(d->defs) += hrotname; *(d->defs) += "\" transform=\"translate(0,0)\"/>\n"; - *(d->defs) += " </pattern>\n"; break; case U_HS_SOLIDCLR: case U_HS_DITHEREDCLR: @@ -562,11 +596,38 @@ uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchCol *(d->defs) += tmpcolor; *(d->defs) += ";stroke:none"; *(d->defs) += "\" />\n"; - *(d->defs) += " </pattern>\n"; break; } + *(d->defs) += " "; + *(d->defs) += " </pattern>\n"; idx = d->hatches.count; } + + + // pattern allows the inner pattern to be rotated nicely, load this one second only if needed + // hatchname retained from above + sprintf(hrotname,"EMFrothatch%d_%s",hatchType,tmpcolor); /* name of pattern AFTER rotation*/ + if(current_rotation(d) >= 0.00001 || current_rotation(d) <= -0.00001){ /* some rotation, allow a little rounding error around 0 degrees */ + idx = in_hatches(d,hrotname); + if(!idx){ + if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); } + d->hatches.strings[d->hatches.count++]=strdup(hrotname); + + *(d->defs) += "\n"; + *(d->defs) += " <pattern\n"; + *(d->defs) += " id=\""; + *(d->defs) += hrotname; + *(d->defs) += "\"\n"; + *(d->defs) += " xlink:href=\"#"; + *(d->defs) += hatchname; + *(d->defs) += "\"\n"; + *(d->defs) += " patternTransform="; + *(d->defs) += current_matrix(d, 0.0, 0.0, 0); //j use offset 0,0 + *(d->defs) += " />\n"; + idx = d->hatches.count; + } + } + return(idx-1); } @@ -597,7 +658,9 @@ uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t uint32_t idx; char imagename[64]; // big enough + char imrotname[64]; // big enough char xywh[64]; // big enough + int dibparams; MEMPNG mempng; // PNG in memory comes back in this mempng.buffer = NULL; @@ -609,7 +672,7 @@ uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t if(!cbBits || !cbBmi || (iUsage != U_DIB_RGB_COLORS) || - !get_DIB_params( // this returns pointers and values, but allocates no memory + !(dibparams = get_DIB_params( // this returns pointers and values, but allocates no memory pEmr, offBits, offBmi, @@ -620,13 +683,14 @@ uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t &height, &colortype, &invert - )){ + )) + ){ // U_EMRCREATEMONOBRUSH uses text/bk colors instead of what is in the color map. if(((PU_EMR)pEmr)->iType == U_EMR_CREATEMONOBRUSH){ if(numCt==2){ ct[0] = U_RGB2BGR(d->dc[d->level].textColor); - ct[1] = U_RGB2BGR(d->dc[d->level].bkColor); + ct[1] = U_RGB2BGR(d->dc[d->level].bkColor); } else { // createmonobrush renders on other platforms this way return(0xFFFFFFFF); @@ -654,7 +718,11 @@ uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t } } gchar *base64String; - if(mempng.buffer){ + if(dibparams == U_BI_JPEG || dibparams==U_BI_PNG){ + base64String = g_base64_encode((guchar*) px, numCt ); + idx = in_images(d, (char *) base64String); + } + else if(mempng.buffer){ base64String = g_base64_encode((guchar*) mempng.buffer, mempng.size ); free(mempng.buffer); idx = in_images(d, (char *) base64String); @@ -666,7 +734,7 @@ uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t base64String = strdup("iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII="); idx = in_images(d, (char *) base64String); } - if(!idx){ // add it if not already present + 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; d->images.strings[d->images.count++]=strdup(base64String); @@ -680,7 +748,8 @@ uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t *(d->defs) += "\"\n "; *(d->defs) += xywh; *(d->defs) += "\n"; - *(d->defs) += " xlink:href=\"data:image/png;base64,"; + if(dibparams == U_BI_JPEG){ *(d->defs) += " xlink:href=\"data:image/jpeg;base64,"; } + else { *(d->defs) += " xlink:href=\"data:image/png;base64,"; } *(d->defs) += base64String; *(d->defs) += "\"\n"; *(d->defs) += " />\n"; @@ -699,9 +768,46 @@ uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t *(d->defs) += " xlink:href=\"#"; *(d->defs) += imagename; *(d->defs) += "\" />\n"; + *(d->defs) += " "; *(d->defs) += " </pattern>\n"; } g_free(base64String); + + /* image allows the inner image to be rotated nicely, load this one second only if needed + imagename retained from above + Here comes a dreadful hack. How do we determine if this rotation of the base image has already + been loaded? The image names contain no identifying information, they are just numbered sequentially. + So the rotated name is EMFrotimage###_XXXXXX, where ### is the number of the referred to image, and + XXXX is the rotation in radians x 1000000 and truncated. That is then stored in BASE64 as the "image". + The corresponding SVG generated though is not for an image, but a reference to an image. + The name of the pattern MUST stil be EMFimage###_ref or output_style() will not be able to use it. + */ + if(current_rotation(d) >= 0.00001 || current_rotation(d) <= -0.00001){ /* some rotation, allow a little rounding error around 0 degrees */ + int tangle = round(current_rotation(d)*1000000.0); + sprintf(imrotname,"EMFrotimage%d_%d",idx-1,tangle); + base64String = g_base64_encode((guchar*) imrotname, strlen(imrotname) ); + idx = in_images(d, (char *) base64String); // scan for this "image" + if(!idx){ + if(d->images.count == d->images.size){ enlarge_images(d); } + idx = d->images.count; + d->images.strings[d->images.count++]=strdup(base64String); + sprintf(imrotname,"EMFimage%d",idx++); + + *(d->defs) += "\n"; + *(d->defs) += " <pattern\n"; + *(d->defs) += " id=\""; + *(d->defs) += imrotname; + *(d->defs) += "_ref\"\n"; + *(d->defs) += " xlink:href=\"#"; + *(d->defs) += imagename; + *(d->defs) += "_ref\"\n"; + *(d->defs) += " patternTransform="; + *(d->defs) += current_matrix(d, 0.0, 0.0, 0); //j use offset 0,0 + *(d->defs) += " />\n"; + } + g_free(base64String); + } + return(idx-1); } @@ -936,16 +1042,20 @@ pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py) } static double -pix_to_size_point(PEMF_CALLBACK_DATA d, double px) +pix_to_abs_size(PEMF_CALLBACK_DATA d, double px) { - double ppx = px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0) * d->D2PscaleX; - // double ppy = 0; - - double dx = ppx * d->dc[d->level].worldTransform.eM11; // + ppy * d->dc[d->level].worldTransform.eM21 - double dy = ppx * d->dc[d->level].worldTransform.eM12; // + ppy * d->dc[d->level].worldTransform.eM22 + double ppx = fabs(px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0) * d->D2PscaleX * current_scale(d)); + return ppx; +} - double tmp = sqrt(dx * dx + dy * dy); - return tmp; +/* returns "x,y" (without the quotes) in inkscape coordinates for a pair of EMF x,y coordinates +*/ +static std::string pix_to_xy(PEMF_CALLBACK_DATA d, double x, double y){ + std::stringstream cxform; + cxform << pix_to_x_point(d,x,y); + cxform << ","; + cxform << pix_to_y_point(d,x,y); + return(cxform.str()); } @@ -1044,14 +1154,14 @@ select_pen(PEMF_CALLBACK_DATA d, int index) } else if (pEmr->lopn.lopnWidth.x) { int cur_level = d->level; d->level = d->emf_obj[index].level; - double pen_width = pix_to_size_point( d, pEmr->lopn.lopnWidth.x ); + double pen_width = pix_to_abs_size( d, pEmr->lopn.lopnWidth.x ); d->level = cur_level; d->dc[d->level].style.stroke_width.value = pen_width; } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?) //d->dc[d->level].style.stroke_width.value = 1.0; int cur_level = d->level; d->level = d->emf_obj[index].level; - double pen_width = pix_to_size_point( d, 1 ); + double pen_width = pix_to_abs_size( d, 1 ); d->level = cur_level; d->dc[d->level].style.stroke_width.value = pen_width; } @@ -1088,7 +1198,7 @@ select_extpen(PEMF_CALLBACK_DATA d, int index) d->level = d->emf_obj[index].level; // Doing it this way typically results in a pattern that is tiny, better to assume the array // is the same scale as for dot/dash below, that is, no scaling should be applied -// double dash_length = pix_to_size_point( d, pEmr->elp.elpStyleEntry[i] ); +// 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; @@ -1196,14 +1306,14 @@ select_extpen(PEMF_CALLBACK_DATA d, int index) if (pEmr->elp.elpWidth) { int cur_level = d->level; d->level = d->emf_obj[index].level; - double pen_width = pix_to_size_point( d, pEmr->elp.elpWidth ); + double pen_width = pix_to_abs_size( d, pEmr->elp.elpWidth ); d->level = cur_level; d->dc[d->level].style.stroke_width.value = pen_width; } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?) //d->dc[d->level].style.stroke_width.value = 1.0; int cur_level = d->level; d->level = d->emf_obj[index].level; - double pen_width = pix_to_size_point( d, 1 ); + double pen_width = pix_to_abs_size( d, 1 ); d->level = cur_level; d->dc[d->level].style.stroke_width.value = pen_width; } @@ -1303,7 +1413,7 @@ select_font(PEMF_CALLBACK_DATA d, int index) */ int cur_level = d->level; d->level = d->emf_obj[index].level; - double font_size = pix_to_size_point( d, pEmr->elfw.elfLogFont.lfHeight ); + double font_size = pix_to_abs_size( d, pEmr->elfw.elfLogFont.lfHeight ); /* snap the font_size to the nearest 1/32nd of a point. (The size is converted from Pixels to points, snapped, and converted back.) See the notes where d->D2Pscale[XY] are set for the reason why. @@ -1408,12 +1518,12 @@ uint32_t *unknown_chars(size_t count){ \fn store SVG for an image given the pixmap and various coordinate information \param d \param pEmr - \param dl (double) destination left in inkscape pixels - \param dt (double) destination top in inkscape pixels - \param dr (double) destination right in inkscape pixels - \param db (double) destination bottom in inkscape pixels - \param sl (int) source left in pixels in the src image - \param st (int) source top in pixels in the src image + \param dx (double) destination x in inkscape pixels + \param dy (double) destination y in inkscape pixels + \param dw (double) destination width in inkscape pixels + \param dh (double) destination height in inkscape pixels + \param sx (int) source x in src image pixels + \param sy (int) source y in src image pixels \param iUsage \param offBits \param cbBits @@ -1421,89 +1531,109 @@ uint32_t *unknown_chars(size_t count){ \param cbBmi */ void common_image_extraction(PEMF_CALLBACK_DATA d, void *pEmr, - double dl, double dt, double dr, double db, int sl, int st, int sw, int sh, - uint32_t iUsage, uint32_t offBits, uint32_t cbBits, uint32_t offBmi, uint32_t cbBmi){ - SVGOStringStream tmp_image; - tmp_image << " y=\"" << dt << "\"\n x=\"" << dl <<"\"\n "; - - // The image ID is filled in much later when tmp_image is converted - - tmp_image << " xlink:href=\"data:image/png;base64,"; - - MEMPNG mempng; // PNG in memory comes back in this - mempng.buffer = NULL; - - char *rgba_px=NULL; // RGBA pixels - char *sub_px=NULL; // RGBA pixels, subarray - char *px=NULL; // DIB pixels - uint32_t width, height, colortype, numCt, invert; - PU_RGBQUAD ct = NULL; - if(!cbBits || - !cbBmi || - (iUsage != U_DIB_RGB_COLORS) || - !get_DIB_params( // this returns pointers and values, but allocates no memory - pEmr, - offBits, - offBmi, - &px, - &ct, - &numCt, - &width, - &height, - &colortype, - &invert - )){ - if(sw == 0 || sl == 0){ - sw = width; - sh = height; - } + double dx, double dy, double dw, double dh, int sx, int sy, int sw, int sh, + uint32_t iUsage, uint32_t offBits, uint32_t cbBits, uint32_t offBmi, uint32_t cbBmi){ - 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 - height, // Height of pixel array - colortype, // DIB BitCount Enumeration - numCt, // Color table used if not 0 - invert // If DIB rows are in opposite order from RGBA rows - ) && - rgba_px) - { - sub_px = RGBA_to_RGBA( - rgba_px, // full pixel array from DIB - width, // Width of pixel array - height, // Height of pixel array - sl,st, // starting point in pixel array - &sw,&sh // columns/rows to extract from the pixel array (output array size) - ); - - if(!sub_px)sub_px=rgba_px; - toPNG( // Get the image from the RGBA px into mempng - &mempng, - sw, sh, // size of the extracted pixel array - sub_px); - free(sub_px); - } - } - if(mempng.buffer){ - gchar *base64String = g_base64_encode((guchar*) mempng.buffer, mempng.size ); - free(mempng.buffer); - tmp_image << base64String ; - g_free(base64String); - } - else { - // insert a random 3x4 blotch otherwise - tmp_image << "iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII="; - } - - tmp_image << "\"\n height=\"" << db-dt+1 << "\"\n width=\"" << dr-dl+1 << "\"\n"; + SVGOStringStream tmp_image; + int dibparams; - *(d->outsvg) += "\n\t <image\n"; - *(d->outsvg) += tmp_image.str().c_str(); - *(d->outsvg) += "/> \n"; - *(d->path) = ""; + tmp_image << " y=\"" << dy << "\"\n x=\"" << dx <<"\"\n "; + + // The image ID is filled in much later when tmp_image is converted + + + MEMPNG mempng; // PNG in memory comes back in this + mempng.buffer = NULL; + + char *rgba_px=NULL; // RGBA pixels + char *sub_px=NULL; // RGBA pixels, subarray + char *px=NULL; // DIB pixels + uint32_t width, height, colortype, numCt, invert; + PU_RGBQUAD ct = NULL; + 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, + &ct, + &numCt, + &width, + &height, + &colortype, + &invert + )) + ){ + if(sw == 0 || sh == 0){ + sw = width; + sh = height; + } + + 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 + height, // Height of pixel array + colortype, // DIB BitCount Enumeration + numCt, // Color table used if not 0 + invert // If DIB rows are in opposite order from RGBA rows + ) && + rgba_px) + { + sub_px = RGBA_to_RGBA( + rgba_px, // full pixel array from DIB + width, // Width of pixel array + height, // Height of pixel array + sx,sy, // starting point in pixel array + &sw,&sh // columns/rows to extract from the pixel array (output array size) + ); + + if(!sub_px)sub_px=rgba_px; + toPNG( // Get the image from the RGBA px into mempng + &mempng, + sw, sh, // size of the extracted pixel array + sub_px); + free(sub_px); + } + } + gchar *base64String; + if(dibparams == U_BI_JPEG){ + tmp_image << " xlink:href=\"data:image/jpeg;base64,"; + base64String = g_base64_encode((guchar*) px, numCt ); + tmp_image << base64String ; + g_free(base64String); + } + else if(dibparams==U_BI_PNG){ + tmp_image << " xlink:href=\"data:image/png;base64,"; + base64String = g_base64_encode((guchar*) px, numCt ); + tmp_image << base64String ; + g_free(base64String); + } + else if(mempng.buffer){ + tmp_image << " xlink:href=\"data:image/png;base64,"; + gchar *base64String = g_base64_encode((guchar*) mempng.buffer, mempng.size ); + free(mempng.buffer); + tmp_image << base64String ; + g_free(base64String); + } + else { + tmp_image << " xlink:href=\"data:image/png;base64,"; + // insert a random 3x4 blotch otherwise + tmp_image << "iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAA3NCSVQICAjb4U/gAAAALElEQVQImQXBQQ2AMAAAsUJQMSWI2H8qME1yMshojwrvGB8XcHKvR1XtOTc/8HENumHCsOMAAAAASUVORK5CYII="; + } + + tmp_image << "\"\n height=\"" << dh << "\"\n width=\"" << dw << "\"\n"; + + tmp_image << " transform=" << current_matrix(d, dx, dy, 1); // calculate appropriate offset + *(d->outsvg) += "\n\t <image\n"; + *(d->outsvg) += tmp_image.str().c_str(); + + *(d->outsvg) += "/> \n"; + *(d->path) = ""; } /** @@ -1690,7 +1820,7 @@ std::cout << "BEFORE DRAW" // d->defs holds any defines which are read in. - tmp_outsvg << "\n</defs>\n<g>\n"; // start of main body + tmp_outsvg << "\n</defs>\n\n"; // start of main body if (pEmr->nHandles) { d->n_obj = pEmr->nHandles; @@ -1724,15 +1854,13 @@ std::cout << "BEFORE DRAW" tmp_str << "\n\tM " << - pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " << - pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y) << " "; + pix_to_xy( d, pEmr->aptl[0].x, pEmr->aptl[0].y) << " "; for (i=1; i<pEmr->cptl; ) { tmp_str << "\n\tC "; for (j=0; j<3 && i<pEmr->cptl; j++,i++) { tmp_str << - pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " << - pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; + pix_to_xy( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; } } @@ -1754,14 +1882,12 @@ std::cout << "BEFORE DRAW" tmp_str << "\n\tM " << - pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " << - pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " "; + pix_to_xy( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " "; for (i=1; i<pEmr->cptl; i++) { tmp_str << "\n\tL " << - pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " << - pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; + pix_to_xy( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; } tmp_path << tmp_str.str().c_str(); @@ -1783,14 +1909,12 @@ std::cout << "BEFORE DRAW" tmp_str << "\n\tM " << - pix_to_x_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " " << - pix_to_y_point( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " "; + pix_to_xy( d, pEmr->aptl[0].x, pEmr->aptl[0].y ) << " "; for (i=1; i<pEmr->cptl; i++) { tmp_str << "\n\tL " << - pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " << - pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; + pix_to_xy( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; } tmp_path << tmp_str.str().c_str(); @@ -1810,8 +1934,7 @@ std::cout << "BEFORE DRAW" tmp_path << "\n\tC "; for (j=0; j<3 && i<pEmr->cptl; j++,i++) { tmp_path << - pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " << - pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; + pix_to_xy( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; } } @@ -1829,8 +1952,7 @@ std::cout << "BEFORE DRAW" for (i=0; i<pEmr->cptl;i++) { tmp_path << "\n\tL " << - pix_to_x_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " " << - pix_to_y_point( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; + pix_to_xy( d, pEmr->aptl[i].x, pEmr->aptl[i].y ) << " "; } break; @@ -1855,14 +1977,12 @@ std::cout << "BEFORE DRAW" SVGOStringStream poly_path; poly_path << "\n\tM " << - pix_to_x_point( d, aptl[i].x, aptl[i].y ) << " " << - pix_to_y_point( d, aptl[i].x, aptl[i].y ) << " "; + pix_to_xy( d, aptl[i].x, aptl[i].y ) << " "; i++; for (j=1; j<pEmr->aPolyCounts[n] && i<pEmr->cptl; j++) { poly_path << "\n\tL " << - pix_to_x_point( d, aptl[i].x, aptl[i].y ) << " " << - pix_to_y_point( d, aptl[i].x, aptl[i].y ) << " "; + pix_to_xy( d, aptl[i].x, aptl[i].y ) << " "; i++; } @@ -1967,7 +2087,6 @@ std::cout << "BEFORE DRAW" { dbg_str << "<!-- U_EMR_EOF -->\n"; - tmp_outsvg << "</g>\n"; tmp_outsvg << "</svg>\n"; *(d->outsvg) = *(d->outdef) + *(d->defs) + *(d->outsvg); OK=0; @@ -2043,7 +2162,6 @@ std::cout << "BEFORE DRAW" PU_EMRSETTEXTCOLOR pEmr = (PU_EMRSETTEXTCOLOR) lpEMFR; d->dc[d->level].textColor = pEmr->crColor; - d->dc[d->level].textColorSet = true; break; } case U_EMR_SETBKCOLOR: @@ -2052,7 +2170,6 @@ std::cout << "BEFORE DRAW" PU_EMRSETBKCOLOR pEmr = (PU_EMRSETBKCOLOR) lpEMFR; d->dc[d->level].bkColor = pEmr->crColor; - d->dc[d->level].bkColorSet = true; break; } case U_EMR_OFFSETCLIPRGN: dbg_str << "<!-- U_EMR_OFFSETCLIPRGN -->\n"; break; @@ -2068,8 +2185,7 @@ std::cout << "BEFORE DRAW" tmp_path << "\n\tM " << - pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " << - pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " "; + pix_to_xy( d, pEmr->ptl.x, pEmr->ptl.y ) << " "; break; } case U_EMR_SETMETARGN: dbg_str << "<!-- U_EMR_SETMETARGN -->\n"; break; @@ -2085,19 +2201,20 @@ std::cout << "BEFORE DRAW" break; rc_old = rc; - double l = pix_to_x_point( d, rc.left, rc.top ); - double t = pix_to_y_point( d, rc.left, rc.top ); - double r = pix_to_x_point( d, rc.right, rc.bottom ); - double b = pix_to_y_point( d, rc.right, rc.bottom ); + double dx = pix_to_x_point( d, rc.left, rc.top ); + double dy = pix_to_y_point( d, rc.left, rc.top ); + double dw = pix_to_abs_size( d, rc.right - rc.left + 1); + double dh = pix_to_abs_size( d, rc.bottom - rc.top + 1); SVGOStringStream tmp_rectangle; tmp_rectangle << "\n<clipPath\n\tclipPathUnits=\"userSpaceOnUse\" "; - tmp_rectangle << "\n\tid=\"clipEmfPath" << ++(d->id) << "\" >"; + tmp_rectangle << "\nid=\"clipEmfPath" << ++(d->id) << "\" >"; tmp_rectangle << "\n<rect "; - tmp_rectangle << "\n\tx=\"" << l << "\" "; - tmp_rectangle << "\n\ty=\"" << t << "\" "; - tmp_rectangle << "\n\twidth=\"" << r-l << "\" "; - tmp_rectangle << "\n\theight=\"" << b-t << "\" />"; + tmp_rectangle << "\n x=\"" << dx << "\" "; + tmp_rectangle << "\n y=\"" << dy << "\" "; + tmp_rectangle << "\n width=\"" << dw << "\" "; + tmp_rectangle << "\n height=\"" << dh << "\" />"; + tmp_rectangle << "\n transform=" << current_matrix(d, dx, dy, 1); // calculate appropriate offset tmp_rectangle << "\n</clipPath>"; *(d->outdef) += tmp_rectangle.str().c_str(); @@ -2372,15 +2489,10 @@ std::cout << "BEFORE DRAW" PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE) lpEMFR; U_RECTL rclBox = pEmr->rclBox; - double l = pix_to_x_point( d, rclBox.left, rclBox.top ); - double t = pix_to_y_point( d, rclBox.left, rclBox.top ); - double r = pix_to_x_point( d, rclBox.right, rclBox.bottom ); - double b = pix_to_y_point( d, rclBox.right, rclBox.bottom ); - - double cx = (l + r) / 2.0; - double cy = (t + b) / 2.0; - double rx = fabs(l - r) / 2.0; - double ry = fabs(t - b) / 2.0; + double cx = pix_to_x_point( d, (rclBox.left + rclBox.right)/2.0, (rclBox.bottom + rclBox.top)/2.0 ); + double cy = pix_to_y_point( d, (rclBox.left + rclBox.right)/2.0, (rclBox.bottom + rclBox.top)/2.0 ); + double rx = pix_to_abs_size( d, fabs(rclBox.right - rclBox.left )/2.0 ); + double ry = pix_to_abs_size( d, fabs(rclBox.top - rclBox.bottom)/2.0 ); SVGOStringStream tmp_ellipse; tmp_ellipse << "cx=\"" << cx << "\" "; @@ -2405,16 +2517,11 @@ std::cout << "BEFORE DRAW" PU_EMRRECTANGLE pEmr = (PU_EMRRECTANGLE) lpEMFR; U_RECTL rc = pEmr->rclBox; - double l = pix_to_x_point( d, rc.left, rc.top ); - double t = pix_to_y_point( d, rc.left, rc.top ); - double r = pix_to_x_point( d, rc.right, rc.bottom ); - double b = pix_to_y_point( d, rc.right, rc.bottom ); - SVGOStringStream tmp_rectangle; - tmp_rectangle << "\n\tM " << l << " " << t << " "; - tmp_rectangle << "\n\tL " << r << " " << t << " "; - tmp_rectangle << "\n\tL " << r << " " << b << " "; - tmp_rectangle << "\n\tL " << l << " " << b << " "; + tmp_rectangle << "\n\tM " << pix_to_xy( d, rc.left , rc.top ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, rc.right, rc.top ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, rc.right, rc.bottom ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, rc.left, rc.bottom ) << " "; tmp_rectangle << "\n\tz"; d->mask |= emr_mask; @@ -2430,24 +2537,54 @@ std::cout << "BEFORE DRAW" U_RECTL rc = pEmr->rclBox; U_SIZEL corner = pEmr->szlCorner; double f = 4.*(sqrt(2) - 1)/3; - - double l = pix_to_x_point(d, rc.left, rc.top); - double t = pix_to_y_point(d, rc.left, rc.top); - double r = pix_to_x_point(d, rc.right, rc.bottom); - double b = pix_to_y_point(d, rc.right, rc.bottom); - double cnx = pix_to_size_point(d, corner.cx/2); - double cny = pix_to_size_point(d, corner.cy/2); - + double f1 = 1.0 - f; + double cnx = corner.cx/2; + double cny = corner.cy/2; + SVGOStringStream tmp_rectangle; - tmp_rectangle << "\n\tM " << l << ", " << t + cny << " "; - tmp_rectangle << "\n\tC " << l << ", " << t + (1-f)*cny << " " << l + (1-f)*cnx << ", " << t << " " << l + cnx << ", " << t << " "; - tmp_rectangle << "\n\tL " << r - cnx << ", " << t << " "; - tmp_rectangle << "\n\tC " << r - (1-f)*cnx << ", " << t << " " << r << ", " << t + (1-f)*cny << " " << r << ", " << t + cny << " "; - tmp_rectangle << "\n\tL " << r << ", " << b - cny << " "; - tmp_rectangle << "\n\tC " << r << ", " << b - (1-f)*cny << " " << r - (1-f)*cnx << ", " << b << " " << r - cnx << ", " << b << " "; - tmp_rectangle << "\n\tL " << l + cnx << ", " << b << " "; - tmp_rectangle << "\n\tC " << l + (1-f)*cnx << ", " << b << " " << l << ", " << b - (1-f)*cny << " " << l << ", " << b - cny << " "; - tmp_rectangle << "\n\tz"; + tmp_rectangle << "\n" + << " M " + << pix_to_xy(d, rc.left , rc.top + cny ) + << "\n"; + tmp_rectangle << " C " + << pix_to_xy(d, rc.left , rc.top + cny*f1 ) + << " " + << pix_to_xy(d, rc.left + cnx*f1 , rc.top ) + << " " + << pix_to_xy(d, rc.left + cnx , rc.top ) + << "\n"; + tmp_rectangle << " L " + << pix_to_xy(d, rc.right - cnx , rc.top ) + << "\n"; + tmp_rectangle << " C " + << pix_to_xy(d, rc.right - cnx*f1 , rc.top ) + << " " + << pix_to_xy(d, rc.right , rc.top + cny*f1 ) + << " " + << pix_to_xy(d, rc.right , rc.top + cny ) + << "\n"; + tmp_rectangle << " L " + << pix_to_xy(d, rc.right , rc.bottom - cny ) + << "\n"; + tmp_rectangle << " C " + << pix_to_xy(d, rc.right , rc.bottom - cny*f1 ) + << " " + << pix_to_xy(d, rc.right - cnx*f1 , rc.bottom ) + << " " + << pix_to_xy(d, rc.right - cnx , rc.bottom ) + << "\n"; + tmp_rectangle << " L " + << pix_to_xy(d, rc.left + cnx , rc.bottom ) + << "\n"; + tmp_rectangle << " C " + << pix_to_xy(d, rc.left + cnx*f1 , rc.bottom ) + << " " + << pix_to_xy(d, rc.left , rc.bottom - cny*f1 ) + << " " + << pix_to_xy(d, rc.left , rc.bottom - cny ) + << "\n"; + tmp_rectangle << " z\n"; + d->mask |= emr_mask; @@ -2460,13 +2597,15 @@ std::cout << "BEFORE DRAW" U_PAIRF center,start,end,size; int f1; 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_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y); - tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0 ; - tmp_path << " 0 "; + 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 << " "; + tmp_path << 180.0 * current_rotation(d)/M_PI; + tmp_path << " "; tmp_path << " " << f1 << "," << f2 << " "; - tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y)<< " "; - + tmp_path << pix_to_xy(d, end.x, end.y) << " \n"; d->mask |= emr_mask; } else { @@ -2481,11 +2620,13 @@ std::cout << "BEFORE DRAW" int f1; 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_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y); - tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0 ; - tmp_path << " 0 "; + 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 << " "; + tmp_path << 180.0 * current_rotation(d)/M_PI; + tmp_path << " "; tmp_path << " " << f1 << "," << f2 << " "; - tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y); + tmp_path << pix_to_xy(d, end.x, end.y) << " \n"; tmp_path << " z "; d->mask |= emr_mask; } @@ -2501,12 +2642,14 @@ std::cout << "BEFORE DRAW" int f1; 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_x_point(d, center.x, center.y) << "," << pix_to_y_point(d, center.x, center.y); - tmp_path << "\n\tL " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y); - tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0; - tmp_path << " 0 "; + 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 << " "; + tmp_path << 180.0 * current_rotation(d)/M_PI; + tmp_path << " "; tmp_path << " " << f1 << "," << f2 << " "; - tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y); + tmp_path << pix_to_xy(d, end.x, end.y) << " \n"; tmp_path << " z "; d->mask |= emr_mask; } @@ -2531,8 +2674,7 @@ std::cout << "BEFORE DRAW" tmp_path << "\n\tL " << - pix_to_x_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " " << - pix_to_y_point( d, pEmr->ptl.x, pEmr->ptl.y ) << " "; + pix_to_xy( d, pEmr->ptl.x, pEmr->ptl.y ) << " "; break; } case U_EMR_ARCTO: @@ -2543,12 +2685,14 @@ std::cout << "BEFORE DRAW" int f2 = (d->arcdir == U_AD_COUNTERCLOCKWISE ? 0 : 1); if(!emr_arc_points( lpEMFR, &f1, f2, ¢er, &start, &end, &size)){ // draw a line from current position to start - tmp_path << "\n\tL " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y); - tmp_path << "\n\tM " << pix_to_x_point(d, start.x, start.y) << "," << pix_to_y_point(d, start.x, start.y); - tmp_path << " A " << pix_to_x_point(d, size.x, size.y)/2.0 << "," << pix_to_y_point(d, size.x, size.y)/2.0 ; - tmp_path << " 0 "; + tmp_path << "\n\tL " << pix_to_xy(d, start.x, start.y); + 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 << " "; + tmp_path << 180.0 * current_rotation(d)/M_PI; + tmp_path << " "; tmp_path << " " << f1 << "," << f2 << " "; - tmp_path << pix_to_x_point(d, end.x, end.y) << "," << pix_to_y_point(d, end.x, end.y)<< " "; + tmp_path << pix_to_xy(d, end.x, end.y)<< " "; d->mask |= emr_mask; } @@ -2691,27 +2835,20 @@ std::cout << "BEFORE DRAW" dbg_str << "<!-- U_EMR_BITBLT -->\n"; PU_EMRBITBLT pEmr = (PU_EMRBITBLT) lpEMFR; - double dl = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y); - double dt = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y); - double dr = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y); - double db = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y); - //source position within the bitmap, in pixels - int sl = pEmr->Src.x + pEmr->xformSrc.eDx; - int st = pEmr->Src.y + pEmr->xformSrc.eDy; - int sw = 0; // extract all of the image - int sh = 0; - if(sl<0)sl=0; - if(st<0)st=0; - // Treat all nonImage bitblts as a rectangular write. Definitely not correct, but at + // Treat all nonImage bitblts as a rectangular write. Definitely not correct, but at // least it leaves objects where the operations should have been. if (!pEmr->cbBmiSrc) { // should be an application of a DIBPATTERNBRUSHPT, use a solid color instead + int32_t dx = pEmr->Dest.x; + int32_t dy = pEmr->Dest.y; + int32_t dw = pEmr->cDest.x; + int32_t dh = pEmr->cDest.y; SVGOStringStream tmp_rectangle; - tmp_rectangle << "\n\tM " << dl << " " << dt << " "; - tmp_rectangle << "\n\tL " << dr << " " << dt << " "; - tmp_rectangle << "\n\tL " << dr << " " << db << " "; - tmp_rectangle << "\n\tL " << dl << " " << db << " "; + tmp_rectangle << "\n\tM " << pix_to_xy( d, dx, dy ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, dx + dw, dy ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, dx + dw, dy + dh ) << " "; + tmp_rectangle << "\n\tL " << pix_to_xy( d, dx, dy + dh ) << " "; tmp_rectangle << "\n\tz"; d->mask |= emr_mask; @@ -2721,7 +2858,18 @@ std::cout << "BEFORE DRAW" tmp_path << tmp_rectangle.str().c_str(); } else { - common_image_extraction(d,pEmr,dl,dt,dr,db,sl,st,sw,sh, + double dx = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y); + double dy = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y); + double dw = pix_to_abs_size( d, pEmr->cDest.x); + double dh = pix_to_abs_size( d, pEmr->cDest.y); + //source position within the bitmap, in pixels + int sx = pEmr->Src.x + pEmr->xformSrc.eDx; + int sy = pEmr->Src.y + pEmr->xformSrc.eDy; + int sw = 0; // extract all of the image + int sh = 0; + if(sx<0)sx=0; + if(sy<0)sy=0; + common_image_extraction(d,pEmr,dx,dy,dw,dh,sx,sy,sw,sh, pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc); } break; @@ -2732,16 +2880,16 @@ std::cout << "BEFORE DRAW" PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) lpEMFR; // Always grab image, ignore modes. if (pEmr->cbBmiSrc) { - double dl = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y); - double dt = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y); - double dr = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y); - double db = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y); + double dx = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y); + double dy = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y); + double dw = pix_to_abs_size( d, pEmr->cDest.x); + double dh = pix_to_abs_size( d, pEmr->cDest.y); //source position within the bitmap, in pixels - int sl = pEmr->Src.x + pEmr->xformSrc.eDx; - int st = pEmr->Src.y + pEmr->xformSrc.eDy; + int sx = pEmr->Src.x + pEmr->xformSrc.eDx; + int sy = pEmr->Src.y + pEmr->xformSrc.eDy; int sw = pEmr->cSrc.x; // extract the specified amount of the image int sh = pEmr->cSrc.y; - common_image_extraction(d,pEmr,dl,dt,dr,db,sl,st,sw,sh, + common_image_extraction(d,pEmr,dx,dy,dw,dh,sx,sy,sw,sh, pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc); } break; @@ -2752,15 +2900,15 @@ std::cout << "BEFORE DRAW" PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) lpEMFR; // Always grab image, ignore masks and modes. if (pEmr->cbBmiSrc) { - double dl = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y); - double dt = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y); - double dr = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y); - double db = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y); - int sl = pEmr->Src.x + pEmr->xformSrc.eDx; //source position within the bitmap, in pixels - int st = pEmr->Src.y + pEmr->xformSrc.eDy; + double dx = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y); + double dy = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y); + double dw = pix_to_abs_size( d, pEmr->cDest.x); + double dh = pix_to_abs_size( d, pEmr->cDest.y); + int sx = pEmr->Src.x + pEmr->xformSrc.eDx; //source position within the bitmap, in pixels + int sy = pEmr->Src.y + pEmr->xformSrc.eDy; int sw = 0; // extract all of the image int sh = 0; - common_image_extraction(d,pEmr,dl,dt,dr,db,sl,st,sw,sh, + common_image_extraction(d,pEmr,dx,dy,dw,dh,sx,sy,sw,sh, pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc); } break; @@ -2776,15 +2924,15 @@ std::cout << "BEFORE DRAW" // user can sort out transparency later using Gimp, if need be. PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) lpEMFR; - double dl = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y ); - double dt = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y ); - double dr = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y ); - double db = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y ); - int sl = pEmr->Src.x; //source position within the bitmap, in pixels - int st = pEmr->Src.y; + double dx = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y ); + double dy = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y ); + double dw = pix_to_abs_size( d, pEmr->cDest.x); + double dh = pix_to_abs_size( d, pEmr->cDest.y); + int sx = pEmr->Src.x; //source position within the bitmap, in pixels + int sy = pEmr->Src.y; int sw = pEmr->cSrc.x; // extract the specified amount of the image int sh = pEmr->cSrc.y; - common_image_extraction(d,pEmr,dl,dt,dr,db,sl,st,sw,sh, + common_image_extraction(d,pEmr,dx,dy,dw,dh,sx,sy,sw,sh, pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc); dbg_str << "<!-- U_EMR_STRETCHDIBITS -->\n"; @@ -2919,6 +3067,7 @@ std::cout << "BEFORE DRAW" tsp.ldir = (d->dc[d->level].textAlign & U_TA_RTLREADING ? LDIR_RL : LDIR_LR); // language direction tsp.condensed = FC_WIDTH_NORMAL; // Not implemented well in libTERE (yet) tsp.ori = d->dc[d->level].style.baseline_shift.value; // For now orientation is always the same as escapement + tsp.ori += 180.0 * current_rotation(d)/ M_PI; // radians to degrees tsp.string = (uint8_t *) U_strdup(escaped_text); // this will be free'd much later at a trinfo_clear(). tsp.fs = d->dc[d->level].style.font_size.computed * 0.8; // Font size in points (void) trinfo_load_fontname(d->tri, (uint8_t *)d->dc[d->level].font_name, &tsp); @@ -2956,17 +3105,12 @@ std::cout << "BEFORE DRAW" d->mask |= emr_mask; - tmp_str << - "\n\tM " << - pix_to_x_point( d, apts[0].x, apts[0].y ) << " " << - pix_to_y_point( d, apts[0].x, apts[0].y ) << " "; + tmp_str << "\n\tM " << pix_to_xy( d, apts[0].x, apts[0].y ) << " "; for (i=1; i<pEmr->cpts; ) { tmp_str << "\n\tC "; for (j=0; j<3 && i<pEmr->cpts; j++,i++) { - tmp_str << - pix_to_x_point( d, apts[i].x, apts[i].y ) << " " << - pix_to_y_point( d, apts[i].x, apts[i].y ) << " "; + tmp_str << pix_to_xy( d, apts[i].x, apts[i].y ) << " "; } } @@ -2987,14 +3131,10 @@ std::cout << "BEFORE DRAW" d->mask |= emr_mask; // skip the first point? - tmp_poly << "\n\tM " << - pix_to_x_point( d, apts[first].x, apts[first].y ) << " " << - pix_to_y_point( d, apts[first].x, apts[first].y ) << " "; + tmp_poly << "\n\tM " << pix_to_xy( d, apts[first].x, apts[first].y ) << " "; for (i=first+1; i<pEmr->cpts; i++) { - tmp_poly << "\n\tL " << - pix_to_x_point( d, apts[i].x, apts[i].y ) << " " << - pix_to_y_point( d, apts[i].x, apts[i].y ) << " "; + tmp_poly << "\n\tL " << pix_to_xy( d, apts[i].x, apts[i].y ) << " "; } tmp_path << tmp_poly.str().c_str(); @@ -3016,16 +3156,10 @@ std::cout << "BEFORE DRAW" d->mask |= emr_mask; - tmp_str << - "\n\tM " << - pix_to_x_point( d, apts[0].x, apts[0].y ) << " " << - pix_to_y_point( d, apts[0].x, apts[0].y ) << " "; + tmp_str << "\n\tM " << pix_to_xy( d, apts[0].x, apts[0].y ) << " "; for (i=1; i<pEmr->cpts; i++) { - tmp_str << - "\n\tL " << - pix_to_x_point( d, apts[i].x, apts[i].y ) << " " << - pix_to_y_point( d, apts[i].x, apts[i].y ) << " "; + tmp_str << "\n\tL " << pix_to_xy( d, apts[i].x, apts[i].y ) << " "; } tmp_path << tmp_str.str().c_str(); @@ -3045,9 +3179,7 @@ std::cout << "BEFORE DRAW" for (i=0; i<pEmr->cpts;) { tmp_path << "\n\tC "; for (j=0; j<3 && i<pEmr->cpts; j++,i++) { - tmp_path << - pix_to_x_point( d, apts[i].x, apts[i].y ) << " " << - pix_to_y_point( d, apts[i].x, apts[i].y ) << " "; + tmp_path << pix_to_xy( d, apts[i].x, apts[i].y ) << " "; } } @@ -3064,10 +3196,7 @@ std::cout << "BEFORE DRAW" d->mask |= emr_mask; for (i=0; i<pEmr->cpts;i++) { - tmp_path << - "\n\tL " << - pix_to_x_point( d, apts[i].x, apts[i].y ) << " " << - pix_to_y_point( d, apts[i].x, apts[i].y ) << " "; + tmp_path << "\n\tL " << pix_to_xy( d, apts[i].x, apts[i].y ) << " "; } break; @@ -3091,15 +3220,11 @@ std::cout << "BEFORE DRAW" for (n=0; n<pEmr->nPolys && i<pEmr->cpts; n++) { SVGOStringStream poly_path; - poly_path << "\n\tM " << - pix_to_x_point( d, apts[i].x, apts[i].y ) << " " << - pix_to_y_point( d, apts[i].x, apts[i].y ) << " "; + poly_path << "\n\tM " << pix_to_xy( d, apts[i].x, apts[i].y ) << " "; i++; for (j=1; j<pEmr->aPolyCounts[n] && i<pEmr->cpts; j++) { - poly_path << "\n\tL " << - pix_to_x_point( d, apts[i].x, apts[i].y ) << " " << - pix_to_y_point( d, apts[i].x, apts[i].y ) << " "; + poly_path << "\n\tL " << pix_to_xy( d, apts[i].x, apts[i].y ) << " "; i++; } @@ -3244,6 +3369,8 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) d.dc[0].worldTransform.eDx = 0.0; d.dc[0].worldTransform.eDy = 0.0; d.dc[0].font_name = strdup("Arial"); // Default font, EMF spec says device can pick whatever it wants + d.dc[0].textColor = U_RGB(0, 0, 0); // default foreground color (black) + d.dc[0].bkColor = U_RGB(255, 255, 255); // default background color (white) if (uri == NULL) { return NULL; @@ -3349,6 +3476,7 @@ Emf::init (void) "<param name=\"FixPPTDashLine\" gui-text=\"" N_("Convert dashed/dotted lines to single lines") "\" type=\"boolean\">false</param>\n" "<param name=\"FixPPTGrad2Polys\" gui-text=\"" N_("Convert gradients to colored polygon series") "\" type=\"boolean\">false</param>\n" "<param name=\"FixPPTPatternAsHatch\" gui-text=\"" N_("Map all fill patterns to standard EMF hatches") "\" type=\"boolean\">false</param>\n" + "<param name=\"FixImageRot\" gui-text=\"" N_("Ignore image rotations") "\" type=\"boolean\">false</param>\n" "<output>\n" "<extension>.emf</extension>\n" "<mimetype>image/x-emf</mimetype>\n" |
