=== modified file 'src/extension/internal/emf-inout.cpp' --- src/extension/internal/emf-inout.cpp 2012-12-13 04:10:54 +0000 +++ src/extension/internal/emf-inout.cpp 2013-01-31 22:22:14 +0000 @@ -117,12 +117,11 @@ { 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 my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { @@ -323,6 +322,7 @@ 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 @@ 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); @@ -423,6 +424,49 @@ 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 +489,7 @@ */ 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; @@ -476,7 +521,8 @@ // 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 +538,12 @@ *(d->defs) += " defs) += tmpcolor; *(d->defs) += "\" />\n"; - *(d->defs) += " \n"; break; case U_HS_VERTICAL: *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" >\n"; *(d->defs) += " defs) += tmpcolor; *(d->defs) += "\" />\n"; - *(d->defs) += " \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 +558,6 @@ *(d->defs) += " defs) += hatchname; *(d->defs) += "\" transform=\"translate(-6,0)\"/>\n"; - *(d->defs) += " \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 +572,23 @@ *(d->defs) += " defs) += hatchname; *(d->defs) += "\" transform=\"translate(-6,0)\"/>\n"; - *(d->defs) += " \n"; break; case U_HS_CROSS: *(d->defs) += " patternUnits=\"userSpaceOnUse\" width=\"6\" height=\"6\" x=\"0\" y=\"0\" >\n"; *(d->defs) += " defs) += tmpcolor; *(d->defs) += "\" />\n"; - *(d->defs) += " \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) += " 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) += " 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) += " \n"; break; case U_HS_SOLIDCLR: case U_HS_DITHEREDCLR: @@ -562,11 +602,38 @@ *(d->defs) += tmpcolor; *(d->defs) += ";stroke:none"; *(d->defs) += "\" />\n"; - *(d->defs) += " \n"; break; } + *(d->defs) += " "; + *(d->defs) += " \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) += " 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 +664,9 @@ 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 +678,7 @@ 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,7 +689,8 @@ &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){ @@ -654,7 +724,11 @@ } } 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 +740,7 @@ 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 +754,8 @@ *(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 +774,46 @@ *(d->defs) += " xlink:href=\"#"; *(d->defs) += imagename; *(d->defs) += "\" />\n"; + *(d->defs) += " "; *(d->defs) += " \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) += " 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 +1048,20 @@ } 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 tmp = sqrt(dx * dx + dy * dy); - return tmp; + double ppx = fabs(px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0) * d->D2PscaleX * current_scale(d)); + return ppx; +} + +/* 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 +1160,14 @@ } 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 +1204,7 @@ 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 +1312,14 @@ 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 +1419,7 @@ */ 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 +1524,12 @@ \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 +1537,109 @@ \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; - } - - 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"; - - *(d->outsvg) += "\n\t outsvg) += tmp_image.str().c_str(); - *(d->outsvg) += "/> \n"; - *(d->path) = ""; + 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){ + + SVGOStringStream tmp_image; + int dibparams; + + 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 outsvg) += tmp_image.str().c_str(); + + *(d->outsvg) += "/> \n"; + *(d->path) = ""; } /** @@ -1690,7 +1826,7 @@ // d->defs holds any defines which are read in. - tmp_outsvg << "\n\n\n"; // start of main body + tmp_outsvg << "\n\n\n"; // start of main body if (pEmr->nHandles) { d->n_obj = pEmr->nHandles; @@ -1724,15 +1860,13 @@ 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; icptl; ) { tmp_str << "\n\tC "; for (j=0; j<3 && icptl; 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 +1888,12 @@ 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; icptl; 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 +1915,12 @@ 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; icptl; 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 +1940,7 @@ tmp_path << "\n\tC "; for (j=0; j<3 && icptl; 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 +1958,7 @@ for (i=0; icptl;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 +1983,12 @@ 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; jaPolyCounts[n] && icptl; 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 +2093,6 @@ { dbg_str << "\n"; - tmp_outsvg << "\n"; tmp_outsvg << "\n"; *(d->outsvg) = *(d->outdef) + *(d->defs) + *(d->outsvg); OK=0; @@ -2068,8 +2193,7 @@ 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 << "\n"; break; @@ -2085,19 +2209,20 @@ 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 << "\nid) << "\" >"; + tmp_rectangle << "\nid=\"clipEmfPath" << ++(d->id) << "\" >"; tmp_rectangle << "\n"; + 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"; *(d->outdef) += tmp_rectangle.str().c_str(); @@ -2372,15 +2497,10 @@ 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 +2525,11 @@ 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 +2545,54 @@ 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 +2605,15 @@ 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 +2628,13 @@ 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 +2650,14 @@ 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 +2682,7 @@ 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 +2693,14 @@ 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 +2843,20 @@ dbg_str << "\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 +2866,18 @@ 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 +2888,16 @@ 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 +2908,15 @@ 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 +2932,15 @@ // 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 << "\n"; @@ -2919,6 +3075,7 @@ 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 +3113,12 @@ 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; icpts; ) { tmp_str << "\n\tC "; for (j=0; j<3 && icpts; 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 +3139,10 @@ 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; icpts; 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 +3164,10 @@ 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; icpts; 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 +3187,7 @@ for (i=0; icpts;) { tmp_path << "\n\tC "; for (j=0; j<3 && icpts; 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 +3204,7 @@ d->mask |= emr_mask; for (i=0; icpts;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 +3228,11 @@ for (n=0; nnPolys && icpts; 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; jaPolyCounts[n] && icpts; 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++; } @@ -3349,6 +3482,7 @@ "false\n" "false\n" "false\n" + "false\n" "\n" ".emf\n" "image/x-emf\n" === modified file 'src/extension/internal/emf-print.cpp' --- src/extension/internal/emf-print.cpp 2012-10-25 08:08:38 +0000 +++ src/extension/internal/emf-print.cpp 2013-01-31 20:53:37 +0000 @@ -100,7 +100,7 @@ /* globals */ static double PX2WORLD = 20.0f; static U_XFORM worldTransform; -static bool FixPPTCharPos, FixPPTDashLine, FixPPTGrad2Polys, FixPPTPatternAsHatch; +static bool FixPPTCharPos, FixPPTDashLine, FixPPTGrad2Polys, FixPPTPatternAsHatch, FixImageRot; static FFNEXUS *short_fflist = NULL; //only those fonts so far encountered static FFNEXUS *long_fflist = NULL; //all the fonts described in ...\share\extensions\fontfix.conf static EMFTRACK *et = NULL; @@ -302,6 +302,7 @@ FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); FixPPTGrad2Polys = mod->get_param_bool("FixPPTGrad2Polys"); FixPPTPatternAsHatch = mod->get_param_bool("FixPPTPatternAsHatch"); + FixImageRot = mod->get_param_bool("FixImageRot"); (void) emf_start(utf8_fn, 1000000, 250000, &et); // Initialize the et structure (void) htable_create(128, 128, &eht); // Initialize the eht structure @@ -627,7 +628,7 @@ if(style->fill.isColor()){ fill_mode = DRAW_PAINT; float opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value); - if (opacity <= 0.0) return 1; // opacity isn't used here beyond this + if (opacity <= 0.0)opacity = 0.0; // basically the same as no fill sp_color_get_rgb_floatv( &style->fill.value.color, rgb ); hatchColor = U_RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]); @@ -1215,11 +1216,9 @@ use_fill = true; use_stroke = false; - // earlier versions had flush of fill here, but it never executed and was removed - fill_transform = tf; - if (create_brush(style, NULL)){ + if (create_brush(style, NULL)){ // 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. @@ -1389,8 +1388,6 @@ } } - - // std::cout << "end fill" << std::endl; return 0; } @@ -1663,11 +1660,9 @@ in the past (or will be in the future?) Not in current trunk. (4/19/2012) Limitations of this code: - 1. rotated images are mangled. They stay in their original orientation and are stretched - along X or Y. - 2. Transparency is lost on export. (Apparently a limitation of the EMF format.) - 3. Probably messes up if row stride != w*4 - 4. There is still a small memory leak somewhere, possibly in a pixbuf created in a routine + 1. Transparency is lost on export. (Apparently a limitation of the EMF format.) + 2. Probably messes up if row stride != w*4 + 3. There is still a small memory leak somewhere, possibly in a pixbuf created in a routine that calls this one and passes px, but never removes the rest of the pixbuf. The first time this is called it leaked 5M (in one test) and each subsequent call leaked around 200K more. If this routine is reduced to @@ -1685,7 +1680,7 @@ SPStyle const *style) /** provides indirect link to image object */ { // std::cout << "image " << std::endl; - double x1,x2,y1,y2; + double x1,y1,dw,dh; char *rec = NULL; Geom::Affine tf = m_tr_stack.top(); @@ -1694,14 +1689,12 @@ throw "Fatal programming error in PrintEmf::image at EMRHEADER"; } - x1= atof(style->object->getAttribute("x")); - y1= atof(style->object->getAttribute("y")); - x2=x1 + atof(style->object->getAttribute("width")); - y2=y1 + atof(style->object->getAttribute("height")); + x1= atof(style->object->getAttribute("x")); + y1= atof(style->object->getAttribute("y")); + dw= atof(style->object->getAttribute("width")); + dh= atof(style->object->getAttribute("height")); Geom::Point pLL(x1,y1); - Geom::Point pUR(x2,y2); - Geom::Point p2LL = pLL * tf; - Geom::Point p2UR = pUR * tf; + Geom::Point pLL2 = pLL * tf; //location of LL corner in Inkscape coordinates char *px; uint32_t cbPx; @@ -1715,10 +1708,33 @@ Bmih = bitmapinfoheader_set(w, h, 1, colortype, U_BI_RGB, 0, PXPERMETER, PXPERMETER, numCt, 0); Bmi = bitmapinfo_set(Bmih, ct); - U_POINTL Dest = pointl_set(round(p2LL[Geom::X] * PX2WORLD), round(p2LL[Geom::Y] * PX2WORLD)); - U_POINTL cDest = pointl_set(round((p2UR[Geom::X]-p2LL[Geom::X]) * PX2WORLD), round((p2UR[Geom::Y]-p2LL[Geom::Y]) * PX2WORLD)); + U_POINTL Dest = pointl_set(round(pLL2[Geom::X] * PX2WORLD), round(pLL2[Geom::Y] * PX2WORLD)); + 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); + 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; + U_XFORM tmpTransform; + tmpTransform.eM11 = tf[0]; + 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.eDy = (pLL2[Geom::Y] - pLL2prime[Geom::Y]) * PX2WORLD; + + rec=U_EMRSAVEDC_set(); + if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ + throw "Fatal programming error in PrintEmf::begin at U_EMRSAVEDC_set"; + } + + + rec = U_EMRMODIFYWORLDTRANSFORM_set(tmpTransform, U_MWT_LEFTMULTIPLY); + if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ + throw "Fatal programming error in PrintEmf::begin at EMRMODIFYWORLDTRANSFORM"; + } + + } rec = U_EMRSTRETCHDIBITS_set( U_RCL_DEF, //! Bounding rectangle in device units Dest, //! Destination UL corner in logical units @@ -1737,7 +1753,14 @@ free(px); free(Bmi); if(numCt)free(ct); - + + if(!FixImageRot){ + rec=U_EMRRESTOREDC_set(-1); + if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ + throw "Fatal programming error in PrintEmf::begin at U_EMRRESTOREDC_set"; + } + } + // std::cout << "end image" << std::endl; return 0; } @@ -1746,16 +1769,21 @@ unsigned int PrintEmf::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform) { // std::cout << "print_pathv " << std::endl << std::flush; - char *rec = NULL; + Geom::Affine tf = transform; + char *rec = NULL; - simple_shape = print_simple_shape(pathv, transform); + simple_shape = print_simple_shape(pathv, tf); if (simple_shape || pathv.empty()){ if (use_fill){ destroy_brush(); } // these must be cleared even if nothing is drawn or hbrush,hpen fill up if (use_stroke){ destroy_pen(); } return TRUE; } - Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform ); + /* inkscape to EMF scaling is done below, but NOT the rotation/translation transform, + that is handled by the EMF MODIFYWORLDTRANSFORM record + */ + + Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * tf ); rec = U_EMRBEGINPATH_set(); if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ @@ -1892,6 +1920,7 @@ if (use_stroke){ destroy_pen(); } + // std::cout << "end pathv" << std::endl; return TRUE; @@ -2119,6 +2148,7 @@ "false\n" "false\n" "false\n" + "false\n" "\n" "", new PrintEmf()); === modified file 'src/extension/internal/text_reassemble.c' --- src/extension/internal/text_reassemble.c 2012-12-13 04:10:54 +0000 +++ src/extension/internal/text_reassemble.c 2013-01-29 21:55:06 +0000 @@ -1,61 +1,52 @@ -/* text_reassemble.c -version 0.0.3 2012-12-07 -Copyright 2012, Caltech and David Mathog - -Reassemble formatted text from a series of text/position/font records. - +/** + @file text_reassemble.c + +\verbatim Method: 1. For all ordered text objects which are sequential and share the same esc. 2. For the first only pull x,y,esc and save, these define origin and rotation. 3. Save the text object. 4. Phase I: For all saved text objects construct lines. - 5. Check for allowed overlaps on sequential saved text object bounding rectangles. + 5. Check for allowed overlaps on sequential saved text object bounding rectangles. 6 If found merge second with first, check next one. - 7. If not found, start a new complex (line). + 7. If not found, start a new complex (line). 8. Phase II; for all lines construct paragraphs. - 9. Check alignment and line spacing of preceding line with current line. - 10. if alignment is the same, and line spacing is compatible merge current line into - current paragraph. Reaverage line spacing over all lines in paragraph. Check next one. - 11. If alignment does not match start a new paragraph. + 9. Check alignment and line spacing of preceding line with current line. + 10. if alignment is the same, and line spacing is compatible merge current line into + current paragraph. Reaverage line spacing over all lines in paragraph. Check next one. + 11. If alignment does not match start a new paragraph. (Test program) 12. Over all phase II paragraphs 13. Over all phase I lines in each paragraph. 14. Over all text objects in each line. - Emit SVG correspnding to this construct to a file dump.svg. + Emit SVG corresponding to this construct to a file dump.svg. + (Conversion to other file types would be modeled on this example.) 15. Clean up. (General program) - Like for the Test program, but final represenation may not be SVG. - -During the accept stage (1) it uses fontconfig/freetype data to store up font faces and to -work out the extent of each substring. This code assumes all text goes L->R, if it goes the other way -the same groupings would occur, just mirror imaged. - -At step 5 it calculates overlapping bounding boxes == formatted strings. The bounding boxes are extended -out by 1 character laterally and .49 character vertically. If it was able to figure out justification -that is returned along with the number of formatted strings. - -The caller then retrieves the x,y,xe,ye,string,format,font data and uses it to construct a formatted -string in whatever format the caller happens to be using. For Inskcape this would be SVG. - -Finally the caller cleans up, releasing all of the stored memory. FreeType memory is always all released. -FontConfig memory is released except for, optionally, not calling FcFini(), which would likely cause -problems for any program that was using FontConfig elsewhere. + Like for the Test program, but final representation may not be SVG. + Text object and bounding rectangle memory would all be released. If another set of + text will be processed then hang onto both Freetype and Fontconfig structures. If no + other text will be processed here, then also release Freetype structures. If the caller uses + Fontconfig elsewhere then do not release it, otherwise, do so. NOTE ON COORDINATES: x is positive to the right, y is positive down. So (0,0) is the upper left corner, and the lower left corner of a rectangle has a LARGER Y coordinate than the upper left. Ie, LL=(10,10) UR=(30,5) is typical. - - -Compilation of test program: +\endverbatim +*/ + +/* + +Compilation of test program (with all debugging output, but not loop testing): On Windows use: - gcc -Wall -DWIN32 -DTEST \ + gcc -Wall -DWIN32 -DTEST -DDBG_TR_PARA -DDBG_TR_INPUT \ -I. -I/c/progs/devlibs32/include -I/c/progs/devlibs32/include/freetype2\ -o text_reassemble text_reassemble.c uemf_utf.c \ - -lfreetype6 -lfontconfig-1 -lm -L/c/progs/devlibs32/bin + -lfreetype6 -lfontconfig-1 -liconv -lm -L/c/progs/devlibs32/bin On Linux use: - gcc -Wall -DTEST -I. -I/usr/include/freetype2 -o text_reassemble text_reassemble.c uemf_utf.c -lfreetype -lfontconfig -lm + gcc -Wall -DTEST -DTEST -DDBG_TR_PARA -DDBG_TR_INPUT -I. -I/usr/include/freetype2 -o text_reassemble text_reassemble.c uemf_utf.c -lfreetype -lfontconfig -lm Compilation of object file only (Windows): @@ -75,6 +66,12 @@ memory leaks. Ouput file is overwritten each time. +File: text_reassemble.c +Version: 0.0.4 +Date: 24-JAN-2013 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -84,10 +81,11 @@ #include "text_reassemble.h" #include "uemf_utf.h" /* For a couple of text functions. Exact copy from libUEMF. */ -/* end of functions from libUEMF */ - -/* Utility function, find a (sub)string in a caseinvariant manner, used for locating "Narrow" in font name. - Returns -1 if no match, else returns the position (numbered from 0) of the first character of the match. +/** + \brief Find a (sub)string in a caseinvariant manner, used for locating "Narrow" in font name + \return Returns -1 if no match, else returns the position (numbered from 0) of the first character of the match. + \param string Text to search + \param sub Text to find */ int TR_findcasesub(char *string, char *sub){ int i,j; @@ -105,16 +103,19 @@ } /** -Get the advance for the 32 bit character, returned value has units of 1/64th of a Point. - When load_flags == FT_LOAD_NO_SCALE is used the internal advance is in 1/64th of a point. - This does NOT stop scaling on kerning values! - When load_flags == FT_LOAD_TARGET_NORMAL is used the internal advance also seem to be in 1/64th of a point. The scale + \brief Get the advance for the 32 bit character + + \return Returns -1 on error, or advance in units of 1/64th of a Point. + \param fsp Pointer to FNT_SPECS struct. + \param wc Current character (32 bit int) + \param pc Previous character + \param load_flags Controls internal advance: + FT_LOAD_NO_SCALE, internal advance is in 1/64th of a point. (kerning values are still scaled) + FT_LOAD_TARGET_NORMAL internal advance is in 1/64th of a point. The scale factor seems to be (Font Size in points)*(DPI)/(32.0 pnts)*(72 dpi). -kern_mode, One of FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, FT_KERNING_UNSCALED -wc is the current character -pc is the previous character, 0 if there was not one - If ymin,ymax are passed in, then if the character's limits decrease/increase that value, it is modified (for founding string bounding box) -On error return -1. + \param kern_mode FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, or FT_KERNING_UNSCALED. Set to match calling application. + \param ymin If the pointer is defined, the value is adjusted if ymin of wc character is less than the current value. + \param ymax If the pointer is defined, the value is adjusted if ymin of wc character is more than the current value. */ int TR_getadvance(FNT_SPECS *fsp, uint32_t wc, uint32_t pc, int load_flags, int kern_mode, int *ymin, int *ymax){ FT_Glyph glyph; @@ -137,15 +138,12 @@ } /** -Get the kerning for a pair of 32 bit characters, returned value has units of 1/64th of a Point. - When load_flags == FT_LOAD_NO_SCALE is used the internal advance is in 1/64th of a point. - This does NOT stop scaling on kerning values! - When load_flags == FT_LOAD_TARGET_NORMAL is used the internal advance also seem to be in 1/64th of a point. The scale - factor seems to be (Font Size in points)*(DPI)/(32.0 pnts)*(72 dpi). -kern_mode, One of FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, FT_KERNING_UNSCALED -wc is the current character -pc is the previous character, 0 if there was not one -Returns 0 on error or if the kerning is 0. + \brief Get the kerning for a pair of 32 bit characters + \return Returns 0 on error, or kerning value (which may be 0) for the pair in units of 1/64th of a point. + \param fsp Pointer to FNT_SPECS struct. + \param wc Current character (32 bit int) + \param pc Previous character + \param kern_mode FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, or FT_KERNING_UNSCALED. Set to match calling application. */ int TR_getkern2(FNT_SPECS *fsp, uint32_t wc, uint32_t pc, int kern_mode){ int this_glyph_index; @@ -166,18 +164,12 @@ } /** -Get the kerning for a pair of 32 bit characters, where one is the last charcter in the previous text block, -and the other is the first in the current text block. - When load_flags == FT_LOAD_NO_SCALE is used the internal advance is in 1/64th of a point. - This does NOT stop scaling on kerning values! - When load_flags == FT_LOAD_TARGET_NORMAL is used the internal advance also seem to be in 1/64th of a point. The scale - factor seems to be (Font Size in points)*(DPI)/(32.0 pnts)*(72 dpi). -kern_mode, One of FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, FT_KERNING_UNSCALED -tsp is current text object -ptsp is the previous text object -wc is the current character -pc is the previous character -Returns 0 on error or if the kerning is 0. + \brief Get the kerning for a pair of 32 bit characters, where one is the last charcter in the previous text block, and the other is the first in the current text block. + \return Returns 0 on error, or kerning value (which may be 0) for the pair in units of 1/64th of a point. + \param fsp Pointer to FNT_SPECS struct. + \param tsp current text object + \param ptsp previous text object + \param kern_mode FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, or FT_KERNING_UNSCALED. Set to match calling application. */ int TR_kern_gap(FNT_SPECS *fsp, TCHUNK_SPECS *tsp, TCHUNK_SPECS *ptsp, int kern_mode){ int kern=0; @@ -206,14 +198,19 @@ -/* If the complex is a TR_TXT or TR_LINE find its baseline. - If the complex is TR_PARA+* find the baseline of the last line. - If AscMax or DscMax exists find the maximum Ascender/Descender size in this complex. - If there are multiple text elements in a TR_LINE, the baseline is that of the - element that uses the largest font. This will definitely give the wrong - result if that line starts with a super or subscript that is full font size, but - they are usually smaller. - returns 0 if it screws up and cannot figure out the baseline. +/** + \brief Find baseline on Y axis of a complex. + If the complex is a TR_TEXT or TR_LINE find its baseline. + If the complex is TR_PARA_[UCLR]J find the baseline of the last line. + If there are multiple text elements in a TR_LINE, the baseline is that of the + element that uses the largest font. This will definitely give the wrong + result if that line starts with a super or subscript that is full font size, but + they are usually smaller. + \return Returns 0 if it cannot determine a baseline, else returns the baseline Y coordinate. + \param tri pointer to the TR_INFO structure holding all TR data + \param src index of the current complex + \param ymax If the pointer is defined, the value is adjusted if ymax of current complex is more than the current value. + \param ymin If the pointer is defined, the value is adjusted if ymin of current complex is less than the current value. */ double TR_baseline(TR_INFO *tri, int src, double *ymax, double *ymin){ double baseline=0; @@ -277,16 +274,28 @@ return(baseline); } -/* check or set vadvance on growing complex dst with positions of text in - potential TR_LINE/TR_TEXT src. Vadvance is a multiplicative factor like 1.25. - The distance between successive baselines is vadvance * max(font_size), where the maximum - is over all text elements in src. - lines is the index of the first text block that was added, so src - lines can be used - to determine the weight to give to each new vadvance value as it is merged into the - running weighted average. This improves the accuracy of the vertical advance, since - there can be some noise introduced when lines have different maximum font sizes. - Returns 0 on success. - Returns !0 on failure +/** + \brief Check or set vertical advance on the growing complex relative to the current complex. + Vadvance is a multiplicative factor like 1.25. + The distance between successive baselines is vadvance * max(font_size), where the maximum + is over all text elements in src. + The growing complex is always the last one in the CX_INFO section of the TR_INFO structure. + If an existing vadvance does not match the one which would be required to fit the next complex + to add to the growing one, it terminates a growing complex. (Ie, starts a new paragraph.) + Find baseline on Y axis of a complex. + If the complex is a TR_TEXT or TR_LINE find its baseline. + If the complex is TR_PARA+* find the baseline of the last line. + If there are multiple text elements in a TR_LINE, the baseline is that of the + element that uses the largest font. This will definitely give the wrong + result if that line starts with a super or subscript that is full font size, but + they are usually smaller. + \return Returns 0 on success, !0 on failure. + \param tri pointer to the TR_INFO structure holding all TR data + \param src index of the current complex, to be added to the growing complex. + This lets the value of "src - lines" determine the weight to give to each new vadvance value + as it is merged into the running weighted average. This improves the accuracy of the vertical advance, + since there can be some noise introduced when lines have different maximum font sizes. + \param lines index of the first text block that was added to the growing complex. */ int TR_check_set_vadvance(TR_INFO *tri, int src, int lines){ int status = 0; @@ -328,7 +337,10 @@ } -/* Initialize the ftinfo system. Sets up a freetype library to use in this context. Returns NULL on failure. */ +/** + \brief Initialize an FT_INFO structure. Sets up a freetype library to use in this context. + \returns a pointer to the FT_INFO structure created, or NULL on error. +*/ FT_INFO *ftinfo_init(void){ FT_INFO *fti = NULL; if(FcInit()){ @@ -354,8 +366,11 @@ return(fti); } -/* verifies that there is space to add one more entry. - 0 on sucess, anything else is an error */ +/** + \brief Make an FT_INFO structure insertable. Adds storage as needed. + \param fti pointer to the FT_INFO structure + \returns 0 on success, !0 on error. +*/ int ftinfo_make_insertable(FT_INFO *fti){ int status=0; if(!fti)return(2); @@ -375,8 +390,12 @@ } -/* Insert an fsp into an fti - 0 on sucess, anything else is an error */ +/** + \brief Insert a copy of a FNT_SPECS structure into the FT_INFO structure. + \param fti pointer to the FT_INFO structure. + \param fsp pointer to the FNT_SPECS structure. + \returns 0 on success, !0 on error. +*/ int ftinfo_insert(FT_INFO *fti, FNT_SPECS *fsp){ int status=1; if(!fti)return(2); @@ -390,8 +409,11 @@ -/* Shut down the ftinfo system. Release all memory. - call like: fi_ptr = ftinfo_release(fi_ptr) +/** + \brief Release an FT_INFO structure. Release all associated memory. + Use like: fi_ptr = ftinfo_release(fi_ptr) + \param fti pointer to the FT_INFO structure. + \returns NULL. */ FT_INFO *ftinfo_release(FT_INFO *fti){ int i; @@ -410,9 +432,13 @@ return NULL; } -/* Clear the ftinfo system. Release all Freetype memory but do NOT shut down Fontconfig. This would - be called in preference to ftinfo_release if some other part of the program needed to continue using - Fontconfig.: fi_ptr = ftinfo_clear(fi_ptr) +/** + \brief Clear an FT_INFO structure. Release all Freetype memory but does not release Fontconfig. + This would be called in preference to ftinfo_release() if some other part of the program needed + to continue using Fontconfig. + Use like: fi_ptr = ftinfo_clear(fi_ptr) + \param fti pointer to the FT_INFO structure. + \returns NULL. */ FT_INFO *ftinfo_clear(FT_INFO *fti){ int i; @@ -431,8 +457,11 @@ } -/* verifies that there is space to add one more entry. - 0 on sucess, anything else is an error */ +/** + \brief Make a CHILD_SPECS structure insertable. Adds storage as needed. + \param csp pointer to the CHILD_SPECS structure + \returns 0 on success, !0 on error. +*/ int csp_make_insertable(CHILD_SPECS *csp){ int status=0; if(!csp)return(2); @@ -451,7 +480,12 @@ return(status); } -/* Add a member (src) to a child spec. 0 on success, anything else is an error */ +/** + \brief Add a member to a CHILD_SPECS structure. (Member is an index for either a text object or a complex.) + \param dst pointer to the CHILD_SPECS structure. + \param src index of the member. + \returns 0 on success, !0 on error. +*/ int csp_insert(CHILD_SPECS *dst, int src){ int status=1; if(!dst)return(2); @@ -462,8 +496,14 @@ return(status); } -/* Add all the members of child spec src to child spec dst. -0 on success, anything else is an error */ +/** + \brief Append all the members of one CHILD_SPECS structure to another CHILD_SPECS structure. + Member is an index for either a text object or a complex. + The donor is not modified. + \param dst pointer to the recipient CHILD_SPECS structure. + \param src pointer to the donor CHILD_SPECS structure. + \returns 0 on success, !0 on error. +*/ int csp_merge(CHILD_SPECS *dst, CHILD_SPECS *src){ int i; int status=1; @@ -476,8 +516,10 @@ return(status); } -/* Shut down the cxinfo system. Release all memory. - call like: (void) csp_release(csp_ptr). +/** + \brief Release a CHILD_SPECS structure. Release all associated memory. + \param csp pointer to the CHILD_SPECS structure. + \returns NULL. */ void csp_release(CHILD_SPECS *csp){ if(csp){ @@ -488,7 +530,10 @@ } -/* Initialize the cxinfo system. Returns NULL on failure. */ +/** + \brief Initialize an CX_INFO structure. Holds complexes (multiple text objects in known positions and order.) + \returns a pointer to the CX_INFO structure created, or NULL on error. +*/ CX_INFO *cxinfo_init(void){ CX_INFO *cxi = NULL; cxi = (CX_INFO *)calloc(1,sizeof(CX_INFO)); @@ -501,9 +546,11 @@ return(cxi); } -/* verifies that there is space to add one more entry. - Creates the structure if it is passed a null pointer. - 0 on sucess, anything else is an error */ +/** + \brief Make a CX_INFO structure insertable. Adds storage as needed. + \returns 0 on success, !0 on error. + \param cxi pointer to the CX_INFO structure +*/ int cxinfo_make_insertable(CX_INFO *cxi){ int status=0; if(cxi->used < cxi->space){ @@ -521,10 +568,14 @@ return(status); } -/* Insert a complex of "type" with one member (src) and that src's associated rectangle (by index). - If type is TR_TEXT src is an index for tpi->chunks[] - If type is TR_LINE src is an index for cxi->kids[] - 0 on sucess, anything else is an error */ +/** + \brief Insert a complex into the CX_INFO structure. (Insert may be either TR_TEXT or TR_LINE.) + \returns 0 on success, !0 on error. + \param cxi pointer to the CX_INFO structure (complexes). + \param src index of the the complex to insert. + \param src_rt_tidx index of the bounding rectangle + \param type TR_TEXT (index is for tpi->chunks[]) or TR_LINE (index is for cxi->kids[]) +*/ int cxinfo_insert(CX_INFO *cxi, int src, int src_rt_tidx, enum tr_classes type){ int status=1; if(!cxi)return(2); @@ -537,10 +588,13 @@ return(status); } -/* Append a a complex "src" of the last complex and change the complex type to "type". - If type is TR_LINE src is an index for tpi->chunks[] - If type is TR_PARA_* src is an index for cxi->kids[], and the incoming complex is a line. - 0 on sucess, anything else is an error */ +/** + \brief Append a complex to the CX_INFO structure and give it a type. + \param cxi pointer to the CX_INFO structure (complexes). + \param src index of the complex to append. + \param type TR_LINE (src is an index for tpi->chunks[]) or TR_PARA (src is an index for cxi->kids[]). + \returns 0 on success, !0 on error. +*/ int cxinfo_append(CX_INFO *cxi, int src, enum tr_classes type){ int status=1; if(!cxi)return(2); @@ -552,8 +606,14 @@ } -/* Merge a complex dst with N members (N>=1) by adding a second complex src . Change the type to "type" - 0 on sucess, anything else is an error */ +/** + \brief Merge a complex dst with N members (N>=1) by adding a second complex src, and change the type. + \param cxi pointer to the CX_INFO structure (complexes). + \param dst index of the complex to expand. + \param src index of the donor complex (which is not modified). + \param type TR_LINE (src is an index for tpi->chunks[]) or TR_PARA (src is an index for cxi->kids[]). + \returns 0 on success, !0 on error. +*/ int cxinfo_merge(CX_INFO *cxi, int dst, int src, enum tr_classes type){ int status =1; if(!cxi)return(2); @@ -564,7 +624,9 @@ return(status); } -/* For debugging purposes,not used in production code. +/** + \brief Dump the contents of the TR_INFO structure to stdout. For debugging purposes,not used in production code. + \param tri pointer to the TR_INFO structure. */ void cxinfo_dump(TR_INFO *tri){ int i,j,k; @@ -600,8 +662,11 @@ return; } -/* Shut down the cxinfo system. Release all memory. - call like: cxi_ptr = cxinfo_release(cxi_ptr) +/** + \brief Release a CX_INFO structure. Release all associated memory. + use like: cxi = cxiinfo_release(cxi); + \param cxi pointer to the CX_INFO structure. + \returns NULL. */ CX_INFO *cxinfo_release(CX_INFO *cxi){ int i; @@ -614,7 +679,10 @@ } -/* Initialize the tpinfo system. Returns NULL on failure. */ +/** + \brief Initialize an TP_INFO structure. Holds text objects from which complexes are built. + \returns a pointer to the TP_INFO structure created, or NULL on error. +*/ TP_INFO *tpinfo_init(void){ TP_INFO *tpi = NULL; tpi = (TP_INFO *)calloc(1,sizeof(TP_INFO)); @@ -628,8 +696,11 @@ } -/* verifies that there is space to add one more entry. - 0 on sucess, anything else is an error */ +/** + \brief Make a TP_INFO structure insertable. Adds storage as needed. + \returns 0 on success, !0 on error. + \param tpi pointer to the TP_INFO structure +*/ int tpinfo_make_insertable(TP_INFO *tpi){ int status=0; if(tpi->used >= tpi->space){ @@ -644,8 +715,12 @@ return(status); } -/* Insert a TCHUNK_SPEC as a tpi chunk.. - 0 on sucess, anything else is an error */ +/** + \brief Insert a copy of a TCHUNK_SPECS structure into a TP_INFO structure. (Insert a text object.) + \returns 0 on success, !0 on error. + \param tpi pointer to the TP_INFO structure + \param tsp pointer to the TCHUNK_SPECS structure +*/ int tpinfo_insert(TP_INFO *tpi, TCHUNK_SPECS *tsp){ int status=1; if(!tpi)return(2); @@ -658,8 +733,11 @@ return(status); } -/* Shut down the tpinfo system. Release all memory. - call like: tpi_ptr = tpinfo_release(tpi_ptr) +/** + \brief Release a TP_INFO structure. Release all associated memory. + use like: tpi = tpinfo_release(tpi); + \returns NULL. + \param tpi pointer to the TP_INFO structure. */ TP_INFO *tpinfo_release(TP_INFO *tpi){ int i; @@ -672,7 +750,10 @@ return NULL; } -/* Initialize the brinfo system. Returns NULL on failure. */ +/** + \brief Initialize an BR_INFO structure. Holds bounding rectangles, for both text objects and complexes. + \returns a pointer to the BR_INFO structure created, or NULL on error. +*/ BR_INFO *brinfo_init(void){ BR_INFO *bri = NULL; bri = (BR_INFO *)calloc(1,sizeof(BR_INFO)); @@ -685,9 +766,11 @@ return(bri); } -/* verifies that there is space to add one more entry. - Creates rects if that pointer is NULL. - 0 on sucess, anything else is an error */ +/** + \brief Make a BR_INFO structure insertable. Adds storage as needed. + \returns 0 on success, !0 on error. + \param bri pointer to the BR_INFO structure +*/ int brinfo_make_insertable(BR_INFO *bri){ int status=0; if(!bri)return(2); @@ -698,9 +781,12 @@ return(status); } -/** Append a BRECT_SPEC element to brinfo. - Side effect - may realloc bri->rects, so element MUST NOT be a pointer into that array! - 0 on sucess, anything else is an error */ +/** + \brief Insert a copy of a BRECT_SPEC structure into a BR_INFO structure. (Insert a bounding rectangle.) + \returns 0 on success, !0 on error. + \param bri pointer to the BR_INFO structure + \param element pointer to the BRECT_SPECS structure +*/ int brinfo_insert(BR_INFO *bri, BRECT_SPECS *element){ int status=1; if(!bri)return(2); @@ -711,8 +797,13 @@ return(status); } -/** Merge BRECT_SPEC element src with dst. dst becomes the merged result. - 0 on sucess, anything else is an error */ +/** + \brief Merge BRECT_SPEC element src into/with BRECT_SPEC element dst. src is unchanged. (Merge two bounding rectangles.) + \returns 0 on success, !0 on error. + \param bri pointer to the BR_INFO structure + \param dst index of the destination bounding rectangle. + \param src index of the source bounding rectangle. +*/ int brinfo_merge(BR_INFO *bri, int dst, int src){ if(!bri)return(1); if(dst<0 || dst>= bri->used)return(2); @@ -735,18 +826,26 @@ return(0); } -/** Check for an allowable overlap of two rectangles. The method works backwards, look for all reasons - they might not overlap, and none are found, then the rectangles do overlap. - An overlap here does not count just a line or a point - area must be involved. - dst one retangle to test - src the other rectangle to test - rp_src padding to apply to src, make it a little bigger, as in, allow leading or trailing spaces - 0 on sucess, 1 on no overlap, anything else is an error */ +/** + \brief Check for an allowable overlap of two bounding rectangles. + Allowable overlap is any area overlap of src and dst bounding rectangles, after + they have been expanded (padded) by allowed edge expansions. (For instance, if + missing spaces must be accounted for.) + The method works backwards: look for all reasons they might not overlap, + if none are found, then the rectangles do overlap. + An overlap here does not count just a line or a point - area must be involved. + \returns 0 on success (overlap detected), 1 on no overlap, anything else is an error. + \param bri pointer to the BR_INFO structure + \param dst index of the destination bounding rectangle. + \param src index of the source bounding rectangle. + \param rp_dst Pointer to edge padding values for dst. + \param rp_src Pointer to edge padding values for src. +*/ int brinfo_overlap(BR_INFO *bri, int dst, int src, RT_PAD *rp_dst, RT_PAD *rp_src){ int status; BRECT_SPECS *br_dst; BRECT_SPECS *br_src; - if(!bri)return(2); + if(!bri || !rp_dst || !rp_src)return(2); if(dst<0 || dst>= bri->used)return(3); if(src<0 || src>= bri->used)return(4); br_dst=&bri->rects[dst]; @@ -759,8 +858,21 @@ ){ status = 1; } - else { /* overlap not excluded, so it must occur */ - status = 0; + else { + /* overlap not excluded, so it must occur. + Only accept overlaps that are mostly at one end or the other, not mostly top or bottom. + If the following condition is true then there is no more than a tiny bit of horizontal overlap of src + within dist, which suggests that the two pieces of text may be considered part of one line. + (For a vertical alphabet the same method could be used for up/down.) */ + if( + (br_src->xll >= br_dst->xur - rp_dst->right) || /* src overlaps just a little on the right (L->R language) */ + (br_src->xur <= br_dst->xll + rp_dst->left) /* src overlaps just a little on the left (R->L language) */ + ){ + status = 0; + } + else { /* Too much overlap, reject the overlap */ + status = 1; + } } /* printf("Overlap status:%d\nOverlap trects (LL,UR) dst:(%lf,%lf),(%lf,%lf) src:(%lf,%lf),(%lf,%lf)\n", @@ -795,9 +907,16 @@ return(status); } -/* Attempt to deduce justification of a paragraph from the bounding rectangles for two lines. If type in not UJ -then the alignment must match or UJ is returned. "slop" is the numeric inaccuracy which is permitted - two values -within that range are the same as identical.*/ +/** + \brief Try to deduce justification of a paragraph from the bounding rectangles for two successive lines. + \returns one of TR_PARA_ UJ (unknown justified), LJ, CJ, or RJ (left, center, or right justified). + \param bri pointer to the BR_INFO structure + \param dst index of the destination bounding rectangle. + \param src index of the source bounding rectangle. + \param slop allowed error in edge alignment. + \param type Preexisting justification for dst, if any. Justification of dst and src must match this or + TR_PARA_UJ is returned even if dst and src have some (other) alignment. +*/ enum tr_classes brinfo_pp_alignment(BR_INFO *bri, int dst, int src, double slop, enum tr_classes type){ enum tr_classes newtype; BRECT_SPECS *br_dst = & bri->rects[dst]; @@ -841,8 +960,11 @@ return(newtype); } -/* Shut down the tpinfo system. Release all memory. - call like: bri_ptr = brinfo_release(bri_ptr) +/** + \brief Release a BR_INFO structure. Release all associated memory. + use like: bri = brinfo_release(bri); + \param bri pointer to the BR_INFO structure. + \returns NULL. */ BR_INFO *brinfo_release(BR_INFO *bri){ if(bri){ @@ -854,7 +976,10 @@ -/* Initialize the trinfo system. Returns NULL on failure. */ +/** + \brief Initialize an TR_INFO structure. Holds all data for text reassembly. + \returns a pointer to the TR_INFO structure created, or NULL on error. +*/ TR_INFO *trinfo_init(TR_INFO *tri){ if(tri)return(tri); /* tri is already set, double initialization is not allowed */ if(!(tri = (TR_INFO *)calloc(1,sizeof(TR_INFO))) || @@ -872,7 +997,14 @@ return(tri); } -/* release all memory from the trinfo system. */ +/** + \brief Release a TR_INFO structure completely. + Release all associated memory, including FontConfig. + See also trinfo_clear() and trinfo_release_except_FC(). + use like: tri = trinfo_release(tri); + \param tri pointer to the TR_INFO structure. + \returns NULL. +*/ TR_INFO *trinfo_release(TR_INFO *tri){ if(tri){ if(tri->bri)tri->bri=brinfo_release(tri->bri); @@ -885,8 +1017,15 @@ return(NULL); } -/* release everything except Fontconfig, which may still be needed elsewhere in a program -and there is no way to figure that out here. */ +/** + \brief Release a TR_INFO structure mostly. + Release all associated memory EXCEPT Fontconfig. + Fontconfig may still be needed elsewhere in a program and there is no way to figure that out here. + See also trinfo_clear() and trinfo_release(). + use like: tri = trinfo_release_except_FC(tri); + \param tri pointer to the TR_INFO structure. + \returns NULL. +*/ TR_INFO *trinfo_release_except_FC(TR_INFO *tri){ if(tri){ if(tri->bri)tri->bri=brinfo_release(tri->bri); @@ -899,9 +1038,15 @@ return(NULL); } -/* clear the text and rectangle memory from the trinfo system. Leave the font -information alone unless there is an error, in which case clear that too. The odds -are that at least some of the fonts will be reused, so faster to leave them in place. */ +/** + \brief Clear a TR_INFO structure. + Releases text and rectangle information, but retains font information, both + Freetype information and Fontconfig information. + See also trinfo_release() and trinfo_release_except_FC(). + Use like: tri = trinfo_clear(tri); + \param tri pointer to the TR_INFO structure. + \returns NULL. +*/ TR_INFO *trinfo_clear(TR_INFO *tri){ if(tri){ tri->dirty = 0; /* set these back to their defaults */ @@ -927,8 +1072,12 @@ return(tri); } -/* Load the face by fontname and font size, return the idx. If this combination is already loaded then look it up - and return the idx. +/** + \brief Load a (new) font by name into a TR_INFO structure. + \returns index of font. If the font was already loaded return the existing index. + \param tri pointer to the TR_INFO structure. + \param fontname UTF-8 font name + \param tsp pointer to the TCHUNK_SPECS structure - used to construct a font query string. */ int trinfo_load_fontname(TR_INFO *tri, uint8_t *fontname, TCHUNK_SPECS *tsp){ @@ -1009,14 +1158,17 @@ } -/* Set the quantization error value. If coordinates have passed through an integer form limits - in accuracy may have been imposed. For instance, if the X coordinate of a point in such a file - is 1000, and the conversion factor from those coordinates to points is .04, then eq is .04. This - just says that single coordinates are only good to within .04, and two coordinates may differ by as much - as .08, just due to quantization error. So if some calculation shows a difference of - .02 it may be interpreted as this sort of error and set to 0.0. - - Returns 0 on success, >0 on error. +/** + \brief Set the quantization error value for a TR_INFO structure. + If coordinates have passed through an integer form limits + in accuracy may have been imposed. For instance, if the X coordinate of a point in such a file + is 1000, and the conversion factor from those coordinates to points is .04, then eq is .04. This + just says that single coordinates are only good to within .04, and two coordinates may differ by as much + as .08, just due to quantization error. So if some calculation shows a difference of + .02 it may be interpreted as this sort of error and set to 0.0. + \returns 0 on success, !0 on error. + \param tri pointer to TR_INFO structure + \param qe quantization error. */ int trinfo_load_qe(TR_INFO *tri, double qe){ if(!tri)return(1); @@ -1025,9 +1177,16 @@ return(0); } -/* Set the FT parameters flags and kern mode and decide whether or not to to use kerning. - No error checking on those values. - Returns 0 on success, >0 on error. +/** + \brief Set Freetype parameters and kerning mode (if any) in a TRI_INFO structure. + \returns 0 on success, !0 on error. + \param tri pointer to a TR_INFO structure + \param use_kern 0 if kerning is to be employed, !0 otherwise. + \param load_flags Controls internal advance: + FT_LOAD_NO_SCALE, internal advance is in 1/64th of a point. (kerning values are still scaled) + FT_LOAD_TARGET_NORMAL internal advance is in 1/64th of a point. The scale + factor seems to be (Font Size in points)*(DPI)/(32.0 pnts)*(72 dpi). + \param kern_mode FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, or FT_KERNING_UNSCALED. Set to match calling application. */ int trinfo_load_ft_opts(TR_INFO *tri, int use_kern, int load_flags, int kern_mode){ if(!tri)return(1); @@ -1037,8 +1196,11 @@ return(0); } -/* Append text to the output buffer, expanding it if necessary. - returns 0 on success, -1 on failure +/** + \brief Append text to a TR_INFO struct's output buffer, expanding it if necessary. + \returns 0 on success, !0 on error. + \param tri pointer to a TR_INFO structure + \param src Pointer to a text string. */ int trinfo_append_out(TR_INFO *tri, char *src){ size_t slen; @@ -1057,20 +1219,22 @@ } -/* load a text record into the system. On success returns 0. Any error returns !0. - Escapement must match that of first record. - Status of -1 indicates that an escapement change was detected. - idx etc in tsp must have been set. - load_flags - see TR_getadvance, must match graphics model of CURRENT program. - kern_mode - see TR_getadvance, must match graphics model of CURRENT program. - use_kern - true if kerning is used, must match graphics model of CURRENT program +/** + \brief Load a text object into a TR_INFO struct. + \returns 0 on success, !0 on error. -1 means that the escapement is different from the objects already loaded. + \param tri pointer to a TR_INFO structure + \param tsp pointer to a TCHUNK_SPECS structure (text object to load) + \param escapement angle in degrees of the text object. + \param flags special processing flags: + TR_EMFBOT calculate Y coordinates of ALIBOT object compatible with EMF files TA_BOTTOM alignment. */ int trinfo_load_textrec(TR_INFO *tri, TCHUNK_SPECS *tsp, double escapement, int flags){ int status; double x,y,xe; - double asc,dsc; + double asc,dsc; /* these are the ascender/descender for the actual text */ int ymin,ymax; + double fasc,fdsc; /* these are the ascender/descender for the font as a whole (text independent) */ TP_INFO *tpi; FT_INFO *fti; BR_INFO *bri; @@ -1104,8 +1268,8 @@ tpinfo_insert(tpi,tsp); current=tpi->used-1; - ymin = 64000; - ymax = -64000; + ymin = 64000; + ymax = -64000; /* The geometry model has origin Y at the top of screen, positive Y is down, maximum positive Y is at the bottom of the screen. That makes "top" (by positive Y) actually the bottom @@ -1140,6 +1304,13 @@ else { return(6); } prev=*tptr; } + asc = ((double) (ymax))/64.0; + dsc = ((double) (ymin))/64.0; /* This is negative */ +/* This did not work very well because the ascender/descender went well beyond the actual characters, causing + overlaps on lines that did not actually overlap (vertically). + asc = ((double) (fsp->face->ascender) )/64.0; + dsc = ((double) (fsp->face->descender))/64.0; +*/ free(text32); @@ -1149,6 +1320,10 @@ if(status>=0){ fsp->spcadv = ((double) status)/64.0; } else { return(7); } } + + /* find the font ascender descender (general one, not specific for current text) */ + fasc = ((double) (fsp->face->ascender) )/64.0; + fdsc = ((double) (fsp->face->descender))/64.0; if(tri->load_flags & FT_LOAD_NO_SCALE){ xe *= tsp->fs/32.0; @@ -1169,29 +1344,26 @@ bsp.xur = tpi->chunks[current].x; } - asc = ((double) (ymax))/64.0; - dsc = ((double) (ymin))/64.0; /* This is negative */ -/* This did not work very well because the ascender/descender went well beyond the actual characters, causing - overlaps on lines that did not actually overlap (vertically). - asc = ((double) (fsp->face->ascender) )/64.0; - dsc = ((double) (fsp->face->descender))/64.0; -*/ if(tri->load_flags & FT_LOAD_NO_SCALE){ - asc *= tsp->fs/32.0; - dsc *= tsp->fs/32.0; + asc *= tsp->fs/32.0; + dsc *= tsp->fs/32.0; + fasc *= tsp->fs/32.0; + fdsc *= tsp->fs/32.0; } - /* From this point forward y is on the baseline, so need to correct it in chunks */ - if( taln & ALIVERT & ALITOP ){ tpi->chunks[current].y += -dsc + asc; } - else if( taln & ALIVERT & ALIBASE){ } /* no correction required */ + /* From this point forward y is on the baseline, so need to correct it in chunks. The asc/dsc are the general + ones for the font, else the text content will muck around with the baseline in BAD ways. */ + if( taln & ALIVERT & ALITOP ){ tpi->chunks[current].y += fasc; } + else if( taln & ALIVERT & ALIBASE){ } /* no correction required */ else{ /* taln & ALIVERT & ALIBOT */ - if(flags & TR_EMFBOT){ tpi->chunks[current].y -= 0.35 * tsp->fs; } /* compatible with EMF implementations */ - else { tpi->chunks[current].y += dsc; } + if(flags & TR_EMFBOT){ tpi->chunks[current].y -= 0.35 * tsp->fs; } /* compatible with EMF implementations */ + else { tpi->chunks[current].y += fdsc; } } tpi->chunks[current].boff = -dsc; - /* since y is always on the baseline, the lower left and upper right are easy */ + /* since y is always on the baseline, the lower left and upper right are easy. These use asc/dsc for the particular text, + so that the bounding box will fit it tightly. */ bsp.yll = tpi->chunks[current].y - dsc; bsp.yur = tpi->chunks[current].y - asc; brinfo_insert(bri,&bsp); @@ -1200,10 +1372,14 @@ return(0); } -/* Font weight conversion, from fontconfig weights to SVG weights. -Anything not recognized becomes "normal" == 400. There is no interpolation because a value -that mapped to 775, for instance, most likely would not display at a weight intermediate -between 700 and 800. +/** + \brief Fontweight conversion. Fontconfig units to SVG units. + Anything not recognized becomes "normal" == 400. + There is no interpolation because a value that mapped to 775, for instance, most + likely would not display properly because it is intermediate between 700 and 800, and + only those need be supported in SVG viewers. + \returns SVG font weight + \param weight Fontconfig font weight. */ int TR_weight_FC_to_SVG(int weight){ int ret=400; @@ -1220,9 +1396,15 @@ return(ret); } -/* Set the padding that will be added to rectangles before checking for overlaps. - Method is set for L->R, or R->L text, not correct for vertical text. -*/ +/** + \brief Set the padding that will be added to bounding rectangles before checking for overlaps in brinfo_overlap(). + \returns void + \param rt_pad pointer to an RT_PAD structure. + \param up padding for the top of a bounding rectangle. + \param down padding for the bottom of a bounding rectangle. + \param left padding for the left of a bounding rectangle. + \param right padding for the right of a bounding rectangle. +*/ void TR_rt_pad_set(RT_PAD *rt_pad, double up, double down, double left, double right){ rt_pad->up = up; rt_pad->down = down; @@ -1230,7 +1412,10 @@ rt_pad->right = right; } -/* Convert from analyzed complexes to SVG format, stored in the "out" buffer of the tri. +/** + \brief Convert from analyzed complexes to SVG format. + \returns void + \param tri pointer to a TR_INFO struct which will be analyzed. Result is stored in its "out" buffer. */ void TR_layout_2_svg(TR_INFO *tri){ double x = tri->x; @@ -1481,15 +1666,19 @@ } /* end of i loop */ } -/** Attempt to figure out what the text was originally. - 1. Group text strings by overlaps (optionally allowing up to two spaces to be added) to produce larger rectangles. - Larger rectangles that are more or less sequential are LINES, otherwise they are EQN. - 2. Group sequential LINES into paragraphs (by smooth progression in position down page). +/** + \brief Attempt to figure out the original organization, in lines and paragraphs, of the text objects. + The method is: + 1. Generate complexes from the text objects (strings) by overlaps (optionally allowing up to two spaces to be + added) to produce larger rectangles. Complexes that are more or less sequential and have 2 or more text objects + are TR_LINEs, therwise they are TR_TEXT. + 2. Group sequential complexes (TR_LINE or TR_TEXT) into TR_PARA_UJ (paragraphs,by smooth progression in vertical + position down page). 3. Analyze the paragraphs to classify them as Left/Center/Right justified (possibly with indentation.) If - they do not fall into any of these categories break that one back down into LINES. - 4. Return the number of complex text objects. Value will be >=1 and <= number of text strings. - - Values <0 are errors + they do not fall into any of these categories break that one back down into TR_LINE/TR_TEXT. + 4. Return the number of complex text objects. + \returns Number of complexes. (>=1, <= number of text objects.) <0 is an error. + \param tri pointer to the TR_INFO structure holding the data, which will also hold the results. */ int TR_layout_analyze(TR_INFO *tri){ int i,j; @@ -1533,13 +1722,13 @@ TR_rt_pad_set(&rt_pad_i,tri->qe, tri->qe, 0.0, tri->qe + 2.0 * fti->fonts[tpi->chunks[i].fi_idx].spcadv); for(j=i+1; jused; j++){ - /* Reject font size changes of greater than 50%, these almost certainly not continuous text. These happen + /* Reject font size changes of greater than 50%, these are almost certainly not continuous text. These happen in math formulas, for instance, where a sum or integral is much larger than the other symbols. */ ratio = (double)(tpi->chunks[j].fs)/(double)(tpi->chunks[i].fs); if(ratio >2.0 || ratio <0.5)break; - /* for the trailing text: pad with one leading and no trailing spaces */ - TR_rt_pad_set(&rt_pad_j,tri->qe, tri->qe, 1.0 * fti->fonts[tpi->chunks[j].fi_idx].spcadv, 0.0); + /* for the trailing text: pad with one leading and trailing spaces (so it should work L->R and R->L */ + TR_rt_pad_set(&rt_pad_j,tri->qe, tri->qe, fti->fonts[tpi->chunks[j].fi_idx].spcadv, fti->fonts[tpi->chunks[j].fi_idx].spcadv); src_rt = tpi->chunks[j].rt_tidx; if(!brinfo_overlap(bri, dst_rt, /* index into bri for dst */ @@ -1547,7 +1736,9 @@ &rt_pad_i,&rt_pad_j)){ (void) cxinfo_append(cxi,j,TR_LINE); (void) brinfo_merge(bri,dst_rt,src_rt); - TR_rt_pad_set(&rt_pad_i, tri->qe, tri->qe, 0.0, tri->qe + 2.0 * fti->fonts[tpi->chunks[j].fi_idx].spcadv); + /* for the leading text: pad with two leading and trailing spaces (so it should work L->R and R->L */ + TR_rt_pad_set(&rt_pad_i, tri->qe, tri->qe, + tri->qe + 2.0 * fti->fonts[tpi->chunks[j].fi_idx].spcadv, tri->qe + 2.0 * fti->fonts[tpi->chunks[j].fi_idx].spcadv); } else { /* either alignment ge*/ break; @@ -1618,6 +1809,7 @@ } +/* no doxygen documentation below this point, these pieces are for the text program, not the library. */ #if TEST #define MAXLINE 2048 /* big enough for testing */ === modified file 'src/extension/internal/text_reassemble.h' --- src/extension/internal/text_reassemble.h 2012-12-13 04:10:54 +0000 +++ src/extension/internal/text_reassemble.h 2013-01-25 18:20:41 +0000 @@ -1,9 +1,14 @@ -/* text_reassemble.h -version 0.0.2 2012-12-07 -Copyright 2012, Caltech and David Mathog +/** + @file text_reassemble.h libTERE headers. See text_reassemble.c for notes +File: text_reassemble.h +Version: 0.0.4 +Date: 24-JAN-2013 +Author: David Mathog, Biology Division, Caltech +email: mathog@caltech.edu +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -22,6 +27,7 @@ #include FT_FREETYPE_H #include FT_GLYPH_H +/** \cond */ #define TEREMIN(A,B) (A < B ? A : B) #define TEREMAX(A,B) (A > B ? A : B) @@ -31,151 +37,196 @@ #define ALLOCINFO_CHUNK 32 #define ALLOCOUT_CHUNK 8192 #define TRPRINT trinfo_append_out - -/* text alignment types */ -#define ALILEFT 0x01 -#define ALICENTER 0x02 -#define ALIRIGHT 0x04 -#define ALIHORI 0x07 -#define ALITOP 0x08 -#define ALIBASE 0x10 -#define ALIBOT 0x20 -#define ALIVERT 0x38 - -/* language direction types */ -#define LDIR_LR 0x00 -#define LDIR_RL 0x01 -#define LDIR_TB 0x02 - -/* Flags */ -#define TR_EMFBOT 0x01 /* use an approximation compatible with EMF file's "BOTTOM" text orientation, which is not the "bottom" for Freetype fonts */ - -/* complex classification types - TR_TEXT simple text object - TR_LINE linear assembly of TR_TEXTS - TR_PARA_UJ sequential assembly of TR_LINE into a paragraph, with unknown justification properties - TR_PARA_LJ ..., left justified - TR_PARA_CJ ..., center justified - TR_PARA_RJ ..., right justified -*/ -enum tr_classes {TR_TEXT,TR_LINE,TR_PARA_UJ,TR_PARA_LJ,TR_PARA_CJ,TR_PARA_RJ}; - -/* Fontinfo structure, values related to fonts */ +/** \endcond */ + +/** \defgroup text alignment types + Location of text's {X,Y} coordinate on bounding rectangle. + Values are compatible with Fontconfig. + @{ +*/ +#define ALILEFT 0x01 /**< text object horizontal alignment = left */ +#define ALICENTER 0x02 /**< text object horizontal alignment = center */ +#define ALIRIGHT 0x04 /**< text object horizontal alignment = right */ +#define ALIHORI 0x07 /**< text object horizontal alignment mask */ +#define ALITOP 0x08 /**< text object vertical alignment = top */ +#define ALIBASE 0x10 /**< text object vertical alignment = baseline */ +#define ALIBOT 0x20 /**< text object vertical alignment = bottom */ +#define ALIVERT 0x38 /**< text object vertical alignment mask */ +/** @} */ + +/** \defgroup language direction types + @{ +*/ +#define LDIR_LR 0x00 /**< left to right */ +#define LDIR_RL 0x01 /**< right to left */ +#define LDIR_TB 0x02 /**< top to bottom */ +/** @} */ + +/** \defgroup special processing flags + @{ +*/ +#define TR_EMFBOT 0x01 /**< use an approximation compatible with EMF file's "BOTTOM" text orientation, which is not the "bottom" for Freetype fonts */ +/** @} */ + +/** \enum tr_classes +classification of complexes + @{ +*/ +enum tr_classes { + TR_TEXT, /**< simple text object */ + TR_LINE, /**< linear assembly of TR_TEXTs */ + TR_PARA_UJ, /**< sequential assembly of TR_LINEs and TR_TEXTs into a paragraph - + unknown justification properties */ + TR_PARA_LJ, /**< ditto, left justified */ + TR_PARA_CJ, /**< ditto, center justified */ + TR_PARA_RJ /**< ditto, right justified */ + }; +/** @} */ + +/** + \brief Information for a font instance. +*/ typedef struct { - FT_Face face; /* font face structures (FT_FACE is a pointer!) */ - uint8_t *file; /* pointers to font paths to files */ - uint8_t *fname; /* pointers to font names */ - FcPattern *fpat; /* must hang onto this or faces operations break */ - double spcadv; /* advance equal to a space, in points */ - double fsize; /* face size in points */ + FT_Face face; /**< font face structures (FT_FACE is a pointer!) */ + uint8_t *file; /**< pointers to font paths to files */ + uint8_t *fname; /**< pointers to font names */ + FcPattern *fpat; /**< must hang onto this or faces operations break */ + double spcadv; /**< advance equal to a space, in points */ + double fsize; /**< face size in points */ } FNT_SPECS; +/** + \brief Information for all font instances. +*/ typedef struct { - FT_Library library; /* Fontconfig handle */ - FNT_SPECS *fonts; /* Array of fontinfo structures */ - int space; /* storage slots allocated */ - int used; /* storage slots in use */ + FT_Library library; /**< Fontconfig handle */ + FNT_SPECS *fonts; /**< Array of fontinfo structures */ + int space; /**< storage slots allocated */ + int used; /**< storage slots in use */ } FT_INFO; +/** + \brief Information for a single text object +*/ typedef struct { - uint8_t *string; /* UTF-8 text */ - double ori; /* Orientation, angle of characters with respect to baseline in degrees */ - double fs; /* font size of text */ - double x; /* x coord relative to tri x,y, in points */ - double y; /* y coord */ - double boff; /* Y LL corner - boff finds baseline */ - double vadvance; /* Line spacing typically 1.25 or 1.2, only set on the first text - element in a complex */ - uint32_t color; /* RGBA */ - int taln; /* text alignment with respect to x,y */ - int ldir; /* language diretion LDIR_* */ - int italics; /* italics, as in FontConfig */ - int weight; /* weight, as in FontConfig */ - int condensed; /* condensed, as in FontConfig */ - int co; /* condensed override, if set Font name included narrow */ - int rt_tidx; /* index of rectangle that contains it */ - int fi_idx; /* index of the font it uses */ + uint8_t *string; /**< UTF-8 text */ + double ori; /**< Orientation, angle of characters with respect to baseline in degrees */ + double fs; /**< font size of text */ + double x; /**< x coordinate, relative to TR_INFO x,y, in points */ + double y; /**< y coordinate, relative to TR_INFO x,y, in points */ + double boff; /**< Y LL corner - boff finds baseline */ + double vadvance; /**< Line spacing typically 1.25 or 1.2, only set on the first text + element in a complex */ + uint32_t color; /**< RGBA */ + int taln; /**< text alignment with respect to x,y */ + int ldir; /**< language diretion LDIR_* */ + int italics; /**< italics, as in FontConfig */ + int weight; /**< weight, as in FontConfig */ + int condensed; /**< condensed, as in FontConfig */ + int co; /**< condensed override, if set Font name included narrow */ + int rt_tidx; /**< index of rectangle that contains it */ + int fi_idx; /**< index of the font it uses */ } TCHUNK_SPECS; -/* Text Info/Position Info structure, values related to text properties and string geometry +/** + \brief Information for all text objects. Coordinates here are INTERNAL, after offset/rotate using values in TR_INFO. */ typedef struct { - TCHUNK_SPECS *chunks; /* text chunks */ - int space; /* storage slots allocated */ - int used; /* storage slots in use */ + TCHUNK_SPECS *chunks; /**< text chunks */ + int space; /**< storage slots allocated */ + int used; /**< storage slots in use */ } TP_INFO; -/* Bounding Rectangle(s) structure +/** + \brief Information for a single bounding rectangle. Coordinates here are INTERNAL, after offset/rotate using values in TR_INFO. */ typedef struct { - double xll; /* x rectangle lower left corner */ - double yll; /* y " */ - double xur; /* x upper right corner */ - double yur; /* y " */ - double xbearing; /* x bearing of the leftmost character */ + double xll; /**< x rectangle lower left corner */ + double yll; /**< y " */ + double xur; /**< x upper right corner */ + double yur; /**< y " */ + double xbearing; /**< x bearing of the leftmost character */ } BRECT_SPECS; +/** + \brief Information for all bounding rectangles. +*/ typedef struct { - BRECT_SPECS *rects; /* bounding rectangles */ - int space; /* storage slots allocated */ - int used; /* storage slots in use */ + BRECT_SPECS *rects; /**< bounding rectangles */ + int space; /**< storage slots allocated */ + int used; /**< storage slots in use */ } BR_INFO; +/** + \brief List of all members of a single complex. +*/ typedef struct { - int *members; /* array of immediate children (for TR_PARA_* these are indicies - for TR_TEXT or TR_LINE complexes also in cxi. For TR_TEXT - and TR_LINE these are indices to the actual text in tpi.) */ - int space; /* storage slots allocated */ - int used; /* storage slots in use */ + int *members; /**< array of immediate children (for TR_PARA_* these are indicies + for TR_TEXT or TR_LINE complexes also in cxi. For TR_TEXT + and TR_LINE these are indices to the actual text in tpi.) */ + int space; /**< storage slots allocated */ + int used; /**< storage slots in use */ } CHILD_SPECS; -/* Complex info structure, values related to the assembly of complex text from smaller pieces */ +/** + \brief Information for a single complex. +*/ typedef struct { - int rt_cidx; /* index of rectangle that contains all members */ - enum tr_classes type; /* classification of the complex */ - CHILD_SPECS kids; /* immediate child nodes of this complex, for type TR_TEXT the - idx refers to the tpi data. otherwise, cxi data */ + int rt_cidx; /**< index of rectangle that contains all members */ + enum tr_classes type; /**< classification of the complex */ + CHILD_SPECS kids; /**< immediate child nodes of this complex, for type TR_TEXT the + idx refers to the tpi data. otherwise, cxi data */ } CX_SPECS; +/** + \brief Information for all complexes. +*/ typedef struct { - CX_SPECS *cx; /* complexes */ - int space; /* storage slots allocated */ - int used; /* storage slots in use */ - int phase1; /* Number of complexes (lines + text fragments) entered in phase 1 */ - int lines; /* Number of lines in phase 1 */ - int paras; /* Number of complexes (paras) entered in phase 2 */ + CX_SPECS *cx; /**< complexes */ + int space; /**< storage slots allocated */ + int used; /**< storage slots in use */ + int phase1; /**< Number of complexes (lines + text fragments) entered in phase 1 */ + int lines; /**< Number of lines in phase 1 */ + int paras; /**< Number of complexes (paras) entered in phase 2 */ } CX_INFO; -/* Text reassemble, overall structure */ +/** + \brief Information for the entire text reassembly system. +*/ typedef struct { - FT_INFO *fti; /* Font info storage */ - TP_INFO *tpi; /* Text Info/Position Info storage */ - BR_INFO *bri; /* Bounding Rectangle Info storage */ - CX_INFO *cxi; /* Complex Info storage */ - uint8_t *out; /* buffer to hold formatted output */ - double qe; /* quantization error in points. */ - double esc; /* escapement angle in DEGREES */ - double x; /* coordinates of first text, in points */ - double y; - int dirty; /* 1 if text records are loaded */ - int use_kern; /* 1 if kerning is used, 0 if not */ - int load_flags; /* FT_LOAD_NO_SCALE or FT_LOAD_TARGET_NORMAL */ - int kern_mode; /* FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, or FT_KERNING_UNSCALED */ - int outspace; /* storage in output buffer allocated */ - int outused; /* storage in output buffer in use */ + FT_INFO *fti; /**< Font info storage */ + TP_INFO *tpi; /**< Text Info/Position Info storage */ + BR_INFO *bri; /**< Bounding Rectangle Info storage */ + CX_INFO *cxi; /**< Complex Info storage */ + uint8_t *out; /**< buffer to hold formatted output */ + double qe; /**< quantization error in points. */ + double esc; /**< escapement angle in DEGREES */ + double x; /**< x coordinate of first text object, in points */ + double y; /**< y coordinate of first text object, in points */ + int dirty; /**< 1 if text records are loaded */ + int use_kern; /**< 1 if kerning is used, 0 if not */ + int load_flags; /**< FT_LOAD_NO_SCALE or FT_LOAD_TARGET_NORMAL */ + int kern_mode; /**< FT_KERNING_DEFAULT, FT_KERNING_UNFITTED, or FT_KERNING_UNSCALED */ + int outspace; /**< storage in output buffer allocated */ + int outused; /**< storage in output buffer in use */ } TR_INFO; /* padding added to rectangles before overlap test */ +/** + \brief Information for one padding record. (Padding is added to bounding rectangles before overlap tests.) +*/ typedef struct { - double up; /* to top */ - double down; /* to bottom */ - double left; /* to left */ - double right; /* to right */ + double up; /**< to top */ + double down; /**< to bottom */ + double left; /**< to left */ + double right; /**< to right */ } RT_PAD; -/* iconv() has a funny cast on some older systems, on most recent ones +/** \cond */ +/* + iconv() has a funny cast on some older systems, on most recent ones it is just char **. This tries to work around the issue. If you build this on another funky system this code may need to be modified, or define ICONV_CAST on the compile line(but it may be tricky). @@ -186,6 +237,7 @@ #if !defined(ICONV_CAST) #define ICONV_CAST (char **) #endif //ICONV_CAST +/** \endcond */ /* Prototypes */ int TR_findcasesub(char *string, char *sub); @@ -209,7 +261,6 @@ int csp_insert(CHILD_SPECS *csp, int src); int csp_merge(CHILD_SPECS *dst, CHILD_SPECS *src); void csp_release(CHILD_SPECS *csp); -#define csp_clear csp_release /* since the CHILD_SPECS area itself is not deleted, clear == reset */ CX_INFO *cxinfo_init(void); int cxinfo_make_insertable(CX_INFO *cxi); === modified file 'src/extension/internal/uemf.c' --- src/extension/internal/uemf.c 2012-12-13 04:10:54 +0000 +++ src/extension/internal/uemf.c 2013-01-31 22:22:19 +0000 @@ -14,11 +14,11 @@ /* File: uemf.c -Version: 0.0.11 -Date: 07-DEC-2012 +Version: 0.0.14 +Date: 20-JAN-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -44,6 +44,145 @@ not in uemf.h or uemf_endian.h */ void U_swap2(void *ul, unsigned int count); +/** + \brief Look up the name of the EMR record by type. Returns U_EMR_INVALID if out of range. + + \return name of the EMR record, "U_EMR_INVALID" if out of range. + \param idx EMR record type. + +*/ +char *U_emr_names(unsigned int idx){ + if(idx U_EMR_MAX){ idx = 0; } + static char *U_WMR_NAMES[U_EMR_MAX+1]={ + "U_EMR_INVALID", + "U_EMR_HEADER", + "U_EMR_POLYBEZIER", + "U_EMR_POLYGON", + "U_EMR_POLYLINE", + "U_EMR_POLYBEZIERTO", + "U_EMR_POLYLINETO", + "U_EMR_POLYPOLYLINE", + "U_EMR_POLYPOLYGON", + "U_EMR_SETWINDOWEXTEX", + "U_EMR_SETWINDOWORGEX", + "U_EMR_SETVIEWPORTEXTEX", + "U_EMR_SETVIEWPORTORGEX", + "U_EMR_SETBRUSHORGEX", + "U_EMR_EOF", + "U_EMR_SETPIXELV", + "U_EMR_SETMAPPERFLAGS", + "U_EMR_SETMAPMODE", + "U_EMR_SETBKMODE", + "U_EMR_SETPOLYFILLMODE", + "U_EMR_SETROP2", + "U_EMR_SETSTRETCHBLTMODE", + "U_EMR_SETTEXTALIGN", + "U_EMR_SETCOLORADJUSTMENT", + "U_EMR_SETTEXTCOLOR", + "U_EMR_SETBKCOLOR", + "U_EMR_OFFSETCLIPRGN", + "U_EMR_MOVETOEX", + "U_EMR_SETMETARGN", + "U_EMR_EXCLUDECLIPRECT", + "U_EMR_INTERSECTCLIPRECT", + "U_EMR_SCALEVIEWPORTEXTEX", + "U_EMR_SCALEWINDOWEXTEX", + "U_EMR_SAVEDC", + "U_EMR_RESTOREDC", + "U_EMR_SETWORLDTRANSFORM", + "U_EMR_MODIFYWORLDTRANSFORM", + "U_EMR_SELECTOBJECT", + "U_EMR_CREATEPEN", + "U_EMR_CREATEBRUSHINDIRECT", + "U_EMR_DELETEOBJECT", + "U_EMR_ANGLEARC", + "U_EMR_ELLIPSE", + "U_EMR_RECTANGLE", + "U_EMR_ROUNDRECT", + "U_EMR_ARC", + "U_EMR_CHORD", + "U_EMR_PIE", + "U_EMR_SELECTPALETTE", + "U_EMR_CREATEPALETTE", + "U_EMR_SETPALETTEENTRIES", + "U_EMR_RESIZEPALETTE", + "U_EMR_REALIZEPALETTE", + "U_EMR_EXTFLOODFILL", + "U_EMR_LINETO", + "U_EMR_ARCTO", + "U_EMR_POLYDRAW", + "U_EMR_SETARCDIRECTION", + "U_EMR_SETMITERLIMIT", + "U_EMR_BEGINPATH", + "U_EMR_ENDPATH", + "U_EMR_CLOSEFIGURE", + "U_EMR_FILLPATH", + "U_EMR_STROKEANDFILLPATH", + "U_EMR_STROKEPATH", + "U_EMR_FLATTENPATH", + "U_EMR_WIDENPATH", + "U_EMR_SELECTCLIPPATH", + "U_EMR_ABORTPATH", + "U_EMR_UNDEF69", + "U_EMR_COMMENT", + "U_EMR_FILLRGN", + "U_EMR_FRAMERGN", + "U_EMR_INVERTRGN", + "U_EMR_PAINTRGN", + "U_EMR_EXTSELECTCLIPRGN", + "U_EMR_BITBLT", + "U_EMR_STRETCHBLT", + "U_EMR_MASKBLT", + "U_EMR_PLGBLT", + "U_EMR_SETDIBITSTODEVICE", + "U_EMR_STRETCHDIBITS", + "U_EMR_EXTCREATEFONTINDIRECTW", + "U_EMR_EXTTEXTOUTA", + "U_EMR_EXTTEXTOUTW", + "U_EMR_POLYBEZIER16", + "U_EMR_POLYGON16", + "U_EMR_POLYLINE16", + "U_EMR_POLYBEZIERTO16", + "U_EMR_POLYLINETO16", + "U_EMR_POLYPOLYLINE16", + "U_EMR_POLYPOLYGON16", + "U_EMR_POLYDRAW16", + "U_EMR_CREATEMONOBRUSH", + "U_EMR_CREATEDIBPATTERNBRUSHPT", + "U_EMR_EXTCREATEPEN", + "U_EMR_POLYTEXTOUTA", + "U_EMR_POLYTEXTOUTW", + "U_EMR_SETICMMODE", + "U_EMR_CREATECOLORSPACE", + "U_EMR_SETCOLORSPACE", + "U_EMR_DELETECOLORSPACE", + "U_EMR_GLSRECORD", + "U_EMR_GLSBOUNDEDRECORD", + "U_EMR_PIXELFORMAT", + "U_EMR_DRAWESCAPE", + "U_EMR_EXTESCAPE", + "U_EMR_UNDEF107", + "U_EMR_SMALLTEXTOUT", + "U_EMR_FORCEUFIMAPPING", + "U_EMR_NAMEDESCAPE", + "U_EMR_COLORCORRECTPALETTE", + "U_EMR_SETICMPROFILEA", + "U_EMR_SETICMPROFILEW", + "U_EMR_ALPHABLEND", + "U_EMR_SETLAYOUT", + "U_EMR_TRANSPARENTBLT", + "U_EMR_UNDEF117", + "U_EMR_GRADIENTFILL", + "U_EMR_SETLINKEDUFIS", + "U_EMR_SETTEXTJUSTIFICATION", + "U_EMR_COLORMATCHTOTARGETW", + "U_EMR_CREATECOLORSPACEW" + }; + return(U_WMR_NAMES[idx]); +} + + + /* ********************************************************************************************** These definitions are for code pieces that are used many times in the following implementation. These definitions are not needed in end user code, so they are here rather than in uemf.h. @@ -72,7 +211,10 @@ memcpy(A + off, E, F);\ ((B *) A)->offBitsSrc = off;\ ((B *) A)->cbBitsSrc = F;\ - if(G - F){ memset(A + off, 0, G - F); }\ + if(G - F){ \ + off += F;\ + memset(A + off, 0, G - F); \ + }\ }\ else {\ ((B *) A)->offBmiSrc = 0;\ @@ -182,6 +324,7 @@ /** \brief Look up the properties (a bit map) of a type of EMR record. + Bits that may be set are defined in "Draw Properties" in uemf.h, they are U_DRAW_NOTEMPTY, etc.. \return bitmap of EMR record properties, or U_EMR_INVALID on error or release of all memory \param type EMR record type. If U_EMR_INVALID release memory. (There is no U_EMR_INVALID EMR record type) @@ -201,129 +344,129 @@ // 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01 // Path properties (U_DRAW_*) TEXT ALTERS ONLYTO VISIBLE // PATH FORCE CLOSED NOTEMPTY - table[ 0] = 0x00; //!< Does not map to any EMR record - table[ 1] = 0x80; //!< U_EMRHEADER 1 0 0 0 0 0 0 0 - table[ 2] = 0x83; //!< U_EMRPOLYBEZIER 1 0 0 0 0 0 1 1 - table[ 3] = 0x87; //!< U_EMRPOLYGON 1 0 0 0 0 1 1 1 - table[ 4] = 0x83; //!< U_EMRPOLYLINE 1 0 0 0 0 0 1 1 - table[ 5] = 0x8B; //!< U_EMRPOLYBEZIERTO 1 0 0 0 1 0 1 1 - table[ 6] = 0x8B; //!< U_EMRPOLYLINETO 1 0 0 0 1 0 1 1 - table[ 7] = 0x83; //!< U_EMRPOLYPOLYLINE 1 0 0 0 0 0 1 1 - table[ 8] = 0x87; //!< U_EMRPOLYPOLYGON 1 0 0 0 0 1 1 1 - table[ 9] = 0xA0; //!< U_EMRSETWINDOWEXTEX 1 0 1 0 0 0 0 0 - table[ 10] = 0xA0; //!< U_EMRSETWINDOWORGEX 1 0 1 0 0 0 0 0 - table[ 11] = 0xA0; //!< U_EMRSETVIEWPORTEXTEX 1 0 1 0 0 0 0 0 - table[ 12] = 0xA0; //!< U_EMRSETVIEWPORTORGEX 1 0 1 0 0 0 0 0 - table[ 13] = 0xA0; //!< U_EMRSETBRUSHORGEX 1 0 1 0 0 0 0 0 - table[ 14] = 0x82; //!< U_EMREOF 1 0 1 0 0 0 0 0 Force out any pending draw - table[ 15] = 0x82; //!< U_EMRSETPIXELV 1 0 0 0 0 0 1 0 - table[ 16] = 0xA0; //!< U_EMRSETMAPPERFLAGS 1 0 1 0 0 0 0 0 - table[ 17] = 0xA0; //!< U_EMRSETMAPMODE 1 0 1 0 0 0 0 0 - table[ 18] = 0x20; //!< U_EMRSETBKMODE 0 0 1 0 0 0 0 0 - table[ 19] = 0xA0; //!< U_EMRSETPOLYFILLMODE 1 0 1 0 0 0 0 0 - table[ 20] = 0xA0; //!< U_EMRSETROP2 1 0 1 0 0 0 0 0 - table[ 21] = 0xA0; //!< U_EMRSETSTRETCHBLTMODE 1 0 1 0 0 0 0 0 - table[ 22] = 0x20; //!< U_EMRSETTEXTALIGN 0 0 1 0 0 0 0 0 - table[ 23] = 0xA0; //!< U_EMRSETCOLORADJUSTMENT 1 0 1 0 0 0 0 0 - table[ 24] = 0x20; //!< U_EMRSETTEXTCOLOR 0 0 1 0 0 0 0 0 - table[ 25] = 0x20; //!< U_EMRSETBKCOLOR 0 0 1 0 0 0 0 0 - table[ 26] = 0xA0; //!< U_EMROFFSETCLIPRGN 1 0 1 0 0 0 0 0 - table[ 27] = 0x89; //!< U_EMRMOVETOEX 1 0 0 0 1 0 0 1 - table[ 28] = 0xA0; //!< U_EMRSETMETARGN 1 0 1 0 0 0 0 0 - table[ 29] = 0xA0; //!< U_EMREXCLUDECLIPRECT 1 0 1 0 0 0 0 0 - table[ 30] = 0xA0; //!< U_EMRINTERSECTCLIPRECT 1 0 1 0 0 0 0 0 - table[ 31] = 0xA0; //!< U_EMRSCALEVIEWPORTEXTEX 1 0 1 0 0 0 0 0 - table[ 32] = 0xA0; //!< U_EMRSCALEWINDOWEXTEX 1 0 1 0 0 0 0 0 - table[ 33] = 0xA0; //!< U_EMRSAVEDC 1 0 1 0 0 0 0 0 - table[ 34] = 0xA0; //!< U_EMRRESTOREDC 1 0 1 0 0 0 0 0 - table[ 35] = 0xA0; //!< U_EMRSETWORLDTRANSFORM 1 0 1 0 0 0 0 0 - table[ 36] = 0xA0; //!< U_EMRMODIFYWORLDTRANSFORM 1 0 1 0 0 0 0 0 - table[ 37] = 0x20; //!< U_EMRSELECTOBJECT 0 0 1 0 0 0 0 0 - table[ 38] = 0x20; //!< U_EMRCREATEPEN 0 0 1 0 0 0 0 0 - table[ 39] = 0x20; //!< U_EMRCREATEBRUSHINDIRECT 0 0 1 0 0 0 0 0 - table[ 40] = 0x20; //!< U_EMRDELETEOBJECT 0 0 1 0 0 0 0 0 - table[ 41] = 0x83; //!< U_EMRANGLEARC 1 0 0 0 0 0 1 1 - table[ 42] = 0x87; //!< U_EMRELLIPSE 1 0 0 0 0 1 1 1 - table[ 43] = 0x87; //!< U_EMRRECTANGLE 1 0 0 0 0 1 1 1 - table[ 44] = 0x87; //!< U_EMRROUNDRECT 1 0 0 0 0 1 1 1 - table[ 45] = 0x83; //!< U_EMRARC 1 0 0 0 0 0 1 1 - table[ 46] = 0x87; //!< U_EMRCHORD 1 0 0 0 0 1 1 1 - table[ 47] = 0x87; //!< U_EMRPIE 1 0 0 0 0 1 1 1 - table[ 48] = 0xA0; //!< U_EMRSELECTPALETTE 1 0 1 0 0 0 0 0 - table[ 49] = 0xA0; //!< U_EMRCREATEPALETTE 1 0 1 0 0 0 0 0 - table[ 50] = 0xA0; //!< U_EMRSETPALETTEENTRIES 1 0 1 0 0 0 0 0 - table[ 51] = 0xA0; //!< U_EMRRESIZEPALETTE 1 0 1 0 0 0 0 0 - table[ 52] = 0xA0; //!< U_EMRREALIZEPALETTE 1 0 1 0 0 0 0 0 - table[ 53] = 0x82; //!< U_EMREXTFLOODFILL 1 0 0 0 0 0 1 0 - table[ 54] = 0x8B; //!< U_EMRLINETO 1 0 0 0 1 0 1 1 - table[ 55] = 0x8B; //!< U_EMRARCTO 1 0 0 0 1 0 1 1 - table[ 56] = 0x83; //!< U_EMRPOLYDRAW 1 0 0 0 0 0 1 1 - table[ 57] = 0xA0; //!< U_EMRSETARCDIRECTION 1 0 1 0 0 0 0 0 - table[ 58] = 0xA0; //!< U_EMRSETMITERLIMIT 1 0 1 0 0 0 0 0 - table[ 59] = 0xE0; //!< U_EMRBEGINPATH 1 1 1 0 0 0 0 0 - table[ 60] = 0x80; //!< U_EMRENDPATH 1 0 0 0 0 0 0 0 - table[ 61] = 0x84; //!< U_EMRCLOSEFIGURE 1 0 0 0 0 1 0 0 - table[ 62] = 0x94; //!< U_EMRFILLPATH 1 0 0 1 0 1 0 0 - table[ 63] = 0x94; //!< U_EMRSTROKEANDFILLPATH 1 0 0 1 0 1 0 0 - table[ 64] = 0x90; //!< U_EMRSTROKEPATH 1 0 0 1 0 0 0 0 - table[ 65] = 0xA0; //!< U_EMRFLATTENPATH 1 0 1 0 0 0 0 0 - table[ 66] = 0xA0; //!< U_EMRWIDENPATH 1 0 1 0 0 0 0 0 - table[ 67] = 0xA0; //!< U_EMRSELECTCLIPPATH 1 0 1 0 0 0 0 0 - table[ 68] = 0xA0; //!< U_EMRABORTPATH 1 0 1 0 0 0 0 0 - table[ 69] = 0xA0; //!< U_EMRUNDEF69 1 0 1 0 0 0 0 0 - table[ 70] = 0x00; //!< U_EMRCOMMENT 0 0 0 0 0 0 0 0 - table[ 71] = 0x82; //!< U_EMRFILLRGN 1 0 0 0 0 0 1 0 - table[ 72] = 0x82; //!< U_EMRFRAMERGN 1 0 0 0 0 0 1 0 - table[ 73] = 0x82; //!< U_EMRINVERTRGN 1 0 0 0 0 0 1 0 - table[ 74] = 0x82; //!< U_EMRPAINTRGN 1 0 0 0 0 0 1 0 - table[ 75] = 0xA0; //!< U_EMREXTSELECTCLIPRGN 1 0 1 0 0 0 0 0 - table[ 76] = 0x82; //!< U_EMRBITBLT 1 0 0 0 0 0 1 0 - table[ 77] = 0x82; //!< U_EMRSTRETCHBLT 1 0 0 0 0 0 1 0 - table[ 78] = 0x82; //!< U_EMRMASKBLT 1 0 0 0 0 0 1 0 - table[ 79] = 0x82; //!< U_EMRPLGBLT 1 0 0 0 0 0 1 0 - table[ 80] = 0xA0; //!< U_EMRSETDIBITSTODEVICE 1 0 1 0 0 0 0 0 - table[ 81] = 0xA0; //!< U_EMRSTRETCHDIBITS 1 0 1 0 0 0 0 0 - table[ 82] = 0x20; //!< U_EMREXTCREATEFONTINDIRECTW 0 0 1 0 0 0 0 0 - table[ 83] = 0x02; //!< U_EMREXTTEXTOUTA 0 0 0 0 0 0 1 0 - table[ 84] = 0x02; //!< U_EMREXTTEXTOUTW 0 0 0 0 0 0 1 0 - table[ 85] = 0x83; //!< U_EMRPOLYBEZIER16 1 0 0 0 0 0 1 1 - table[ 86] = 0x83; //!< U_EMRPOLYGON16 1 0 0 0 0 0 1 1 - table[ 87] = 0x83; //!< U_EMRPOLYLINE16 1 0 0 0 0 0 1 1 - table[ 88] = 0x8B; //!< U_EMRPOLYBEZIERTO16 1 0 0 0 1 0 1 1 - table[ 89] = 0x8B; //!< U_EMRPOLYLINETO16 1 0 0 0 1 0 1 1 - table[ 90] = 0x83; //!< U_EMRPOLYPOLYLINE16 1 0 0 0 0 0 1 1 - table[ 91] = 0x87; //!< U_EMRPOLYPOLYGON16 1 0 0 0 0 1 1 1 - table[ 92] = 0x83; //!< U_EMRPOLYDRAW16 1 0 0 0 0 0 1 1 - table[ 93] = 0x80; //!< U_EMRCREATEMONOBRUSH 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions - table[ 94] = 0x80; //!< U_EMRCREATEDIBPATTERNBRUSHPT 1 0 0 0 0 0 0 0 " - table[ 95] = 0x00; //!< U_EMREXTCREATEPEN 0 0 0 0 0 0 0 0 " - table[ 96] = 0x02; //!< U_EMRPOLYTEXTOUTA 0 0 0 0 0 0 1 0 - table[ 97] = 0x02; //!< U_EMRPOLYTEXTOUTW 0 0 0 0 0 0 1 0 - table[ 98] = 0xA0; //!< U_EMRSETICMMODE 1 0 1 0 0 0 0 0 - table[ 99] = 0xA0; //!< U_EMRCREATECOLORSPACE 1 0 1 0 0 0 0 0 - table[100] = 0xA0; //!< U_EMRSETCOLORSPACE 1 0 1 0 0 0 0 0 - table[101] = 0xA0; //!< U_EMRDELETECOLORSPACE 1 0 1 0 0 0 0 0 - table[102] = 0xA0; //!< U_EMRGLSRECORD 1 0 1 0 0 0 0 0 - table[103] = 0xA0; //!< U_EMRGLSBOUNDEDRECORD 1 0 1 0 0 0 0 0 - table[104] = 0xA0; //!< U_EMRPIXELFORMAT 1 0 1 0 0 0 0 0 - table[105] = 0xA0; //!< U_EMRDRAWESCAPE 1 0 1 0 0 0 0 0 - table[106] = 0xA0; //!< U_EMREXTESCAPE 1 0 1 0 0 0 0 0 - table[107] = 0xA0; //!< U_EMRUNDEF107 1 0 1 0 0 0 0 0 - table[108] = 0x02; //!< U_EMRSMALLTEXTOUT 0 0 0 0 0 0 1 0 - table[109] = 0xA0; //!< U_EMRFORCEUFIMAPPING 1 0 1 0 0 0 0 0 - table[110] = 0xA0; //!< U_EMRNAMEDESCAPE 1 0 1 0 0 0 0 0 - table[111] = 0xA0; //!< U_EMRCOLORCORRECTPALETTE 1 0 1 0 0 0 0 0 - table[112] = 0xA0; //!< U_EMRSETICMPROFILEA 1 0 1 0 0 0 0 0 - table[113] = 0xA0; //!< U_EMRSETICMPROFILEW 1 0 1 0 0 0 0 0 - table[114] = 0x82; //!< U_EMRALPHABLEND 1 0 0 0 0 0 1 0 - table[115] = 0xA0; //!< U_EMRSETLAYOUT 1 0 1 0 0 0 0 0 - table[116] = 0x82; //!< U_EMRTRANSPARENTBLT 1 0 0 0 0 0 1 0 - table[117] = 0xA0; //!< U_EMRUNDEF117 1 0 1 0 0 0 0 0 - table[118] = 0x82; //!< U_EMRGRADIENTFILL 1 0 0 0 0 0 1 0 - table[119] = 0xA0; //!< U_EMRSETLINKEDUFIS 1 0 1 0 0 0 0 0 - table[120] = 0x20; //!< U_EMRSETTEXTJUSTIFICATION 0 0 1 0 0 0 0 0 - table[121] = 0xA0; //!< U_EMRCOLORMATCHTOTARGETW 1 0 1 0 0 0 0 0 - table[122] = 0xA0; //!< U_EMRCREATECOLORSPACEW 1 0 1 0 0 0 0 0 + table[ 0] = 0x00; // Does not map to any EMR record + table[ 1] = 0x80; // U_EMRHEADER 1 0 0 0 0 0 0 0 + table[ 2] = 0x83; // U_EMRPOLYBEZIER 1 0 0 0 0 0 1 1 + table[ 3] = 0x87; // U_EMRPOLYGON 1 0 0 0 0 1 1 1 + table[ 4] = 0x83; // U_EMRPOLYLINE 1 0 0 0 0 0 1 1 + table[ 5] = 0x8B; // U_EMRPOLYBEZIERTO 1 0 0 0 1 0 1 1 + table[ 6] = 0x8B; // U_EMRPOLYLINETO 1 0 0 0 1 0 1 1 + table[ 7] = 0x83; // U_EMRPOLYPOLYLINE 1 0 0 0 0 0 1 1 + table[ 8] = 0x87; // U_EMRPOLYPOLYGON 1 0 0 0 0 1 1 1 + table[ 9] = 0xA0; // U_EMRSETWINDOWEXTEX 1 0 1 0 0 0 0 0 + table[ 10] = 0xA0; // U_EMRSETWINDOWORGEX 1 0 1 0 0 0 0 0 + table[ 11] = 0xA0; // U_EMRSETVIEWPORTEXTEX 1 0 1 0 0 0 0 0 + table[ 12] = 0xA0; // U_EMRSETVIEWPORTORGEX 1 0 1 0 0 0 0 0 + table[ 13] = 0xA0; // U_EMRSETBRUSHORGEX 1 0 1 0 0 0 0 0 + table[ 14] = 0x82; // U_EMREOF 1 0 1 0 0 0 0 0 Force out any pending draw + table[ 15] = 0x82; // U_EMRSETPIXELV 1 0 0 0 0 0 1 0 + table[ 16] = 0xA0; // U_EMRSETMAPPERFLAGS 1 0 1 0 0 0 0 0 + table[ 17] = 0xA0; // U_EMRSETMAPMODE 1 0 1 0 0 0 0 0 + table[ 18] = 0x20; // U_EMRSETBKMODE 0 0 1 0 0 0 0 0 + table[ 19] = 0xA0; // U_EMRSETPOLYFILLMODE 1 0 1 0 0 0 0 0 + table[ 20] = 0xA0; // U_EMRSETROP2 1 0 1 0 0 0 0 0 + table[ 21] = 0xA0; // U_EMRSETSTRETCHBLTMODE 1 0 1 0 0 0 0 0 + table[ 22] = 0x20; // U_EMRSETTEXTALIGN 0 0 1 0 0 0 0 0 + table[ 23] = 0xA0; // U_EMRSETCOLORADJUSTMENT 1 0 1 0 0 0 0 0 + table[ 24] = 0x20; // U_EMRSETTEXTCOLOR 0 0 1 0 0 0 0 0 + table[ 25] = 0x20; // U_EMRSETBKCOLOR 0 0 1 0 0 0 0 0 + table[ 26] = 0xA0; // U_EMROFFSETCLIPRGN 1 0 1 0 0 0 0 0 + table[ 27] = 0x89; // U_EMRMOVETOEX 1 0 0 0 1 0 0 1 + table[ 28] = 0xA0; // U_EMRSETMETARGN 1 0 1 0 0 0 0 0 + table[ 29] = 0xA0; // U_EMREXCLUDECLIPRECT 1 0 1 0 0 0 0 0 + table[ 30] = 0xA0; // U_EMRINTERSECTCLIPRECT 1 0 1 0 0 0 0 0 + table[ 31] = 0xA0; // U_EMRSCALEVIEWPORTEXTEX 1 0 1 0 0 0 0 0 + table[ 32] = 0xA0; // U_EMRSCALEWINDOWEXTEX 1 0 1 0 0 0 0 0 + table[ 33] = 0xA0; // U_EMRSAVEDC 1 0 1 0 0 0 0 0 + table[ 34] = 0xA0; // U_EMRRESTOREDC 1 0 1 0 0 0 0 0 + table[ 35] = 0xA0; // U_EMRSETWORLDTRANSFORM 1 0 1 0 0 0 0 0 + table[ 36] = 0xA0; // U_EMRMODIFYWORLDTRANSFORM 1 0 1 0 0 0 0 0 + table[ 37] = 0x20; // U_EMRSELECTOBJECT 0 0 1 0 0 0 0 0 + table[ 38] = 0x20; // U_EMRCREATEPEN 0 0 1 0 0 0 0 0 + table[ 39] = 0x20; // U_EMRCREATEBRUSHINDIRECT 0 0 1 0 0 0 0 0 + table[ 40] = 0x20; // U_EMRDELETEOBJECT 0 0 1 0 0 0 0 0 + table[ 41] = 0x83; // U_EMRANGLEARC 1 0 0 0 0 0 1 1 + table[ 42] = 0x87; // U_EMRELLIPSE 1 0 0 0 0 1 1 1 + table[ 43] = 0x87; // U_EMRRECTANGLE 1 0 0 0 0 1 1 1 + table[ 44] = 0x87; // U_EMRROUNDRECT 1 0 0 0 0 1 1 1 + table[ 45] = 0x83; // U_EMRARC 1 0 0 0 0 0 1 1 + table[ 46] = 0x87; // U_EMRCHORD 1 0 0 0 0 1 1 1 + table[ 47] = 0x87; // U_EMRPIE 1 0 0 0 0 1 1 1 + table[ 48] = 0xA0; // U_EMRSELECTPALETTE 1 0 1 0 0 0 0 0 + table[ 49] = 0xA0; // U_EMRCREATEPALETTE 1 0 1 0 0 0 0 0 + table[ 50] = 0xA0; // U_EMRSETPALETTEENTRIES 1 0 1 0 0 0 0 0 + table[ 51] = 0xA0; // U_EMRRESIZEPALETTE 1 0 1 0 0 0 0 0 + table[ 52] = 0xA0; // U_EMRREALIZEPALETTE 1 0 1 0 0 0 0 0 + table[ 53] = 0x82; // U_EMREXTFLOODFILL 1 0 0 0 0 0 1 0 + table[ 54] = 0x8B; // U_EMRLINETO 1 0 0 0 1 0 1 1 + table[ 55] = 0x8B; // U_EMRARCTO 1 0 0 0 1 0 1 1 + table[ 56] = 0x83; // U_EMRPOLYDRAW 1 0 0 0 0 0 1 1 + table[ 57] = 0xA0; // U_EMRSETARCDIRECTION 1 0 1 0 0 0 0 0 + table[ 58] = 0xA0; // U_EMRSETMITERLIMIT 1 0 1 0 0 0 0 0 + table[ 59] = 0xE0; // U_EMRBEGINPATH 1 1 1 0 0 0 0 0 + table[ 60] = 0x80; // U_EMRENDPATH 1 0 0 0 0 0 0 0 + table[ 61] = 0x84; // U_EMRCLOSEFIGURE 1 0 0 0 0 1 0 0 + table[ 62] = 0x94; // U_EMRFILLPATH 1 0 0 1 0 1 0 0 + table[ 63] = 0x94; // U_EMRSTROKEANDFILLPATH 1 0 0 1 0 1 0 0 + table[ 64] = 0x90; // U_EMRSTROKEPATH 1 0 0 1 0 0 0 0 + table[ 65] = 0xA0; // U_EMRFLATTENPATH 1 0 1 0 0 0 0 0 + table[ 66] = 0xA0; // U_EMRWIDENPATH 1 0 1 0 0 0 0 0 + table[ 67] = 0xA0; // U_EMRSELECTCLIPPATH 1 0 1 0 0 0 0 0 + table[ 68] = 0xA0; // U_EMRABORTPATH 1 0 1 0 0 0 0 0 + table[ 69] = 0xA0; // U_EMRUNDEF69 1 0 1 0 0 0 0 0 + table[ 70] = 0x00; // U_EMRCOMMENT 0 0 0 0 0 0 0 0 + table[ 71] = 0x82; // U_EMRFILLRGN 1 0 0 0 0 0 1 0 + table[ 72] = 0x82; // U_EMRFRAMERGN 1 0 0 0 0 0 1 0 + table[ 73] = 0x82; // U_EMRINVERTRGN 1 0 0 0 0 0 1 0 + table[ 74] = 0x82; // U_EMRPAINTRGN 1 0 0 0 0 0 1 0 + table[ 75] = 0xA0; // U_EMREXTSELECTCLIPRGN 1 0 1 0 0 0 0 0 + table[ 76] = 0x82; // U_EMRBITBLT 1 0 0 0 0 0 1 0 + table[ 77] = 0x82; // U_EMRSTRETCHBLT 1 0 0 0 0 0 1 0 + table[ 78] = 0x82; // U_EMRMASKBLT 1 0 0 0 0 0 1 0 + table[ 79] = 0x82; // U_EMRPLGBLT 1 0 0 0 0 0 1 0 + table[ 80] = 0xA0; // U_EMRSETDIBITSTODEVICE 1 0 1 0 0 0 0 0 + table[ 81] = 0xA0; // U_EMRSTRETCHDIBITS 1 0 1 0 0 0 0 0 + table[ 82] = 0x20; // U_EMREXTCREATEFONTINDIRECTW 0 0 1 0 0 0 0 0 + table[ 83] = 0x02; // U_EMREXTTEXTOUTA 0 0 0 0 0 0 1 0 + table[ 84] = 0x02; // U_EMREXTTEXTOUTW 0 0 0 0 0 0 1 0 + table[ 85] = 0x83; // U_EMRPOLYBEZIER16 1 0 0 0 0 0 1 1 + table[ 86] = 0x83; // U_EMRPOLYGON16 1 0 0 0 0 0 1 1 + table[ 87] = 0x83; // U_EMRPOLYLINE16 1 0 0 0 0 0 1 1 + table[ 88] = 0x8B; // U_EMRPOLYBEZIERTO16 1 0 0 0 1 0 1 1 + table[ 89] = 0x8B; // U_EMRPOLYLINETO16 1 0 0 0 1 0 1 1 + table[ 90] = 0x83; // U_EMRPOLYPOLYLINE16 1 0 0 0 0 0 1 1 + table[ 91] = 0x87; // U_EMRPOLYPOLYGON16 1 0 0 0 0 1 1 1 + table[ 92] = 0x83; // U_EMRPOLYDRAW16 1 0 0 0 0 0 1 1 + table[ 93] = 0x80; // U_EMRCREATEMONOBRUSH 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions + table[ 94] = 0x80; // U_EMRCREATEDIBPATTERNBRUSHPT 1 0 0 0 0 0 0 0 " + table[ 95] = 0x00; // U_EMREXTCREATEPEN 0 0 0 0 0 0 0 0 " + table[ 96] = 0x02; // U_EMRPOLYTEXTOUTA 0 0 0 0 0 0 1 0 + table[ 97] = 0x02; // U_EMRPOLYTEXTOUTW 0 0 0 0 0 0 1 0 + table[ 98] = 0xA0; // U_EMRSETICMMODE 1 0 1 0 0 0 0 0 + table[ 99] = 0xA0; // U_EMRCREATECOLORSPACE 1 0 1 0 0 0 0 0 + table[100] = 0xA0; // U_EMRSETCOLORSPACE 1 0 1 0 0 0 0 0 + table[101] = 0xA0; // U_EMRDELETECOLORSPACE 1 0 1 0 0 0 0 0 + table[102] = 0xA0; // U_EMRGLSRECORD 1 0 1 0 0 0 0 0 + table[103] = 0xA0; // U_EMRGLSBOUNDEDRECORD 1 0 1 0 0 0 0 0 + table[104] = 0xA0; // U_EMRPIXELFORMAT 1 0 1 0 0 0 0 0 + table[105] = 0xA0; // U_EMRDRAWESCAPE 1 0 1 0 0 0 0 0 + table[106] = 0xA0; // U_EMREXTESCAPE 1 0 1 0 0 0 0 0 + table[107] = 0xA0; // U_EMRUNDEF107 1 0 1 0 0 0 0 0 + table[108] = 0x02; // U_EMRSMALLTEXTOUT 0 0 0 0 0 0 1 0 + table[109] = 0xA0; // U_EMRFORCEUFIMAPPING 1 0 1 0 0 0 0 0 + table[110] = 0xA0; // U_EMRNAMEDESCAPE 1 0 1 0 0 0 0 0 + table[111] = 0xA0; // U_EMRCOLORCORRECTPALETTE 1 0 1 0 0 0 0 0 + table[112] = 0xA0; // U_EMRSETICMPROFILEA 1 0 1 0 0 0 0 0 + table[113] = 0xA0; // U_EMRSETICMPROFILEW 1 0 1 0 0 0 0 0 + table[114] = 0x82; // U_EMRALPHABLEND 1 0 0 0 0 0 1 0 + table[115] = 0xA0; // U_EMRSETLAYOUT 1 0 1 0 0 0 0 0 + table[116] = 0x82; // U_EMRTRANSPARENTBLT 1 0 0 0 0 0 1 0 + table[117] = 0xA0; // U_EMRUNDEF117 1 0 1 0 0 0 0 0 + table[118] = 0x82; // U_EMRGRADIENTFILL 1 0 0 0 0 0 1 0 + table[119] = 0xA0; // U_EMRSETLINKEDUFIS 1 0 1 0 0 0 0 0 + table[120] = 0x20; // U_EMRSETTEXTJUSTIFICATION 0 0 1 0 0 0 0 0 + table[121] = 0xA0; // U_EMRCOLORMATCHTOTARGETW 1 0 1 0 0 0 0 0 + table[122] = 0xA0; // U_EMRCREATECOLORSPACEW 1 0 1 0 0 0 0 0 } result = table[type]; } @@ -622,13 +765,13 @@ /** \brief Get the DIB parameters from the BMI of the record for use by DBI_to_RGBA() - \return 0 on success, other values on errors. + \return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid. \param pEmr pointer to EMR record that has a U_BITMAPINFO and bitmap \param offBitsSrc Offset to the bitmap \param offBmiSrc Offset to the U_BITMAPINFO \param px pointer to DIB pixel array in pEmr \param ct pointer to DIB color table in pEmr - \param numCt DIB color table number of entries + \param numCt DIB color table number of entries, for PNG or JPG returns the number of bytes in the image \param width Width of pixel array \param height Height of pixel array (always returned as a positive number) \param colortype DIB BitCount Enumeration @@ -646,11 +789,12 @@ uint32_t *colortype, uint32_t *invert ){ + uint32_t bic; PU_BITMAPINFO Bmi = (PU_BITMAPINFO)((char *)pEmr + offBmiSrc); - if(Bmi->bmiHeader.biCompression != U_BI_RGB)return(1); + /* if biCompression is not U_BI_RGB some or all of the following might not hold real values */ + bic = Bmi->bmiHeader.biCompression; *width = Bmi->bmiHeader.biWidth; *colortype = Bmi->bmiHeader.biBitCount; - *numCt = Bmi->bmiHeader.biClrUsed; if(Bmi->bmiHeader.biHeight < 0){ *height = -Bmi->bmiHeader.biHeight; *invert = 1; @@ -659,11 +803,17 @@ *height = Bmi->bmiHeader.biHeight; *invert = 0; } - if(numCt){ - *ct = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER)); + if(bic == U_BI_RGB){ + *numCt = Bmi->bmiHeader.biClrUsed; + if(numCt){ + *ct = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER)); + } + } + else { + *numCt = Bmi->bmiHeader.biSizeImage; } *px = (char *)((char *)pEmr + offBitsSrc); - return(0); + return(bic); } /** @@ -831,8 +981,8 @@ \param h Height of pixel array in the record \param sl start left position in the pixel array in the record to start extracting \param st start top position in the pixel array in the record to start extracting - \param ew Width of pixel array to extract - \param eh Height of pixel array to extract + \param eew Width of pixel array to extract + \param eeh Height of pixel array to extract */ char *RGBA_to_RGBA( char *rgba_px, @@ -1028,12 +1178,13 @@ #endif return(fp); } + /** \brief Retrieve contents of an EMF file by name. \return 0 on success, >=1 on failure \param filename Name of file to open, including the path \param contents Contents of the file. Buffer must be free()'d by caller. - \param Number of bytes in Contents + \param length Number of bytes in Contents */ int emf_readdata( const char *filename, @@ -1149,10 +1300,27 @@ ehtl->peak = 1; ehtl->sptr = 1; ehtl->top = 0; + ehtl->mftype = U_MFT_EMF; // default and for backwards compatibility, use htable_mftype to change for WMF. *eht = ehtl; return(0); } +/** + \brief Set the metafile type on a handle table. + The type may be used to block accidental cross calls WMF->EMF and so forth. + \return 0 for success, -1 for failure. + \param type Metafile Enumeration + \param eht EMF handle table +*/ +int htable_mftype( + uint32_t type, + EMFHANDLES *eht + ){ + int ret=0; + if((type >= U_MFT_MIN) && (type <= U_MFT_MAX)){ eht->mftype = type; } + else { ret = -1; } + return(ret); +} /** \brief Delete an entry from the handle table. Move it back onto the stack. The specified slot is filled with a 0. @@ -1491,9 +1659,9 @@ \brief Construct a U_XFORM structure. \return U_XFORM structure \param scale Scale factor - \param axesRatio Ratio of minor axis/major axis + \param ratio Ratio of minor axis/major axis \param rot Rotation angle in degrees, positive is counter clockwise from the x axis. - \param axisRot Angle in degrees defining the major axis before rotation, positive is counter clockwise from the x axis. + \param axisrot Angle in degrees defining the major axis before rotation, positive is counter clockwise from the x axis. \param eDx Translation element \param eDy Translation element @@ -2181,6 +2349,7 @@ uint32_t *ihObject, EMFHANDLES *eht ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function uint32_t saveObject=*ihObject; if(htable_delete(ihObject,eht))return(NULL); // invalid handle or other problem, cannot be deleted return(U_EMRDELETEOBJECT_set(saveObject)); @@ -2197,6 +2366,7 @@ uint32_t ihObject, EMFHANDLES *eht ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(!(U_STOCK_OBJECT & ihObject)){ // not a stock object, those go straight through if(eht->top < ihObject)return(NULL); // handle this high is not in the table if(!eht->table[ihObject])return(NULL); // handle is not in the table, so not active, so cannot be selected @@ -2223,6 +2393,7 @@ char *Px, PU_EXTLOGPEN elp ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihPen, eht))return(NULL); return(U_EMREXTCREATEPEN_set(*ihPen, Bmi, cbPx, Px, elp )); } @@ -2240,6 +2411,7 @@ EMFHANDLES *eht, U_LOGPEN lopn ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihPen, eht))return(NULL); return(U_EMRCREATEPEN_set(*ihPen, lopn)); } @@ -2257,6 +2429,7 @@ EMFHANDLES *eht, U_LOGBRUSH lb ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihBrush, eht))return(NULL); return(U_EMRCREATEBRUSHINDIRECT_set(*ihBrush, lb)); } @@ -2281,6 +2454,7 @@ const char *Px ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihBrush, eht))return(NULL); return(U_EMRCREATEDIBPATTERNBRUSHPT_set(*ihBrush, iUsage, Bmi, cbPx, Px)); } @@ -2305,6 +2479,7 @@ const char *Px ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihBrush, eht))return(NULL); return(U_EMRCREATEMONOBRUSH_set(*ihBrush, iUsage, Bmi, cbPx, Px)); } @@ -2323,6 +2498,7 @@ EMFHANDLES *eht, U_LOGCOLORSPACEA lcs ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihCS, eht))return(NULL); return(U_EMRCREATECOLORSPACE_set(*ihCS,lcs)); } @@ -2346,6 +2522,7 @@ U_CBDATA cbData, uint8_t *Data ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihCS, eht))return(NULL); return(U_EMRCREATECOLORSPACEW_set(*ihCS, lcs, dwFlags, cbData, Data)); } @@ -2365,6 +2542,7 @@ const char *elf, const char *elfw ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihFont, eht))return(NULL); return(U_EMREXTCREATEFONTINDIRECTW_set(*ihFont, elf, elfw)); } @@ -2382,6 +2560,7 @@ EMFHANDLES *eht, U_LOGPALETTE lgpl ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihPal, eht))return(NULL); return(U_EMRCREATEPALETTE_set(*ihPal, lgpl)); } @@ -2403,6 +2582,7 @@ const U_NUM_LOGPLTNTRY cEntries, const PU_LOGPLTNTRY aPalEntries ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihPal, eht))return(NULL); return(U_EMRSETPALETTEENTRIES_set(*ihPal, iStart, cEntries, aPalEntries)); } @@ -2422,6 +2602,7 @@ const U_RECTL rclBounds, const PU_RGNDATA RgnData ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihBrush, eht))return(NULL); return(U_EMRFILLRGN_set(rclBounds, *ihBrush, RgnData)); } @@ -2443,6 +2624,7 @@ const U_SIZEL szlStroke, const PU_RGNDATA RgnData ){ + if(U_MFT_MISMATCH(eht,U_MFT_EMF))return(NULL); // something not EMF calling EMF function if(htable_insert(ihBrush, eht))return(NULL); return(U_EMRFRAMERGN_set(rclBounds, *ihBrush, szlStroke, RgnData)); } @@ -3388,7 +3570,7 @@ char *U_EMROFFSETCLIPRGN_set( const U_POINTL ptl ){ - return(U_EMR_CORE7(U_EMR_OFFSETCLIPRGN, (U_PAIR) ptl)); + return(U_EMR_CORE7(U_EMR_OFFSETCLIPRGN, ptl)); } // U_EMRMOVETOEX_set 27 @@ -3400,7 +3582,7 @@ char *U_EMRMOVETOEX_set( const U_POINTL ptl ){ - return(U_EMR_CORE7(U_EMR_MOVETOEX, (U_PAIR) ptl)); + return(U_EMR_CORE7(U_EMR_MOVETOEX, ptl)); } // U_EMRSETMETARGN_set 28 @@ -3899,7 +4081,7 @@ char *U_EMRLINETO_set( const U_POINTL ptl ){ - return(U_EMR_CORE7(U_EMR_LINETO, (U_PAIR) ptl)); + return(U_EMR_CORE7(U_EMR_LINETO, ptl)); } // U_EMRARCTO_set 55 === modified file 'src/extension/internal/uemf.h' --- src/extension/internal/uemf.h 2012-12-13 04:10:54 +0000 +++ src/extension/internal/uemf.h 2013-01-24 22:25:55 +0000 @@ -8,16 +8,16 @@ If the direct link fails the document may be found by searching for: "[MS-EMF]: Enhanced Metafile Format" - + */ /* File: uemf.h -Version: 0.0.10 -Date: 04-DEC-2012 +Version: 0.0.12 +Date: 17-JAN-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifndef _UEMF_ @@ -49,7 +49,16 @@ // *********************************************************************************** // Value enumerations and other predefined constants, alphabetical order by group - +/** \defgroup U_MF_Qualifiers Metafile Enumeration + For EMFHANDLES mftype field + @{ +*/ +#define U_MFT_WMF 1 //!< 16 bit windows metafile +#define U_MFT_EMF 2 //!< 32 bit enhanced windows metafile +#define U_MFT_EMFP 3 //!< EMF plus (reserved, not implemented yet) +#define U_MFT_MAX 3 +#define U_MFT_MIN 1 +/** @} */ /** \defgroup Font_struct_widths Font name and style widths in characters For U_LOGFONT and U_LOGFONT_PANOSE, @@ -193,18 +202,19 @@ #define U_EMR_INVALID 0xFFFFFFFF //!< Not any valid U_EMF_ value /** @} */ -/** \defgroup U_DRAW_PROPERTIES - Used in draw_properties(). These are the bit definitions. +/** \defgroup U_DRAW_PROPERTIES draw properties + Used in emr_properties() and wmr_properties. These are the bit definitions. @{ */ -#define U_DRAW_NOTEMPTY 0x01 //!< Path has at least a MOVETO in it -#define U_DRAW_VISIBLE 0x02 //!< Path has at least a LINE in it -#define U_DRAW_CLOSED 0x04 //!< Path has been closed -#define U_DRAW_ONLYTO 0x08 //!< Path so far contains only *TO operations -#define U_DRAW_FORCE 0x10 //!< Path MUST be drawn -#define U_DRAW_ALTERS 0x20 //!< Alters draw parameters (pen, brush, coordinates...) -#define U_DRAW_PATH 0x40 //!< An explicit path is being used (with a BEGIN and END) -#define U_DRAW_TEXT 0x80 //!< Current record forces all pending text to be drawn first. +#define U_DRAW_NOTEMPTY 0x001 //!< Path has at least a MOVETO in it +#define U_DRAW_VISIBLE 0x002 //!< Path has at least a LINE in it +#define U_DRAW_CLOSED 0x004 //!< Path has been closed +#define U_DRAW_ONLYTO 0x008 //!< Path so far contains only *TO operations +#define U_DRAW_FORCE 0x010 //!< Path MUST be drawn +#define U_DRAW_ALTERS 0x020 //!< Alters draw parameters (pen, brush, coordinates...) +#define U_DRAW_PATH 0x040 //!< An explicit path is being used (with a BEGIN and END) +#define U_DRAW_TEXT 0x080 //!< Current record forces all pending text to be drawn first. +#define U_DRAW_OBJECT 0x100 //!< Creates an Object (only used in WMF) /** @} */ /** \defgroup U_EMRSETARCDIRECTION_Qualifiers ArcDirection Enumeration @@ -272,7 +282,7 @@ #define U_CA_LOG_FILTER 0x0002 /** @} */ -/** \defgroup U_EMRCOLORMATCHTOTARGETW_dwAction_Qualifiers ColorMatchToTarget Enumeration +/** \defgroup U_EMRCOLORMATCHTOTARGETW_dwFlags_Qualifiers ColorMatchToTarget Enumeration For U_EMRCOLORMATCHTOTARGETW dwFlags field @{ */ @@ -311,7 +321,7 @@ #define U_DIB_PAL_COLORS 1 /** @} */ -/** \defgroup U_EMRCOMMENT_* cIdent Qualifiers +/** \defgroup U_EMRCOMMENT_TYPES Comment record types For U_EMRCOMMENT_* cIdent fields @{ */ @@ -321,8 +331,8 @@ #define U_EMR_COMMENT_EMFPLUSRECORD 0x2B464D45 /** @} */ -/** \defgroup U_EMR_COMMENT_PUBLIC, AKA EMRComment Enumeration - For U_EMRCOMMENT_PUBLI pcIdent fields +/** \defgroup U_EMR_COMMENT_PUBLIC EMRComment Enumeration + For U_EMRCOMMENT_PUBLIC pcIdent fields @{ */ #define U_EMR_COMMENT_WINDOWS_METAFILE 0x80000001 @@ -366,8 +376,8 @@ For U_EMREXTFLOODFILL iMode field @{ */ -#define U_FLOODFILLBORDER 0x00000000 -#define U_FLOODFILLSURFACE 0x00000000 +#define U_FLOODFILLBORDER 0x00000000 /* Color specified must be the same as the border - brush fill stops at this color */ +#define U_FLOODFILLSURFACE 0x00000001 /* Color specified must be different from the border - brush fills only this color */ /** @} */ /** \defgroup U_DESIGNVECTOR_Signature_Qualifiers Signature Enumeration @@ -1100,10 +1110,10 @@ #define U_BGRA(r,g,b,a) (U_RGBQUAD){b,g,r,a} //!< Set any BGRA color with an {r,g,b,a} quad #define U_WHITE U_BGR(255,255,255) //!< Set BGR white. #define U_BLACK U_BGR(0,0,0) //!< Set BGR black. -#define U_BGRAGetR(rgb) ((U_RGBQUAD)rgb).Red //!< Color BGR Get Red Macro. -#define U_BGRAGetG(rgb) ((U_RGBQUAD)rgb).Green //!< Color BGR Get Green Macro. -#define U_BGRAGetB(rgb) ((U_RGBQUAD)rgb).Blue //!< Color BGR Get Blue Macro. -#define U_BGRAGetA(rgb) ((U_RGBQUAD)rgb).Reserved //!< Color BGR Get A/reserved Macro. +#define U_BGRAGetR(rgb) (rgb.Red ) //!< Color BGR Get Red Macro. +#define U_BGRAGetG(rgb) (rgb.Green ) //!< Color BGR Get Green Macro. +#define U_BGRAGetB(rgb) (rgb.Blue ) //!< Color BGR Get Blue Macro. +#define U_BGRAGetA(rgb) (rgb.Reserved) //!< Color BGR Get A/reserved Macro. #define U_PALETTERGB(r,g,b) U_RGB(r,g,b,0x02)) //!< Set any Palette RGB color. #define U_PALETTEINDEX(i) ((U_COLORREF)(0x01000000 | (uint16_t)(i)))\ @@ -1147,8 +1157,11 @@ #define U_EMRTYPE(A) (((PU_EMR)A)->iType) //!< Get iType from U_EMR* record #define U_EMRSIZE(A) (((PU_EMR)A)->nSize) //!< Get nSize from U_EMR* record -// Utility macro +// Utility macros #define UP4(A) (4 * ((A + 3 ) / 4)) //!< Round up to nearest multiple of 4 + +#define U_MFT_MISMATCH(A,B) (A->mftype != B) //!< A is [EW]MFHANDLES and B is Metafile enumeration + /** @} */ typedef float U_FLOAT; @@ -1699,88 +1712,6 @@ uint32_t biClrImportant; //!< Number of bmciColors needed (0 means all). } U_BITMAPINFOHEADER, *PU_BITMAPINFOHEADER; -#if 0 -// Do EMF files ever use any of these??? - -// Microsoft name: BITMAPV4HEADER Object -typedef struct { - uint32_t bV4Size; - int32_t bV4Width; - int32_t bV4Height; - uint16_t bV4Planes; - uint16_t bV4BitCount; - uint32_t bV4Compression; - uint32_t bV4SizeImage; - int32_t bV4XPelsPerMeter; - int32_t bV4YPelsPerMeter; - uint32_t bV4ClrUsed; - uint32_t bV4ClrImportant; - uint32_t bV4RedMask; - uint32_t bV4GreenMask; - uint32_t bV4BlueMask; - uint32_t bV4AlphaMask; - uint32_t bV4CSType; - U_CIEXYZTRIPLE bV4EndPoints; - uint32_t bV4GammaRed; - uint32_t bV4GammaGreen; - uint32_t bV4GammaBlue; -} U_BITMAPV4HEADER, *PU_BITMAPV4HEADER; //!< For ? - -// Microsoft name: BITMAPV5HEADER Object -typedef struct { - uint32_t bV5Size; - int32_t bV5Width; - int32_t bV5Height; - uint16_t bV5Planes; - uint16_t bV5BitCount; - uint32_t bV5Compression; - uint32_t bV5SizeImage; - int32_t bV5XPelsPerMeter; - int32_t bV5YPelsPerMeter; - uint32_t bV5ClrUsed; - uint32_t bV5ClrImportant; - uint32_t bV5RedMask; - uint32_t bV5GreenMask; - uint32_t bV5BlueMask; - uint32_t bV5AlphaMask; - uint32_t bV5CSType; - U_CIEXYZTRIPLE bV5Endpoints; - uint32_t bV5GammaRed; - uint32_t bV5GammaGreen; - uint32_t bV5GammaBlue; - uint32_t bV5Intent; - uint32_t bV5ProfileData; - uint32_t bV5ProfileSize; - uint32_t bV5Reserved; -} U_BITMAPV5HEADER, *PU_BITMAPV5HEADER; //!< For ? - -// Microsoft name: BITMAPCOREHEADER Object -typedef struct { - uint32_t bcSize; //!< Structure size in bytes - uint16_t bcWidth; //!< Bitmap width in pixels - uint16_t bcHeight; //!< Bitmap height in pixels - uint16_t bcPlanes; //!< Planes (must be 1) - uint16_t bcBitCount; //!< BitCount Enumeration -} U_BITMAPCOREHEADER, *PU_BITMAPCOREHEADER; //!< For U_BITMAPCOREINFO - -// Microsoft name: BITMAPCOREINFO Object -// Description of a simple Device Independent Bitmap (DIB) - no compression or color maps -typedef struct { - U_BITMAPCOREHEADER bmciHeader; //!< Geometry and pixel properties - U_RGBTRIPLE bmciColors[1]; //!< Color table -} U_BITMAPCOREINFO, *PU_BITMAPCOREINFO; //!< For ? - -// Microsoft name: RGBTRIPLE Object -// NOTE that the color order is BGR, even though the name is RGB! -typedef struct { - uint8_t rgbtBlue; //!< Blue color (0-255) - uint8_t rgbtGreen; //!< Green color (0-255) - uint8_t rgbtRed; //!< Red color (0-255) -} U_RGBTRIPLE, *PU_RGBTRIPLE; //!< For U_BITMAPCOREINFO bmciColors field - - -#endif // elements possibly never used by an EMF file - /** \brief For U_EMR_* OffBmi* fields Description of a Bitmap which in some cases is a Device Independent Bitmap (DIB) @@ -2657,16 +2588,17 @@ uint32_t sptr; //!< Pointer to next available handle in the stack uint32_t top; //!< Highest slot occupied (currently) uint32_t peak; //!< Highest slot occupied (ever) + uint32_t mftype; //!< Metafile type, see Metafile Enumeration (used to block erroneous calls, wmf=>emf, for instance) } EMFHANDLES; /** 2 x 2 matrix, used by xform_alt_set() function. */ typedef struct { - double M11; - double M12; - double M21; - double M22; + double M11; //!< Matrix element 1,1 + double M12; //!< Matrix element 1,2 + double M21; //!< Matrix element 2,1 + double M22; //!< Matrix element 2,2 } U_MAT2X2, *PU_MAT2X2; // ************************************************************************************************ @@ -2680,6 +2612,7 @@ void dumpeht(char *string, unsigned int *handle, EMFHANDLES *eht); +char *U_emr_names(unsigned int idx); uint32_t *dx_set(int32_t height, uint32_t weight, uint32_t members); uint32_t emr_properties(uint32_t type); int emr_arc_points(PU_ENHMETARECORD record, int *f1, int f2, PU_PAIRF center, PU_PAIRF start, PU_PAIRF end, PU_PAIRF size); @@ -2706,6 +2639,7 @@ int htable_delete(uint32_t *ih, EMFHANDLES *eht); int htable_insert(uint32_t *ih, EMFHANDLES *eht); int htable_free(EMFHANDLES **eht); +int htable_mftype(uint32_t type, EMFHANDLES *eht); U_RECTL rectl_set(U_POINTL ul, U_POINTL lr); U_SIZEL sizel_set(int32_t x, int32_t y); === modified file 'src/extension/internal/uemf_endian.c' --- src/extension/internal/uemf_endian.c 2012-10-25 08:08:38 +0000 +++ src/extension/internal/uemf_endian.c 2013-01-24 22:25:55 +0000 @@ -17,11 +17,11 @@ /* File: uemf_endian.h -Version: 0.0.9 -Date: 19-SEP-2012 +Version: 0.0.10 +Date: 11-JAN-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -42,37 +42,26 @@ *********************************************************************************************** */ void U_swap2(void *ul, unsigned int count){ - union i16 { - uint16_t i16; - uint8_t i8[2]; - }; - register union i16 ltmp; - register uint8_t ctmp; - for(; count; count--,ul+=2){ - ltmp.i16 = *(uint16_t *)ul; - ctmp = ltmp.i8[0]; - ltmp.i8[0] = ltmp.i8[1]; - ltmp.i8[1] = ctmp; - *(uint16_t *)ul = ltmp.i16; + uint8_t ctmp; + uint8_t *cl = (uint8_t *) ul; + for(; count; count--,cl+=2){ + ctmp = *cl; + *cl = *(cl+1); + *(cl+1) = ctmp; } } +/* Note: U_swap4 is also used by uwmf_endian.c, in cases where the 32 bit data is not aligned on a 4 byte boundary */ void U_swap4(void *ul, unsigned int count){ - union i32 { - uint32_t i32; - uint8_t i8[4]; - }; - register union i32 ltmp; - register uint8_t ctmp; - for(;count;count--,ul+=4){ - ltmp.i32 = *(uint32_t *)ul; - ctmp = ltmp.i8[0]; - ltmp.i8[0] = ltmp.i8[3]; - ltmp.i8[3] = ctmp; - ctmp = ltmp.i8[1]; - ltmp.i8[1] = ltmp.i8[2]; - ltmp.i8[2] = ctmp; - *(uint32_t *)ul = ltmp.i32; + uint8_t ctmp; + uint8_t *cl = (uint8_t *) ul; + for(; count; count--,cl+=4){ + ctmp = *(cl+0); + *(cl+0) = *(cl+3); + *(cl+3) = ctmp; + ctmp = *(cl+1); + *(cl+1) = *(cl+2); + *(cl+2) = ctmp; } } === modified file 'src/extension/internal/uemf_print.c' --- src/extension/internal/uemf_print.c 2012-10-25 08:08:38 +0000 +++ src/extension/internal/uemf_print.c 2013-01-24 22:25:55 +0000 @@ -4,11 +4,11 @@ /* File: uemf_print.c -Version: 0.0.9 -Date: 19-OCT-2012 +Version: 0.0.11 +Date: 22-JAN-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -17,6 +17,7 @@ #include #include +#include /* for offsetof() macro */ #include #include "uemf.h" @@ -90,8 +91,10 @@ } /** - \brief Print a U_POINT16 object - \param pt U_POINT16 object + \brief Print a pointer to a U_POINT16 object + \param pt pointer to a U_POINT16 object + Warning - WMF data may contain unaligned U_POINT16, do not call + this routine with a pointer to such data! */ void point16_print( U_POINT16 pt @@ -137,7 +140,7 @@ /** \brief Print a U_GRADIENT3 object. - \param tv U_GRADIENT3 object. + \param g3 U_GRADIENT3 object. */ void gradient3_print( U_GRADIENT3 g3 @@ -147,7 +150,7 @@ /** \brief Print a U_GRADIENT4 object. - \param tv U_GRADIENT4 object. + \param g4 U_GRADIENT4 object. */ void gradient4_print( U_GRADIENT4 g4 @@ -308,41 +311,55 @@ } /** - \brief Print a U_BITMAPINFOHEADER object. - \param Bmi U_BITMAPINFOHEADER object + \brief Print a pointer to U_BITMAPINFOHEADER object. + \param Bmih pointer to a U_BITMAPINFOHEADER object + This may be called indirectly from WMF _print routines, where problems could occur + if the data was passed as the struct or a pointer to the struct, as the struct may not + be aligned in memory. */ void bitmapinfoheader_print( - U_BITMAPINFOHEADER Bmi + char *Bmih ){ - printf("biSize:%u " ,Bmi.biSize ); - printf("biWidth:%d " ,Bmi.biWidth ); - printf("biHeight:%d " ,Bmi.biHeight ); - printf("biPlanes:%u " ,Bmi.biPlanes ); - printf("biBitCount:%u " ,Bmi.biBitCount ); - printf("biCompression:%u " ,Bmi.biCompression ); - printf("biSizeImage:%u " ,Bmi.biSizeImage ); - printf("biXPelsPerMeter:%d " ,Bmi.biXPelsPerMeter); - printf("biYPelsPerMeter:%d " ,Bmi.biYPelsPerMeter); - printf("biClrUsed:%u " ,Bmi.biClrUsed ); - printf("biClrImportant:%u " ,Bmi.biClrImportant ); + uint32_t utmp4; + int32_t tmp4; + int16_t tmp2; + + /* DIB from a WMF may not be properly aligned on a 4 byte boundary, will be aligned on a 2 byte boundary */ + + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSize), 4); printf("biSize:%u " ,utmp4 ); + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biWidth), 4); printf("biWidth:%d " ,tmp4 ); + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biHeight), 4); printf("biHeight:%d " ,tmp4 ); + memcpy(&tmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biPlanes), 2); printf("biPlanes:%u " ,tmp2 ); + memcpy(&tmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biBitCount), 2); printf("biBitCount:%u " ,tmp2 ); + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biCompression), 4); printf("biCompression:%u " ,utmp4 ); + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSizeImage), 4); printf("biSizeImage:%u " ,utmp4 ); + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biXPelsPerMeter), 4); printf("biXPelsPerMeter:%d " ,tmp4 ); + memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biYPelsPerMeter), 4); printf("biYPelsPerMeter:%d " ,tmp4 ); + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrUsed), 4); printf("biClrUsed:%u " ,utmp4 ); + memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrImportant), 4); printf("biClrImportant:%u " ,utmp4 ); } /** \brief Print a Pointer to a U_BITMAPINFO object. \param Bmi Pointer to a U_BITMAPINFO object + This may be called from WMF _print routines, where problems could occur + if the data was passed as the struct or a pointer to the struct, as the struct may not + be aligned in memory. */ void bitmapinfo_print( - PU_BITMAPINFO Bmi + char *Bmi ){ - int i; - PU_RGBQUAD BmiColors; - PU_BITMAPINFOHEADER BmiHeader = &(Bmi->bmiHeader); - printf("BmiHeader: "); bitmapinfoheader_print(*BmiHeader); - if(BmiHeader->biClrUsed){ - BmiColors = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER)); - for(i=0; ibiClrUsed; i++){ - printf("%d:",i); rgbquad_print(BmiColors[i]); + int i,k; + uint32_t biClrUsed; + U_RGBQUAD BmiColor; + printf("BmiHeader: "); bitmapinfoheader_print(Bmi + offsetof(U_BITMAPINFO,bmiHeader)); + memcpy(&biClrUsed, Bmi + offsetof(U_BITMAPINFO,bmiHeader) + offsetof(U_BITMAPINFOHEADER,biClrUsed), 4); + if(biClrUsed){ + k= offsetof(U_BITMAPINFO,bmiColors); + for(i=0; iiType,(int) off,lpEMFR->nSize); -} // Functions with the same form starting with U_EMRPOLYBEZIER_print -void core1_print(char *name, char *contents, int recnum, size_t off){ +void core1_print(char *name, char *contents){ int i; - PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (contents + off); - core5_print(name, contents, recnum, off); + PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (contents); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" cptl: %d\n",pEmr->cptl ); printf(" Points: "); @@ -626,10 +610,9 @@ } // Functions with the same form starting with U_EMRPOLYPOLYLINE_print -void core2_print(char *name, char *contents, int recnum, size_t off){ +void core2_print(char *name, char *contents){ int i; - PU_EMRPOLYPOLYGON pEmr = (PU_EMRPOLYPOLYGON) (contents + off); - core5_print(name, contents, recnum, off); + PU_EMRPOLYPOLYGON pEmr = (PU_EMRPOLYPOLYGON) (contents); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" nPolys: %d\n",pEmr->nPolys ); printf(" cptl: %d\n",pEmr->cptl ); @@ -648,9 +631,8 @@ // Functions with the same form starting with U_EMRSETMAPMODE_print -void core3_print(char *name, char *label, char *contents, int recnum, size_t off){ - PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(contents + off); - core5_print(name, contents, recnum, off); +void core3_print(char *name, char *label, char *contents){ + PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(contents); if(!strcmp(label,"crColor:")){ printf(" %-15s ",label); colorref_print(*(U_COLORREF *)&(pEmr->iMode)); printf("\n"); } @@ -663,17 +645,15 @@ } // Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_print, also U_EMRFILLPATH_print, -void core4_print(char *name, char *contents, int recnum, size_t off){ - PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( contents + off); - core5_print(name, contents, recnum, off); +void core4_print(char *name, char *contents){ + PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( contents); printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n"); } // Functions with the same form starting with U_EMRPOLYBEZIER16_print -void core6_print(char *name, char *contents, int recnum, size_t off){ +void core6_print(char *name, char *contents){ int i; - PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (contents + off); - core5_print(name, contents, recnum, off); + PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (contents); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" cpts: %d\n",pEmr->cpts ); printf(" Points: "); @@ -689,9 +669,8 @@ // CAREFUL, in the _set equivalents all functions with two uint32_t values are mapped here, and member names differ, consequently // print routines must supply the names of the two arguments. These cannot be null. If the second one is // empty the values are printed as a pair {x,y}, otherwise each is printed with its own label on a separate line. -void core7_print(char *name, char *field1, char *field2, char *contents, int recnum, size_t off){ - PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (contents + off); - core5_print(name, contents, recnum, off); +void core7_print(char *name, char *field1, char *field2, char *contents){ + PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (contents); if(*field2){ printf(" %-15s %d\n",field1,pEmr->pair.x); printf(" %-15s %d\n",field2,pEmr->pair.y); @@ -702,32 +681,29 @@ } // For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one -void core8_print(char *name, char *contents, int recnum, size_t off, int type){ - PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (contents + off); - core5_print(name, contents, recnum, off); +void core8_print(char *name, char *contents, int type){ + PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (contents); printf(" iGraphicsMode: %u\n",pEmr->iGraphicsMode ); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" exScale: %f\n",pEmr->exScale ); printf(" eyScale: %f\n",pEmr->eyScale ); printf(" emrtext: "); - emrtext_print(contents + off + sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT),contents + off,type); + emrtext_print(contents + sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT),contents,type); printf("\n"); } // Functions that take a rect and a pair of points, starting with U_EMRARC_print -void core9_print(char *name, char *contents, int recnum, size_t off){ - PU_EMRARC pEmr = (PU_EMRARC) (contents + off); - core5_print(name, contents, recnum, off); +void core9_print(char *name, char *contents){ + PU_EMRARC pEmr = (PU_EMRARC) (contents); printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n"); printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n"); printf(" ptlEnd: "); pointl_print(pEmr->ptlEnd); printf("\n"); } // Functions with the same form starting with U_EMRPOLYPOLYLINE16_print -void core10_print(char *name, char *contents, int recnum, size_t off){ +void core10_print(char *name, char *contents){ int i; - PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (contents + off); - core5_print(name, contents, recnum, off); + PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (contents); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" nPolys: %d\n",pEmr->nPolys ); printf(" cpts: %d\n",pEmr->cpts ); @@ -746,10 +722,9 @@ } // Functions with the same form starting with U_EMRINVERTRGN_print and U_EMRPAINTRGN_print, -void core11_print(char *name, char *contents, int recnum, size_t off){ +void core11_print(char *name, char *contents){ int i,roff; - PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (contents + off); - core5_print(name, contents, recnum, off); + PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (contents); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" cbRgnData: %d\n",pEmr->cbRgnData); // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them. @@ -766,16 +741,15 @@ // common code for U_EMRCREATEMONOBRUSH_print and U_EMRCREATEDIBPATTERNBRUSHPT_print, -void core12_print(char *name, char *contents, int recnum, size_t off){ - PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (contents + off); - core5_print(name, contents, recnum, off); +void core12_print(char *name, char *contents){ + PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (contents); printf(" ihBrush: %u\n",pEmr->ihBrush ); printf(" iUsage : %u\n",pEmr->iUsage ); printf(" offBmi : %u\n",pEmr->offBmi ); printf(" cbBmi : %u\n",pEmr->cbBmi ); if(pEmr->cbBmi){ printf(" bitmap:"); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmi)); + bitmapinfo_print(contents + pEmr->offBmi); printf("\n"); } printf(" offBits: %u\n",pEmr->offBits ); @@ -783,9 +757,8 @@ } // common code for U_EMRALPHABLEND_print and U_EMRTRANSPARENTBLT_print, -void core13_print(char *name, char *contents, int recnum, size_t off){ - PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (contents + off); - core5_print(name, contents, recnum, off); +void core13_print(char *name, char *contents){ + PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); @@ -798,7 +771,7 @@ printf(" cbBmiSrc: %u\n",pEmr->cbBmiSrc ); if(pEmr->cbBmiSrc){ printf(" bitmap:"); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc)); + bitmapinfo_print(contents + pEmr->offBmiSrc); printf("\n"); } printf(" offBitsSrc: %u\n",pEmr->offBitsSrc ); @@ -816,12 +789,8 @@ \brief Print a pointer to a U_EMR_whatever record which has not been implemented. \param name name of this type of record \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRNOTIMPLEMENTED_print(char *name, char *contents, int recnum, size_t off){ - PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off); - printf("%-30srecord:%5d type:%3d offset:%8d size:%8d\n",name,recnum,lpEMFR->iType,(int) off,lpEMFR->nSize); +void U_EMRNOTIMPLEMENTED_print(char *name, char *contents){ printf(" Not Implemented!\n"); } @@ -829,15 +798,12 @@ /** \brief Print a pointer to a U_EMR_HEADER record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRHEADER_print(char *contents, int recnum, size_t off){ +void U_EMRHEADER_print(char *contents){ char *string; int p1len; - core5_print("U_EMRHEADER", contents, recnum, off); - PU_EMRHEADER pEmr = (PU_EMRHEADER)(contents+off); + PU_EMRHEADER pEmr = (PU_EMRHEADER)(contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" rclFrame: "); rectl_print( pEmr->rclFrame); printf("\n"); printf(" dSignature: 0x%8.8X\n", pEmr->dSignature ); @@ -867,7 +833,7 @@ printf(" offPixelFormat: %d\n", pEmr->offPixelFormat); if(pEmr->cbPixelFormat){ printf(" PFD:"); - pixelformatdescriptor_print( *(PU_PIXELFORMATDESCRIPTOR) (contents + off + pEmr->offPixelFormat)); + pixelformatdescriptor_print( *(PU_PIXELFORMATDESCRIPTOR) (contents + pEmr->offPixelFormat)); printf("\n"); } printf(" bOpenGL: %d\n",pEmr->bOpenGL ); @@ -884,22 +850,18 @@ /** \brief Print a pointer to a U_EMR_POLYBEZIER record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYBEZIER_print(char *contents, int recnum, size_t off){ - core1_print("U_EMRPOLYBEZIER", contents, recnum, off); +void U_EMRPOLYBEZIER_print(char *contents){ + core1_print("U_EMRPOLYBEZIER", contents); } // U_EMRPOLYGON 3 /** \brief Print a pointer to a U_EMR_POLYGON record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYGON_print(char *contents, int recnum, size_t off){ - core1_print("U_EMRPOLYGON", contents, recnum, off); +void U_EMRPOLYGON_print(char *contents){ + core1_print("U_EMRPOLYGON", contents); } @@ -907,128 +869,104 @@ /** \brief Print a pointer to a U_EMR_POLYLINE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYLINE_print(char *contents, int recnum, size_t off){ - core1_print("U_EMRPOLYLINE", contents, recnum, off); +void U_EMRPOLYLINE_print(char *contents){ + core1_print("U_EMRPOLYLINE", contents); } // U_EMRPOLYBEZIERTO 5 /** \brief Print a pointer to a U_EMR_POLYBEZIERTO record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYBEZIERTO_print(char *contents, int recnum, size_t off){ - core1_print("U_EMRPOLYBEZIERTO", contents, recnum, off); +void U_EMRPOLYBEZIERTO_print(char *contents){ + core1_print("U_EMRPOLYBEZIERTO", contents); } // U_EMRPOLYLINETO 6 /** \brief Print a pointer to a U_EMR_POLYLINETO record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYLINETO_print(char *contents, int recnum, size_t off){ - core1_print("U_EMRPOLYLINETO", contents, recnum, off); +void U_EMRPOLYLINETO_print(char *contents){ + core1_print("U_EMRPOLYLINETO", contents); } // U_EMRPOLYPOLYLINE 7 /** \brief Print a pointer to a U_EMR_POLYPOLYLINE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYPOLYLINE_print(char *contents, int recnum, size_t off){ - core2_print("U_EMRPOLYPOLYLINE", contents, recnum, off); +void U_EMRPOLYPOLYLINE_print(char *contents){ + core2_print("U_EMRPOLYPOLYLINE", contents); } // U_EMRPOLYPOLYGON 8 /** \brief Print a pointer to a U_EMR_POLYPOLYGON record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYPOLYGON_print(char *contents, int recnum, size_t off){ - core2_print("U_EMRPOLYPOLYGON", contents, recnum, off); +void U_EMRPOLYPOLYGON_print(char *contents){ + core2_print("U_EMRPOLYPOLYGON", contents); } // U_EMRSETWINDOWEXTEX 9 /** \brief Print a pointer to a U_EMR_SETWINDOWEXTEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETWINDOWEXTEX_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRSETWINDOWEXTEX", "szlExtent:","",contents, recnum, off); +void U_EMRSETWINDOWEXTEX_print(char *contents){ + core7_print("U_EMRSETWINDOWEXTEX", "szlExtent:","",contents); } // U_EMRSETWINDOWORGEX 10 /** \brief Print a pointer to a U_EMR_SETWINDOWORGEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETWINDOWORGEX_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRSETWINDOWORGEX", "ptlOrigin:","",contents, recnum, off); +void U_EMRSETWINDOWORGEX_print(char *contents){ + core7_print("U_EMRSETWINDOWORGEX", "ptlOrigin:","",contents); } // U_EMRSETVIEWPORTEXTEX 11 /** \brief Print a pointer to a U_EMR_SETVIEWPORTEXTEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETVIEWPORTEXTEX_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRSETVIEWPORTEXTEX", "szlExtent:","",contents, recnum, off); +void U_EMRSETVIEWPORTEXTEX_print(char *contents){ + core7_print("U_EMRSETVIEWPORTEXTEX", "szlExtent:","",contents); } // U_EMRSETVIEWPORTORGEX 12 /** \brief Print a pointer to a U_EMR_SETVIEWPORTORGEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETVIEWPORTORGEX_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRSETVIEWPORTORGEX", "ptlOrigin:","",contents, recnum, off); +void U_EMRSETVIEWPORTORGEX_print(char *contents){ + core7_print("U_EMRSETVIEWPORTORGEX", "ptlOrigin:","",contents); } // U_EMRSETBRUSHORGEX 13 /** \brief Print a pointer to a U_EMR_SETBRUSHORGEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETBRUSHORGEX_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRSETBRUSHORGEX", "ptlOrigin:","",contents, recnum, off); +void U_EMRSETBRUSHORGEX_print(char *contents){ + core7_print("U_EMRSETBRUSHORGEX", "ptlOrigin:","",contents); } // U_EMREOF 14 /** \brief Print a pointer to a U_EMR_EOF record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREOF_print(char *contents, int recnum, size_t off){ - core5_print("U_EMREOF", contents, recnum, off); - - PU_EMREOF pEmr = (PU_EMREOF)(contents+off); +void U_EMREOF_print(char *contents){ + PU_EMREOF pEmr = (PU_EMREOF)(contents); printf(" cbPalEntries: %u\n", pEmr->cbPalEntries ); printf(" offPalEntries: %u\n", pEmr->offPalEntries); if(pEmr->cbPalEntries){ printf(" PE:"); - logpalette_print( (PU_LOGPALETTE)(contents + off + pEmr->offPalEntries)); + logpalette_print( (PU_LOGPALETTE)(contents + pEmr->offPalEntries)); printf("\n"); } } @@ -1038,12 +976,9 @@ /** \brief Print a pointer to a U_EMR_SETPIXELV record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETPIXELV_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRSETPIXELV", contents, recnum, off); - PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(contents+off); +void U_EMRSETPIXELV_print(char *contents){ + PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(contents); printf(" ptlPixel: "); pointl_print( pEmr->ptlPixel); printf("\n"); printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n"); } @@ -1053,12 +988,9 @@ /** \brief Print a pointer to a U_EMR_SETMAPPERFLAGS record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETMAPPERFLAGS_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRSETMAPPERFLAGS", contents, recnum, off); - PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(contents+off); +void U_EMRSETMAPPERFLAGS_print(char *contents){ + PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(contents); printf(" dwFlags: %u\n",pEmr->dwFlags); } @@ -1067,78 +999,63 @@ /** \brief Print a pointer to a U_EMR_SETMAPMODE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETMAPMODE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETMAPMODE", "iMode:", contents, recnum, off); +void U_EMRSETMAPMODE_print(char *contents){ + core3_print("U_EMRSETMAPMODE", "iMode:", contents); } // U_EMRSETBKMODE 18 /** \brief Print a pointer to a U_EMR_SETBKMODE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETBKMODE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETBKMODE", "iMode:", contents, recnum, off); +void U_EMRSETBKMODE_print(char *contents){ + core3_print("U_EMRSETBKMODE", "iMode:", contents); } // U_EMRSETPOLYFILLMODE 19 /** \brief Print a pointer to a U_EMR_SETPOLYFILLMODE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETPOLYFILLMODE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETPOLYFILLMODE", "iMode:", contents, recnum, off); +void U_EMRSETPOLYFILLMODE_print(char *contents){ + core3_print("U_EMRSETPOLYFILLMODE", "iMode:", contents); } // U_EMRSETROP2 20 /** \brief Print a pointer to a U_EMR_SETROP2 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETROP2_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETROP2", "dwRop:", contents, recnum, off); +void U_EMRSETROP2_print(char *contents){ + core3_print("U_EMRSETROP2", "dwRop:", contents); } // U_EMRSETSTRETCHBLTMODE 21 /** \brief Print a pointer to a U_EMR_SETSTRETCHBLTMODE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETSTRETCHBLTMODE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETSTRETCHBLTMODE", "iMode:", contents, recnum, off); +void U_EMRSETSTRETCHBLTMODE_print(char *contents){ + core3_print("U_EMRSETSTRETCHBLTMODE", "iMode:", contents); } // U_EMRSETTEXTALIGN 22 /** \brief Print a pointer to a U_EMR_SETTEXTALIGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETTEXTALIGN_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETTEXTALIGN", "iMode:", contents, recnum, off); +void U_EMRSETTEXTALIGN_print(char *contents){ + core3_print("U_EMRSETTEXTALIGN", "iMode:", contents); } // U_EMRSETCOLORADJUSTMENT 23 /** \brief Print a pointer to a U_EMR_SETCOLORADJUSTMENT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETCOLORADJUSTMENT_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRSETCOLORADJUSTMENT", contents, recnum, off); - PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(contents+off); +void U_EMRSETCOLORADJUSTMENT_print(char *contents){ + PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(contents); printf(" ColorAdjustment:"); coloradjustment_print(pEmr->ColorAdjustment); printf("\n"); @@ -1148,88 +1065,71 @@ /** \brief Print a pointer to a U_EMR_SETTEXTCOLOR record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETTEXTCOLOR_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETTEXTCOLOR", "crColor:", contents, recnum, off); +void U_EMRSETTEXTCOLOR_print(char *contents){ + core3_print("U_EMRSETTEXTCOLOR", "crColor:", contents); } // U_EMRSETBKCOLOR 25 /** \brief Print a pointer to a U_EMR_SETBKCOLOR record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETBKCOLOR_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETBKCOLOR", "crColor:", contents, recnum, off); +void U_EMRSETBKCOLOR_print(char *contents){ + core3_print("U_EMRSETBKCOLOR", "crColor:", contents); } // U_EMROFFSETCLIPRGN 26 /** \brief Print a pointer to a U_EMR_OFFSETCLIPRGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMROFFSETCLIPRGN_print(char *contents, int recnum, size_t off){ - core7_print("U_EMROFFSETCLIPRGN", "ptl:","",contents, recnum, off); +void U_EMROFFSETCLIPRGN_print(char *contents){ + core7_print("U_EMROFFSETCLIPRGN", "ptl:","",contents); } // U_EMRMOVETOEX 27 /** \brief Print a pointer to a U_EMR_MOVETOEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRMOVETOEX_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRMOVETOEX", "ptl:","",contents, recnum, off); +void U_EMRMOVETOEX_print(char *contents){ + core7_print("U_EMRMOVETOEX", "ptl:","",contents); } // U_EMRSETMETARGN 28 /** \brief Print a pointer to a U_EMR_SETMETARGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETMETARGN_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRSETMETARGN", contents, recnum, off); +void U_EMRSETMETARGN_print(char *contents){ } // U_EMREXCLUDECLIPRECT 29 /** \brief Print a pointer to a U_EMR_EXCLUDECLIPRECT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREXCLUDECLIPRECT_print(char *contents, int recnum, size_t off){ - core4_print("U_EMREXCLUDECLIPRECT", contents, recnum, off); +void U_EMREXCLUDECLIPRECT_print(char *contents){ + core4_print("U_EMREXCLUDECLIPRECT", contents); } // U_EMRINTERSECTCLIPRECT 30 /** \brief Print a pointer to a U_EMR_INTERSECTCLIPRECT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRINTERSECTCLIPRECT_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRINTERSECTCLIPRECT", contents, recnum, off); +void U_EMRINTERSECTCLIPRECT_print(char *contents){ + core4_print("U_EMRINTERSECTCLIPRECT", contents); } // U_EMRSCALEVIEWPORTEXTEX 31 /** \brief Print a pointer to a U_EMR_SCALEVIEWPORTEXTEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSCALEVIEWPORTEXTEX_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRSCALEVIEWPORTEXTEX", contents, recnum, off); +void U_EMRSCALEVIEWPORTEXTEX_print(char *contents){ + core4_print("U_EMRSCALEVIEWPORTEXTEX", contents); } @@ -1237,45 +1137,35 @@ /** \brief Print a pointer to a U_EMR_SCALEWINDOWEXTEX record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSCALEWINDOWEXTEX_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRSCALEWINDOWEXTEX", contents, recnum, off); +void U_EMRSCALEWINDOWEXTEX_print(char *contents){ + core4_print("U_EMRSCALEWINDOWEXTEX", contents); } // U_EMRSAVEDC 33 /** \brief Print a pointer to a U_EMR_SAVEDC record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSAVEDC_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRSAVEDC", contents, recnum, off); +void U_EMRSAVEDC_print(char *contents){ } // U_EMRRESTOREDC 34 /** \brief Print a pointer to a U_EMR_RESTOREDC record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRRESTOREDC_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRRESTOREDC", "iRelative:", contents, recnum, off); +void U_EMRRESTOREDC_print(char *contents){ + core3_print("U_EMRRESTOREDC", "iRelative:", contents); } // U_EMRSETWORLDTRANSFORM 35 /** \brief Print a pointer to a U_EMR_SETWORLDTRANSFORM record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETWORLDTRANSFORM_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRSETWORLDTRANSFORM", contents, recnum, off); - PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(contents+off); +void U_EMRSETWORLDTRANSFORM_print(char *contents){ + PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(contents); printf(" xform:"); xform_print(pEmr->xform); printf("\n"); @@ -1285,12 +1175,9 @@ /** \brief Print a pointer to a U_EMR_MODIFYWORLDTRANSFORM record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRMODIFYWORLDTRANSFORM_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRMODIFYWORLDTRANSFORM", contents, recnum, off); - PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(contents+off); +void U_EMRMODIFYWORLDTRANSFORM_print(char *contents){ + PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(contents); printf(" xform:"); xform_print(pEmr->xform); printf("\n"); @@ -1301,12 +1188,9 @@ /** \brief Print a pointer to a U_EMR_SELECTOBJECT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSELECTOBJECT_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRSELECTOBJECT", contents, recnum, off); - PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(contents+off); +void U_EMRSELECTOBJECT_print(char *contents){ + PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(contents); if(pEmr->ihObject & U_STOCK_OBJECT){ printf(" StockObject: 0x%8.8X\n", pEmr->ihObject ); } @@ -1319,12 +1203,9 @@ /** \brief Print a pointer to a U_EMR_CREATEPEN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCREATEPEN_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRCREATEPEN", contents, recnum, off); - PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(contents+off); +void U_EMRCREATEPEN_print(char *contents){ + PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(contents); printf(" ihPen: %u\n", pEmr->ihPen ); printf(" lopn: "); logpen_print(pEmr->lopn); printf("\n"); } @@ -1333,12 +1214,9 @@ /** \brief Print a pointer to a U_EMR_CREATEBRUSHINDIRECT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCREATEBRUSHINDIRECT_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRCREATEBRUSHINDIRECT", contents, recnum, off); - PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(contents+off); +void U_EMRCREATEBRUSHINDIRECT_print(char *contents){ + PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(contents); printf(" ihBrush: %u\n", pEmr->ihBrush ); printf(" lb: "); logbrush_print(pEmr->lb); printf("\n"); } @@ -1347,12 +1225,9 @@ /** \brief Print a pointer to a U_EMR_DELETEOBJECT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRDELETEOBJECT_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRDELETEOBJECT", contents, recnum, off); - PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(contents+off); +void U_EMRDELETEOBJECT_print(char *contents){ + PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(contents); printf(" ihObject: %u\n", pEmr->ihObject ); } @@ -1360,12 +1235,9 @@ /** \brief Print a pointer to a U_EMR_ANGLEARC record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRANGLEARC_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRANGLEARC", contents, recnum, off); - PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(contents+off); +void U_EMRANGLEARC_print(char *contents){ + PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(contents); printf(" ptlCenter: "), pointl_print(pEmr->ptlCenter ); printf("\n"); printf(" nRadius: %u\n", pEmr->nRadius ); printf(" eStartAngle: %f\n", pEmr->eStartAngle ); @@ -1376,34 +1248,27 @@ /** \brief Print a pointer to a U_EMR_ELLIPSE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRELLIPSE_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRELLIPSE", contents, recnum, off); +void U_EMRELLIPSE_print(char *contents){ + core4_print("U_EMRELLIPSE", contents); } // U_EMRRECTANGLE 43 /** \brief Print a pointer to a U_EMR_RECTANGLE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRRECTANGLE_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRRECTANGLE", contents, recnum, off); +void U_EMRRECTANGLE_print(char *contents){ + core4_print("U_EMRRECTANGLE", contents); } // U_EMRROUNDRECT 44 /** \brief Print a pointer to a U_EMR_ROUNDRECT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRROUNDRECT_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRROUNDRECT", contents, recnum, off); - PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(contents+off); +void U_EMRROUNDRECT_print(char *contents){ + PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(contents); printf(" rclBox: "), rectl_print(pEmr->rclBox ); printf("\n"); printf(" szlCorner: "), sizel_print(pEmr->szlCorner ); printf("\n"); } @@ -1412,56 +1277,45 @@ /** \brief Print a pointer to a U_EMR_ARC record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRARC_print(char *contents, int recnum, size_t off){ - core9_print("U_EMRARC", contents, recnum, off); +void U_EMRARC_print(char *contents){ + core9_print("U_EMRARC", contents); } // U_EMRCHORD 46 /** \brief Print a pointer to a U_EMR_CHORD record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCHORD_print(char *contents, int recnum, size_t off){ - core9_print("U_EMRCHORD", contents, recnum, off); +void U_EMRCHORD_print(char *contents){ + core9_print("U_EMRCHORD", contents); } // U_EMRPIE 47 /** \brief Print a pointer to a U_EMR_PIE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPIE_print(char *contents, int recnum, size_t off){ - core9_print("U_EMRPIE", contents, recnum, off); +void U_EMRPIE_print(char *contents){ + core9_print("U_EMRPIE", contents); } // U_EMRSELECTPALETTE 48 /** \brief Print a pointer to a U_EMR_SELECTPALETTE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSELECTPALETTE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSELECTPALETTE", "ihPal:", contents, recnum, off); +void U_EMRSELECTPALETTE_print(char *contents){ + core3_print("U_EMRSELECTPALETTE", "ihPal:", contents); } // U_EMRCREATEPALETTE 49 /** \brief Print a pointer to a U_EMR_CREATEPALETTE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCREATEPALETTE_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRCREATEPALETTE", contents, recnum, off); - PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(contents+off); +void U_EMRCREATEPALETTE_print(char *contents){ + PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(contents); printf(" ihPal: %u\n",pEmr->ihPal); printf(" lgpl: "), logpalette_print( (PU_LOGPALETTE)&(pEmr->lgpl) ); printf("\n"); } @@ -1470,13 +1324,10 @@ /** \brief Print a pointer to a U_EMR_SETPALETTEENTRIES record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETPALETTEENTRIES_print(char *contents, int recnum, size_t off){ +void U_EMRSETPALETTEENTRIES_print(char *contents){ int i; - core5_print("U_EMRSETPALETTEENTRIES", contents, recnum, off); - PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(contents+off); + PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(contents); printf(" ihPal: %u\n",pEmr->ihPal); printf(" iStart: %u\n",pEmr->iStart); printf(" cEntries: %u\n",pEmr->cEntries); @@ -1494,34 +1345,26 @@ /** \brief Print a pointer to a U_EMR_RESIZEPALETTE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRRESIZEPALETTE_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRRESIZEPALETTE", "ihPal:","cEntries",contents, recnum, off); +void U_EMRRESIZEPALETTE_print(char *contents){ + core7_print("U_EMRRESIZEPALETTE", "ihPal:","cEntries",contents); } // U_EMRREALIZEPALETTE 52 /** \brief Print a pointer to a U_EMR_REALIZEPALETTE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRREALIZEPALETTE_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRREALIZEPALETTE", contents, recnum, off); +void U_EMRREALIZEPALETTE_print(char *contents){ } // U_EMREXTFLOODFILL 53 /** \brief Print a pointer to a U_EMR_EXTFLOODFILL record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREXTFLOODFILL_print(char *contents, int recnum, size_t off){ - core5_print("U_EMREXTFLOODFILL", contents, recnum, off); - PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(contents+off); +void U_EMREXTFLOODFILL_print(char *contents){ + PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(contents); printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n"); printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n"); printf(" iMode: %u\n",pEmr->iMode); @@ -1531,35 +1374,28 @@ /** \brief Print a pointer to a U_EMR_LINETO record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRLINETO_print(char *contents, int recnum, size_t off){ - core7_print("U_EMRLINETO", "ptl:","",contents, recnum, off); +void U_EMRLINETO_print(char *contents){ + core7_print("U_EMRLINETO", "ptl:","",contents); } // U_EMRARCTO 55 /** \brief Print a pointer to a U_EMR_ARCTO record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRARCTO_print(char *contents, int recnum, size_t off){ - core9_print("U_EMRARCTO", contents, recnum, off); +void U_EMRARCTO_print(char *contents){ + core9_print("U_EMRARCTO", contents); } // U_EMRPOLYDRAW 56 /** \brief Print a pointer to a U_EMR_POLYDRAW record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYDRAW_print(char *contents, int recnum, size_t off){ +void U_EMRPOLYDRAW_print(char *contents){ int i; - core5_print("U_EMRPOLYDRAW", contents, recnum, off); - PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(contents+off); + PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" cptl: %d\n",pEmr->cptl ); printf(" Points: "); @@ -1579,22 +1415,18 @@ /** \brief Print a pointer to a U_EMR_SETARCDIRECTION record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETARCDIRECTION_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETARCDIRECTION","arcDirection:", contents, recnum, off); +void U_EMRSETARCDIRECTION_print(char *contents){ + core3_print("U_EMRSETARCDIRECTION","arcDirection:", contents); } // U_EMRSETMITERLIMIT 58 /** \brief Print a pointer to a U_EMR_SETMITERLIMIT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETMITERLIMIT_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETMITERLIMIT", "eMiterLimit:", contents, recnum, off); +void U_EMRSETMITERLIMIT_print(char *contents){ + core3_print("U_EMRSETMITERLIMIT", "eMiterLimit:", contents); } @@ -1602,128 +1434,99 @@ /** \brief Print a pointer to a U_EMR_BEGINPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRBEGINPATH_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRBEGINPATH", contents, recnum, off); +void U_EMRBEGINPATH_print(char *contents){ } // U_EMRENDPATH 60 /** \brief Print a pointer to a U_EMR_ENDPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRENDPATH_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRENDPATH", contents, recnum, off); +void U_EMRENDPATH_print(char *contents){ } // U_EMRCLOSEFIGURE 61 /** \brief Print a pointer to a U_EMR_CLOSEFIGURE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCLOSEFIGURE_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRCLOSEFIGURE", contents, recnum, off); +void U_EMRCLOSEFIGURE_print(char *contents){ } // U_EMRFILLPATH 62 /** \brief Print a pointer to a U_EMR_FILLPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRFILLPATH_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRFILLPATH", contents, recnum, off); +void U_EMRFILLPATH_print(char *contents){ + core4_print("U_EMRFILLPATH", contents); } // U_EMRSTROKEANDFILLPATH 63 /** \brief Print a pointer to a U_EMR_STROKEANDFILLPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSTROKEANDFILLPATH_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRSTROKEANDFILLPATH", contents, recnum, off); +void U_EMRSTROKEANDFILLPATH_print(char *contents){ + core4_print("U_EMRSTROKEANDFILLPATH", contents); } // U_EMRSTROKEPATH 64 /** \brief Print a pointer to a U_EMR_STROKEPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSTROKEPATH_print(char *contents, int recnum, size_t off){ - core4_print("U_EMRSTROKEPATH", contents, recnum, off); +void U_EMRSTROKEPATH_print(char *contents){ + core4_print("U_EMRSTROKEPATH", contents); } // U_EMRFLATTENPATH 65 /** \brief Print a pointer to a U_EMR_FLATTENPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRFLATTENPATH_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRFLATTENPATH", contents, recnum, off); +void U_EMRFLATTENPATH_print(char *contents){ } // U_EMRWIDENPATH 66 /** \brief Print a pointer to a U_EMR_WIDENPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRWIDENPATH_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRWIDENPATH", contents, recnum, off); +void U_EMRWIDENPATH_print(char *contents){ } // U_EMRSELECTCLIPPATH 67 /** \brief Print a pointer to a U_EMR_SELECTCLIPPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSELECTCLIPPATH_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSELECTCLIPPATH", "iMode:", contents, recnum, off); +void U_EMRSELECTCLIPPATH_print(char *contents){ + core3_print("U_EMRSELECTCLIPPATH", "iMode:", contents); } // U_EMRABORTPATH 68 /** \brief Print a pointer to a U_EMR_ABORTPATH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRABORTPATH_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRABORTPATH", contents, recnum, off); +void U_EMRABORTPATH_print(char *contents){ } // U_EMRUNDEF69 69 -#define U_EMRUNDEF69_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF69",A,B,C) +#define U_EMRUNDEF69_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF69",A) // U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific) /** \brief Print a pointer to a U_EMR_COMMENT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCOMMENT_print(char *contents, int recnum, size_t off){ +void U_EMRCOMMENT_print(char *contents){ char *string; char *src; uint32_t cIdent,cbData; - core5_print("U_EMRCOMMENT", contents, recnum, off); - PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(contents+off); + PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(contents); /* There are several different types of comments */ @@ -1770,13 +1573,10 @@ /** \brief Print a pointer to a U_EMR_FILLRGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRFILLRGN_print(char *contents, int recnum, size_t off){ +void U_EMRFILLRGN_print(char *contents){ int i,roff; - core5_print("U_EMRFILLRGN", contents, recnum, off); - PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(contents+off); + PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(contents); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" cbRgnData: %u\n",pEmr->cbRgnData); printf(" ihBrush: %u\n",pEmr->ihBrush); @@ -1794,13 +1594,10 @@ /** \brief Print a pointer to a U_EMR_FRAMERGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRFRAMERGN_print(char *contents, int recnum, size_t off){ +void U_EMRFRAMERGN_print(char *contents){ int i,roff; - core5_print("U_EMRFRAMERGN", contents, recnum, off); - PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(contents+off); + PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(contents); printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n"); printf(" cbRgnData: %u\n",pEmr->cbRgnData); printf(" ihBrush: %u\n",pEmr->ihBrush); @@ -1819,35 +1616,28 @@ /** \brief Print a pointer to a U_EMR_INVERTRGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRINVERTRGN_print(char *contents, int recnum, size_t off){ - core11_print("U_EMRINVERTRGN", contents, recnum, off); +void U_EMRINVERTRGN_print(char *contents){ + core11_print("U_EMRINVERTRGN", contents); } // U_EMRPAINTRGN 74 /** \brief Print a pointer to a U_EMR_PAINTRGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPAINTRGN_print(char *contents, int recnum, size_t off){ - core11_print("U_EMRPAINTRGN", contents, recnum, off); +void U_EMRPAINTRGN_print(char *contents){ + core11_print("U_EMRPAINTRGN", contents); } // U_EMREXTSELECTCLIPRGN 75 /** \brief Print a pointer to a U_EMR_EXTSELECTCLIPRGN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREXTSELECTCLIPRGN_print(char *contents, int recnum, size_t off){ +void U_EMREXTSELECTCLIPRGN_print(char *contents){ int i,roff; - PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (contents + off); - core5_print("U_EMREXTSELECTCLIPRGN", contents, recnum, off); + PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (contents); printf(" cbRgnData: %u\n",pEmr->cbRgnData); printf(" iMode: %u\n",pEmr->iMode); // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them. @@ -1863,12 +1653,9 @@ /** \brief Print a pointer to a U_EMR_BITBLT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRBITBLT_print(char *contents, int recnum, size_t off){ - PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (contents + off); - core5_print("U_EMRBITBLT", contents, recnum, off); +void U_EMRBITBLT_print(char *contents){ + PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); @@ -1881,7 +1668,7 @@ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); if(pEmr->cbBmiSrc){ printf(" bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc)); + bitmapinfo_print(contents + pEmr->offBmiSrc); printf("\n"); } printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); @@ -1892,12 +1679,9 @@ /** \brief Print a pointer to a U_EMR_STRETCHBLT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSTRETCHBLT_print(char *contents, int recnum, size_t off){ - PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (contents + off); - core5_print("U_EMRSTRETCHBLT", contents, recnum, off); +void U_EMRSTRETCHBLT_print(char *contents){ + PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); @@ -1910,7 +1694,7 @@ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); if(pEmr->cbBmiSrc){ printf(" bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc)); + bitmapinfo_print(contents + pEmr->offBmiSrc); printf("\n"); } printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); @@ -1922,12 +1706,9 @@ /** \brief Print a pointer to a U_EMR_MASKBLT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRMASKBLT_print(char *contents, int recnum, size_t off){ - PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (contents + off); - core5_print("U_EMRMASKBLT", contents, recnum, off); +void U_EMRMASKBLT_print(char *contents){ + PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n"); @@ -1940,7 +1721,7 @@ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); if(pEmr->cbBmiSrc){ printf(" Src bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc)); + bitmapinfo_print(contents + pEmr->offBmiSrc); printf("\n"); } printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); @@ -1951,7 +1732,7 @@ printf(" cbBmiMask: %u\n", pEmr->cbBmiMask ); if(pEmr->cbBmiMask){ printf(" Mask bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiMask)); + bitmapinfo_print(contents + pEmr->offBmiMask); printf("\n"); } printf(" offBitsMask: %u\n", pEmr->offBitsMask ); @@ -1962,12 +1743,9 @@ /** \brief Print a pointer to a U_EMR_PLGBLT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPLGBLT_print(char *contents, int recnum, size_t off){ - PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (contents + off); - core5_print("U_EMRPLGBLT", contents, recnum, off); +void U_EMRPLGBLT_print(char *contents){ + PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" aptlDst(UL): "); pointl_print(pEmr->aptlDst[0]); printf("\n"); printf(" aptlDst(UR): "); pointl_print(pEmr->aptlDst[1]); printf("\n"); @@ -1981,7 +1759,7 @@ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); if(pEmr->cbBmiSrc){ printf(" Src bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc)); + bitmapinfo_print(contents + pEmr->offBmiSrc); printf("\n"); } printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); @@ -1992,7 +1770,7 @@ printf(" cbBmiMask: %u\n", pEmr->cbBmiMask ); if(pEmr->cbBmiMask){ printf(" Mask bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiMask)); + bitmapinfo_print(contents + pEmr->offBmiMask); printf("\n"); } printf(" offBitsMask: %u\n", pEmr->offBitsMask ); @@ -2003,12 +1781,9 @@ /** \brief Print a pointer to a U_EMRSETDIBITSTODEVICE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETDIBITSTODEVICE_print(char *contents, int recnum, size_t off){ - PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (contents + off); - core5_print("U_EMRSETDIBITSTODEVICE", contents, recnum, off); +void U_EMRSETDIBITSTODEVICE_print(char *contents){ + PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); @@ -2017,7 +1792,7 @@ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); if(pEmr->cbBmiSrc){ printf(" Src bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc)); + bitmapinfo_print(contents + pEmr->offBmiSrc); printf("\n"); } printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); @@ -2031,12 +1806,9 @@ /** \brief Print a pointer to a U_EMR_STRETCHDIBITS record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSTRETCHDIBITS_print(char *contents, int recnum, size_t off){ - PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (contents + off); - core5_print("U_EMRSTRETCHDIBITS", contents, recnum, off); +void U_EMRSTRETCHDIBITS_print(char *contents){ + PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); printf(" Src: "); pointl_print(pEmr->Src); printf("\n"); @@ -2045,7 +1817,7 @@ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc ); if(pEmr->cbBmiSrc){ printf(" Src bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmiSrc)); + bitmapinfo_print(contents + pEmr->offBmiSrc); printf("\n"); } printf(" offBitsSrc: %u\n", pEmr->offBitsSrc ); @@ -2059,12 +1831,9 @@ /** \brief Print a pointer to a U_EMR_EXTCREATEFONTINDIRECTW record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREXTCREATEFONTINDIRECTW_print(char *contents, int recnum, size_t off){ - PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (contents + off); - core5_print("U_EMREXTCREATEFONTINDIRECTW", contents, recnum, off); +void U_EMREXTCREATEFONTINDIRECTW_print(char *contents){ + PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (contents); printf(" ihFont: %u\n",pEmr->ihFont ); printf(" Font: "); if(pEmr->emr.nSize == sizeof(U_EMREXTCREATEFONTINDIRECTW)){ // holds logfont_panose @@ -2080,99 +1849,81 @@ /** \brief Print a pointer to a U_EMR_EXTTEXTOUTA record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREXTTEXTOUTA_print(char *contents, int recnum, size_t off){ - core8_print("U_EMREXTTEXTOUTA", contents, recnum, off, 0); +void U_EMREXTTEXTOUTA_print(char *contents){ + core8_print("U_EMREXTTEXTOUTA", contents, 0); } // U_EMREXTTEXTOUTW 84 /** \brief Print a pointer to a U_EMR_EXTTEXTOUTW record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREXTTEXTOUTW_print(char *contents, int recnum, size_t off){ - core8_print("U_EMREXTTEXTOUTW", contents, recnum, off, 1); +void U_EMREXTTEXTOUTW_print(char *contents){ + core8_print("U_EMREXTTEXTOUTW", contents, 1); } // U_EMRPOLYBEZIER16 85 /** \brief Print a pointer to a U_EMR_POLYBEZIER16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYBEZIER16_print(char *contents, int recnum, size_t off){ - core6_print("U_EMRPOLYBEZIER16", contents, recnum, off); +void U_EMRPOLYBEZIER16_print(char *contents){ + core6_print("U_EMRPOLYBEZIER16", contents); } // U_EMRPOLYGON16 86 /** \brief Print a pointer to a U_EMR_POLYGON16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYGON16_print(char *contents, int recnum, size_t off){ - core6_print("U_EMRPOLYGON16", contents, recnum, off); +void U_EMRPOLYGON16_print(char *contents){ + core6_print("U_EMRPOLYGON16", contents); } // U_EMRPOLYLINE16 87 /** \brief Print a pointer to a U_EMR_POLYLINE16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYLINE16_print(char *contents, int recnum, size_t off){ - core6_print("U_EMRPOLYLINE16", contents, recnum, off); +void U_EMRPOLYLINE16_print(char *contents){ + core6_print("U_EMRPOLYLINE16", contents); } // U_EMRPOLYBEZIERTO16 88 /** \brief Print a pointer to a U_EMR_POLYBEZIERTO16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYBEZIERTO16_print(char *contents, int recnum, size_t off){ - core6_print("U_EMRPOLYBEZIERTO16", contents, recnum, off); +void U_EMRPOLYBEZIERTO16_print(char *contents){ + core6_print("U_EMRPOLYBEZIERTO16", contents); } // U_EMRPOLYLINETO16 89 /** \brief Print a pointer to a U_EMR_POLYLINETO16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYLINETO16_print(char *contents, int recnum, size_t off){ - core6_print("U_EMRPOLYLINETO16", contents, recnum, off); +void U_EMRPOLYLINETO16_print(char *contents){ + core6_print("U_EMRPOLYLINETO16", contents); } // U_EMRPOLYPOLYLINE16 90 /** \brief Print a pointer to a U_EMR_POLYPOLYLINE16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYPOLYLINE16_print(char *contents, int recnum, size_t off){ - core10_print("U_EMRPOLYPOLYLINE16", contents, recnum, off); +void U_EMRPOLYPOLYLINE16_print(char *contents){ + core10_print("U_EMRPOLYPOLYLINE16", contents); } // U_EMRPOLYPOLYGON16 91 /** \brief Print a pointer to a U_EMR_POLYPOLYGON16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYPOLYGON16_print(char *contents, int recnum, size_t off){ - core10_print("U_EMRPOLYPOLYGON16", contents, recnum, off); +void U_EMRPOLYPOLYGON16_print(char *contents){ + core10_print("U_EMRPOLYPOLYGON16", contents); } @@ -2180,13 +1931,10 @@ /** \brief Print a pointer to a U_EMR_POLYDRAW16 record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPOLYDRAW16_print(char *contents, int recnum, size_t off){ +void U_EMRPOLYDRAW16_print(char *contents){ int i; - core5_print("U_EMRPOLYDRAW16", contents, recnum, off); - PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(contents+off); + PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" cpts: %d\n",pEmr->cpts ); printf(" Points: "); @@ -2206,22 +1954,18 @@ /** \brief Print a pointer to a U_EMR_CREATEMONOBRUSH record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCREATEMONOBRUSH_print(char *contents, int recnum, size_t off){ - core12_print("U_EMRCREATEMONOBRUSH", contents, recnum, off); +void U_EMRCREATEMONOBRUSH_print(char *contents){ + core12_print("U_EMRCREATEMONOBRUSH", contents); } // U_EMRCREATEDIBPATTERNBRUSHPT_print 94 /** \brief Print a pointer to a U_EMR_CREATEDIBPATTERNBRUSHPT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCREATEDIBPATTERNBRUSHPT_print(char *contents, int recnum, size_t off){ - core12_print("U_EMRCREATEDIBPATTERNBRUSHPT", contents, recnum, off); +void U_EMRCREATEDIBPATTERNBRUSHPT_print(char *contents){ + core12_print("U_EMRCREATEDIBPATTERNBRUSHPT", contents); } @@ -2229,18 +1973,15 @@ /** \brief Print a pointer to a U_EMR_EXTCREATEPEN record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMREXTCREATEPEN_print(char *contents, int recnum, size_t off){ - core5_print("U_EMREXTCREATEPEN", contents, recnum, off); - PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(contents+off); +void U_EMREXTCREATEPEN_print(char *contents){ + PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(contents); printf(" ihPen: %u\n", pEmr->ihPen ); printf(" offBmi: %u\n", pEmr->offBmi ); printf(" cbBmi: %u\n", pEmr->cbBmi ); if(pEmr->cbBmi){ printf(" bitmap: "); - bitmapinfo_print((PU_BITMAPINFO)(contents + off + pEmr->offBmi)); + bitmapinfo_print(contents + pEmr->offBmi); printf("\n"); } printf(" offBits: %u\n", pEmr->offBits ); @@ -2249,31 +1990,26 @@ } // U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT -#define U_EMRPOLYTEXTOUTA_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTA",A,B,C) +#define U_EMRPOLYTEXTOUTA_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTA",A) // U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT -#define U_EMRPOLYTEXTOUTW_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTW",A,B,C) +#define U_EMRPOLYTEXTOUTW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTW",A) // U_EMRSETICMMODE 98 /** \brief Print a pointer to a U_EMR_SETICMMODE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETICMMODE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETICMMODE", "iMode:", contents, recnum, off); +void U_EMRSETICMMODE_print(char *contents){ + core3_print("U_EMRSETICMMODE", "iMode:", contents); } // U_EMRCREATECOLORSPACE 99 /** \brief Print a pointer to a U_EMR_CREATECOLORSPACE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCREATECOLORSPACE_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRCREATECOLORSPACE", contents, recnum, off); - PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(contents+off); +void U_EMRCREATECOLORSPACE_print(char *contents){ + PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(contents); printf(" ihCS: %u\n", pEmr->ihCS ); printf(" ColorSpace: "); logcolorspacea_print(pEmr->lcs); printf("\n"); } @@ -2282,61 +2018,51 @@ /** \brief Print a pointer to a U_EMR_SETCOLORSPACE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETCOLORSPACE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETCOLORSPACE", "ihCS:", contents, recnum, off); +void U_EMRSETCOLORSPACE_print(char *contents){ + core3_print("U_EMRSETCOLORSPACE", "ihCS:", contents); } // U_EMRDELETECOLORSPACE 101 /** \brief Print a pointer to a U_EMR_DELETECOLORSPACE record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRDELETECOLORSPACE_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRDELETECOLORSPACE", "ihCS:", contents, recnum, off); +void U_EMRDELETECOLORSPACE_print(char *contents){ + core3_print("U_EMRDELETECOLORSPACE", "ihCS:", contents); } // U_EMRGLSRECORD 102 Not implemented -#define U_EMRGLSRECORD_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRGLSRECORD",A,B,C) +#define U_EMRGLSRECORD_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRGLSRECORD",A) // U_EMRGLSBOUNDEDRECORD 103 Not implemented -#define U_EMRGLSBOUNDEDRECORD_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRGLSBOUNDEDRECORD",A,B,C) +#define U_EMRGLSBOUNDEDRECORD_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRGLSBOUNDEDRECORD",A) // U_EMRPIXELFORMAT 104 /** \brief Print a pointer to a U_EMR_PIXELFORMAT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRPIXELFORMAT_print(char *contents, int recnum, size_t off){ - core5_print("U_EMRPIXELFORMAT", contents, recnum, off); - PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(contents+off); +void U_EMRPIXELFORMAT_print(char *contents){ + PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(contents); printf(" Pfd: "); pixelformatdescriptor_print(pEmr->pfd); printf("\n"); } // U_EMRDRAWESCAPE 105 Not implemented -#define U_EMRDRAWESCAPE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRDRAWESCAPE",A,B,C) +#define U_EMRDRAWESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRDRAWESCAPE",A) // U_EMREXTESCAPE 106 Not implemented -#define U_EMREXTESCAPE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMREXTESCAPE",A,B,C) +#define U_EMREXTESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMREXTESCAPE",A) // U_EMRUNDEF107 107 Not implemented -#define U_EMRUNDEF107_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF107",A,B,C) +#define U_EMRUNDEF107_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF107",A) // U_EMRSMALLTEXTOUT 108 /** \brief Print a pointer to a U_EMR_SMALLTEXTOUT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSMALLTEXTOUT_print(char *contents, int recnum, size_t off){ +void U_EMRSMALLTEXTOUT_print(char *contents){ int roff; char *string; - core5_print("U_EMRSMALLTEXTOUT", contents, recnum, off); - PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(contents+off); + PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(contents); printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n"); printf(" cChars: %u\n", pEmr->cChars ); printf(" fuOptions: 0x%8.8X\n", pEmr->fuOptions ); @@ -2345,99 +2071,90 @@ printf(" eyScale: %f\n", pEmr->eyScale ); roff = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields if(!(pEmr->fuOptions & U_ETO_NO_RECT)){ - printf(" rclBounds: "); rectl_print( *(PU_RECTL) (contents + off + roff)); printf("\n"); + printf(" rclBounds: "); rectl_print( *(PU_RECTL) (contents + roff)); printf("\n"); roff += sizeof(U_RECTL); } if(pEmr->fuOptions & U_ETO_SMALL_CHARS){ - printf(" Text8: <%s>\n",contents+off+roff); + printf(" Text8: <%.*s>\n",pEmr->cChars,contents+roff); /* May not be null terminated */ } else { - string = U_Utf16leToUtf8((uint16_t *)(contents+off+roff), pEmr->cChars, NULL); - printf(" Text16: <%s>\n",contents+off+roff); + string = U_Utf16leToUtf8((uint16_t *)(contents+roff), pEmr->cChars, NULL); + printf(" Text16: <%s>\n",contents+roff); free(string); } } // U_EMRFORCEUFIMAPPING 109 Not implemented -#define U_EMRFORCEUFIMAPPING_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRFORCEUFIMAPPING",A,B,C) +#define U_EMRFORCEUFIMAPPING_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRFORCEUFIMAPPING",A) // U_EMRNAMEDESCAPE 110 Not implemented -#define U_EMRNAMEDESCAPE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRNAMEDESCAPE",A,B,C) +#define U_EMRNAMEDESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRNAMEDESCAPE",A) // U_EMRCOLORCORRECTPALETTE 111 Not implemented -#define U_EMRCOLORCORRECTPALETTE_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRCOLORCORRECTPALETTE",A,B,C) +#define U_EMRCOLORCORRECTPALETTE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRCOLORCORRECTPALETTE",A) // U_EMRSETICMPROFILEA 112 Not implemented -#define U_EMRSETICMPROFILEA_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEA",A,B,C) +#define U_EMRSETICMPROFILEA_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEA",A) // U_EMRSETICMPROFILEW 113 Not implemented -#define U_EMRSETICMPROFILEW_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEW",A,B,C) +#define U_EMRSETICMPROFILEW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEW",A) // U_EMRALPHABLEND 114 /** \brief Print a pointer to a U_EMR_ALPHABLEND record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRALPHABLEND_print(char *contents, int recnum, size_t off){ - core13_print("U_EMRALPHABLEND", contents, recnum, off); +void U_EMRALPHABLEND_print(char *contents){ + core13_print("U_EMRALPHABLEND", contents); } // U_EMRSETLAYOUT 115 /** \brief Print a pointer to a U_EMR_SETLAYOUT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRSETLAYOUT_print(char *contents, int recnum, size_t off){ - core3_print("U_EMRSETLAYOUT", "iMode:", contents, recnum, off); +void U_EMRSETLAYOUT_print(char *contents){ + core3_print("U_EMRSETLAYOUT", "iMode:", contents); } // U_EMRTRANSPARENTBLT 116 /** \brief Print a pointer to a U_EMR_TRANSPARENTBLT record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRTRANSPARENTBLT_print(char *contents, int recnum, size_t off){ - core13_print("U_EMRTRANSPARENTBLT", contents, recnum, off); +void U_EMRTRANSPARENTBLT_print(char *contents){ + core13_print("U_EMRTRANSPARENTBLT", contents); } // U_EMRUNDEF117 117 Not implemented -#define U_EMRUNDEF117_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF117",A,B,C) +#define U_EMRUNDEF117_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF117",A) // U_EMRGRADIENTFILL 118 /** \brief Print a pointer to a U_EMR_GRADIENTFILL record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRGRADIENTFILL_print(char *contents, int recnum, size_t off){ +void U_EMRGRADIENTFILL_print(char *contents){ int i; - core5_print("U_EMRGRADIENTFILL", contents, recnum, off); - PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(contents+off); + PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(contents); printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n"); printf(" nTriVert: %u\n", pEmr->nTriVert ); printf(" nGradObj: %u\n", pEmr->nGradObj ); printf(" ulMode: %u\n", pEmr->ulMode ); - off += sizeof(U_EMRGRADIENTFILL); + contents += sizeof(U_EMRGRADIENTFILL); if(pEmr->nTriVert){ printf(" TriVert: "); - for(i=0; inTriVert; i++, off+=sizeof(U_TRIVERTEX)){ - trivertex_print(*(PU_TRIVERTEX)(contents + off)); + for(i=0; inTriVert; i++, contents+=sizeof(U_TRIVERTEX)){ + trivertex_print(*(PU_TRIVERTEX)(contents)); } printf("\n"); } if(pEmr->nGradObj){ printf(" GradObj: "); if( pEmr->ulMode == U_GRADIENT_FILL_TRIANGLE){ - for(i=0; inGradObj; i++, off+=sizeof(U_GRADIENT3)){ - gradient3_print(*(PU_GRADIENT3)(contents + off)); + for(i=0; inGradObj; i++, contents+=sizeof(U_GRADIENT3)){ + gradient3_print(*(PU_GRADIENT3)(contents)); } } else if(pEmr->ulMode == U_GRADIENT_FILL_RECT_H || pEmr->ulMode == U_GRADIENT_FILL_RECT_V){ - for(i=0; inGradObj; i++, off+=sizeof(U_GRADIENT4)){ - gradient4_print(*(PU_GRADIENT4)(contents + off)); + for(i=0; inGradObj; i++, contents+=sizeof(U_GRADIENT4)){ + gradient4_print(*(PU_GRADIENT4)(contents)); } } else { printf("invalid ulMode value!"); } @@ -2446,23 +2163,20 @@ } // U_EMRSETLINKEDUFIS 119 Not implemented -#define U_EMRSETLINKEDUFIS_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETLINKEDUFIS",A,B,C) +#define U_EMRSETLINKEDUFIS_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_SETLINKEDUFIS",A) // U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated) -#define U_EMRSETTEXTJUSTIFICATION_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRSETTEXTJUSTIFICATION",A,B,C) +#define U_EMRSETTEXTJUSTIFICATION_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_SETTEXTJUSTIFICATION",A) // U_EMRCOLORMATCHTOTARGETW 121 Not implemented -#define U_EMRCOLORMATCHTOTARGETW_print(A,B,C) U_EMRNOTIMPLEMENTED_print("U_EMRCOLORMATCHTOTARGETW",A,B,C) +#define U_EMRCOLORMATCHTOTARGETW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_COLORMATCHTOTARGETW",A) // U_EMRCREATECOLORSPACEW 122 /** \brief Print a pointer to a U_EMR_CREATECOLORSPACEW record. \param contents pointer to a buffer holding all EMR records - \param recnum number of this record in contents - \param off offset to this record in contents */ -void U_EMRCREATECOLORSPACEW_print(char *contents, int recnum, size_t off){ +void U_EMRCREATECOLORSPACEW_print(char *contents){ int i; - core5_print("U_EMRCREATECOLORSPACEW", contents, recnum, off); - PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(contents+off); + PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(contents); printf(" ihCS: %u\n", pEmr->ihCS ); printf(" ColorSpace: "); logcolorspacew_print(pEmr->lcs); printf("\n"); printf(" dwFlags: %u\n", pEmr->dwFlags ); @@ -2478,141 +2192,153 @@ /** \brief Print any record in an emf - \returns 1 for a normal record, 0 for EMREOF + \returns record length for a normal record, 0 for EMREOF, -1 for a bad record \param contents pointer to a buffer holding all EMR records + \param blimit pointer to the byte after the last byte in the buffer holding all EMR records \param recnum number of this record in contents \param off offset to this record in contents */ -int U_emf_onerec_print(char *contents, int recnum, size_t off){ +int U_emf_onerec_print(char *contents, char *blimit, int recnum, size_t off){ PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off); - int regular=1; + int size; + + printf("%-30srecord:%5d type:%3d offset:%8d size:%8d\n",U_emr_names(lpEMFR->iType),recnum,lpEMFR->iType,(int) off,lpEMFR->nSize); + size = lpEMFR->nSize; + contents += off; + + /* Check that the record size is OK, abort if not. + Pointer math might wrap, so check both sides of the range */ + if(size < sizeof(U_EMR) || + contents + size - 1 >= blimit || + contents + size - 1 < contents)return(-1); + switch (lpEMFR->iType) { - case U_EMR_HEADER: U_EMRHEADER_print(contents, recnum, off); break; - case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_print(contents, recnum, off); break; - case U_EMR_POLYGON: U_EMRPOLYGON_print(contents, recnum, off); break; - case U_EMR_POLYLINE: U_EMRPOLYLINE_print(contents, recnum, off); break; - case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_print(contents, recnum, off); break; - case U_EMR_POLYLINETO: U_EMRPOLYLINETO_print(contents, recnum, off); break; - case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_print(contents, recnum, off); break; - case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_print(contents, recnum, off); break; - case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_print(contents, recnum, off); break; - case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_print(contents, recnum, off); break; - case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_print(contents, recnum, off); break; - case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_print(contents, recnum, off); break; - case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_print(contents, recnum, off); break; - case U_EMR_EOF: U_EMREOF_print(contents, recnum, off); regular=0; break; - case U_EMR_SETPIXELV: U_EMRSETPIXELV_print(contents, recnum, off); break; - case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_print(contents, recnum, off); break; - case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_print(contents, recnum, off); break; - case U_EMR_SETBKMODE: U_EMRSETBKMODE_print(contents, recnum, off); break; - case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_print(contents, recnum, off); break; - case U_EMR_SETROP2: U_EMRSETROP2_print(contents, recnum, off); break; - case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_print(contents, recnum, off); break; - case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_print(contents, recnum, off); break; - case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_print(contents, recnum, off); break; - case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_print(contents, recnum, off); break; - case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_print(contents, recnum, off); break; - case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_print(contents, recnum, off); break; - case U_EMR_MOVETOEX: U_EMRMOVETOEX_print(contents, recnum, off); break; - case U_EMR_SETMETARGN: U_EMRSETMETARGN_print(contents, recnum, off); break; - case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_print(contents, recnum, off); break; - case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_print(contents, recnum, off); break; - case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_print(contents, recnum, off); break; - case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_print(contents, recnum, off); break; - case U_EMR_SAVEDC: U_EMRSAVEDC_print(contents, recnum, off); break; - case U_EMR_RESTOREDC: U_EMRRESTOREDC_print(contents, recnum, off); break; - case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_print(contents, recnum, off); break; - case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_print(contents, recnum, off); break; - case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_print(contents, recnum, off); break; - case U_EMR_CREATEPEN: U_EMRCREATEPEN_print(contents, recnum, off); break; - case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_print(contents, recnum, off); break; - case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_print(contents, recnum, off); break; - case U_EMR_ANGLEARC: U_EMRANGLEARC_print(contents, recnum, off); break; - case U_EMR_ELLIPSE: U_EMRELLIPSE_print(contents, recnum, off); break; - case U_EMR_RECTANGLE: U_EMRRECTANGLE_print(contents, recnum, off); break; - case U_EMR_ROUNDRECT: U_EMRROUNDRECT_print(contents, recnum, off); break; - case U_EMR_ARC: U_EMRARC_print(contents, recnum, off); break; - case U_EMR_CHORD: U_EMRCHORD_print(contents, recnum, off); break; - case U_EMR_PIE: U_EMRPIE_print(contents, recnum, off); break; - case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_print(contents, recnum, off); break; - case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_print(contents, recnum, off); break; - case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_print(contents, recnum, off); break; - case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_print(contents, recnum, off); break; - case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_print(contents, recnum, off); break; - case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_print(contents, recnum, off); break; - case U_EMR_LINETO: U_EMRLINETO_print(contents, recnum, off); break; - case U_EMR_ARCTO: U_EMRARCTO_print(contents, recnum, off); break; - case U_EMR_POLYDRAW: U_EMRPOLYDRAW_print(contents, recnum, off); break; - case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_print(contents, recnum, off); break; - case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_print(contents, recnum, off); break; - case U_EMR_BEGINPATH: U_EMRBEGINPATH_print(contents, recnum, off); break; - case U_EMR_ENDPATH: U_EMRENDPATH_print(contents, recnum, off); break; - case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_print(contents, recnum, off); break; - case U_EMR_FILLPATH: U_EMRFILLPATH_print(contents, recnum, off); break; - case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_print(contents, recnum, off); break; - case U_EMR_STROKEPATH: U_EMRSTROKEPATH_print(contents, recnum, off); break; - case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_print(contents, recnum, off); break; - case U_EMR_WIDENPATH: U_EMRWIDENPATH_print(contents, recnum, off); break; - case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_print(contents, recnum, off); break; - case U_EMR_ABORTPATH: U_EMRABORTPATH_print(contents, recnum, off); break; - case U_EMR_UNDEF69: U_EMRUNDEF69_print(contents, recnum, off); break; - case U_EMR_COMMENT: U_EMRCOMMENT_print(contents, recnum, off); break; - case U_EMR_FILLRGN: U_EMRFILLRGN_print(contents, recnum, off); break; - case U_EMR_FRAMERGN: U_EMRFRAMERGN_print(contents, recnum, off); break; - case U_EMR_INVERTRGN: U_EMRINVERTRGN_print(contents, recnum, off); break; - case U_EMR_PAINTRGN: U_EMRPAINTRGN_print(contents, recnum, off); break; - case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_print(contents, recnum, off); break; - case U_EMR_BITBLT: U_EMRBITBLT_print(contents, recnum, off); break; - case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_print(contents, recnum, off); break; - case U_EMR_MASKBLT: U_EMRMASKBLT_print(contents, recnum, off); break; - case U_EMR_PLGBLT: U_EMRPLGBLT_print(contents, recnum, off); break; - case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_print(contents, recnum, off); break; - case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_print(contents, recnum, off); break; - case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_print(contents, recnum, off); break; - case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_print(contents, recnum, off); break; - case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_print(contents, recnum, off); break; - case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_print(contents, recnum, off); break; - case U_EMR_POLYGON16: U_EMRPOLYGON16_print(contents, recnum, off); break; - case U_EMR_POLYLINE16: U_EMRPOLYLINE16_print(contents, recnum, off); break; - case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_print(contents, recnum, off); break; - case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_print(contents, recnum, off); break; - case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_print(contents, recnum, off); break; - case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_print(contents, recnum, off); break; - case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_print(contents, recnum, off); break; - case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_print(contents, recnum, off); break; - case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_print(contents, recnum, off); break; - case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_print(contents, recnum, off); break; - case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_print(contents, recnum, off); break; - case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_print(contents, recnum, off); break; - case U_EMR_SETICMMODE: U_EMRSETICMMODE_print(contents, recnum, off); break; - case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_print(contents, recnum, off); break; - case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_print(contents, recnum, off); break; - case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_print(contents, recnum, off); break; - case U_EMR_GLSRECORD: U_EMRGLSRECORD_print(contents, recnum, off); break; - case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_print(contents, recnum, off); break; - case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_print(contents, recnum, off); break; - case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_print(contents, recnum, off); break; - case U_EMR_EXTESCAPE: U_EMREXTESCAPE_print(contents, recnum, off); break; - case U_EMR_UNDEF107: U_EMRUNDEF107_print(contents, recnum, off); break; - case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_print(contents, recnum, off); break; - case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_print(contents, recnum, off); break; - case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_print(contents, recnum, off); break; - case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_print(contents, recnum, off); break; - case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_print(contents, recnum, off); break; - case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_print(contents, recnum, off); break; - case U_EMR_ALPHABLEND: U_EMRALPHABLEND_print(contents, recnum, off); break; - case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_print(contents, recnum, off); break; - case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_print(contents, recnum, off); break; - case U_EMR_UNDEF117: U_EMRUNDEF117_print(contents, recnum, off); break; - case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_print(contents, recnum, off); break; - case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_print(contents, recnum, off); break; - case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_print(contents, recnum, off); break; - case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_print(contents, recnum, off); break; - case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_print(contents, recnum, off); break; - default: U_EMRNOTIMPLEMENTED_print("?",contents, recnum, off); break; + case U_EMR_HEADER: U_EMRHEADER_print(contents); break; + case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_print(contents); break; + case U_EMR_POLYGON: U_EMRPOLYGON_print(contents); break; + case U_EMR_POLYLINE: U_EMRPOLYLINE_print(contents); break; + case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_print(contents); break; + case U_EMR_POLYLINETO: U_EMRPOLYLINETO_print(contents); break; + case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_print(contents); break; + case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_print(contents); break; + case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_print(contents); break; + case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_print(contents); break; + case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_print(contents); break; + case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_print(contents); break; + case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_print(contents); break; + case U_EMR_EOF: U_EMREOF_print(contents); size=0; break; + case U_EMR_SETPIXELV: U_EMRSETPIXELV_print(contents); break; + case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_print(contents); break; + case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_print(contents); break; + case U_EMR_SETBKMODE: U_EMRSETBKMODE_print(contents); break; + case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_print(contents); break; + case U_EMR_SETROP2: U_EMRSETROP2_print(contents); break; + case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_print(contents); break; + case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_print(contents); break; + case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_print(contents); break; + case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_print(contents); break; + case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_print(contents); break; + case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_print(contents); break; + case U_EMR_MOVETOEX: U_EMRMOVETOEX_print(contents); break; + case U_EMR_SETMETARGN: U_EMRSETMETARGN_print(contents); break; + case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_print(contents); break; + case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_print(contents); break; + case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_print(contents); break; + case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_print(contents); break; + case U_EMR_SAVEDC: U_EMRSAVEDC_print(contents); break; + case U_EMR_RESTOREDC: U_EMRRESTOREDC_print(contents); break; + case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_print(contents); break; + case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_print(contents); break; + case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_print(contents); break; + case U_EMR_CREATEPEN: U_EMRCREATEPEN_print(contents); break; + case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_print(contents); break; + case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_print(contents); break; + case U_EMR_ANGLEARC: U_EMRANGLEARC_print(contents); break; + case U_EMR_ELLIPSE: U_EMRELLIPSE_print(contents); break; + case U_EMR_RECTANGLE: U_EMRRECTANGLE_print(contents); break; + case U_EMR_ROUNDRECT: U_EMRROUNDRECT_print(contents); break; + case U_EMR_ARC: U_EMRARC_print(contents); break; + case U_EMR_CHORD: U_EMRCHORD_print(contents); break; + case U_EMR_PIE: U_EMRPIE_print(contents); break; + case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_print(contents); break; + case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_print(contents); break; + case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_print(contents); break; + case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_print(contents); break; + case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_print(contents); break; + case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_print(contents); break; + case U_EMR_LINETO: U_EMRLINETO_print(contents); break; + case U_EMR_ARCTO: U_EMRARCTO_print(contents); break; + case U_EMR_POLYDRAW: U_EMRPOLYDRAW_print(contents); break; + case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_print(contents); break; + case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_print(contents); break; + case U_EMR_BEGINPATH: U_EMRBEGINPATH_print(contents); break; + case U_EMR_ENDPATH: U_EMRENDPATH_print(contents); break; + case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_print(contents); break; + case U_EMR_FILLPATH: U_EMRFILLPATH_print(contents); break; + case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_print(contents); break; + case U_EMR_STROKEPATH: U_EMRSTROKEPATH_print(contents); break; + case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_print(contents); break; + case U_EMR_WIDENPATH: U_EMRWIDENPATH_print(contents); break; + case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_print(contents); break; + case U_EMR_ABORTPATH: U_EMRABORTPATH_print(contents); break; + case U_EMR_UNDEF69: U_EMRUNDEF69_print(contents); break; + case U_EMR_COMMENT: U_EMRCOMMENT_print(contents); break; + case U_EMR_FILLRGN: U_EMRFILLRGN_print(contents); break; + case U_EMR_FRAMERGN: U_EMRFRAMERGN_print(contents); break; + case U_EMR_INVERTRGN: U_EMRINVERTRGN_print(contents); break; + case U_EMR_PAINTRGN: U_EMRPAINTRGN_print(contents); break; + case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_print(contents); break; + case U_EMR_BITBLT: U_EMRBITBLT_print(contents); break; + case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_print(contents); break; + case U_EMR_MASKBLT: U_EMRMASKBLT_print(contents); break; + case U_EMR_PLGBLT: U_EMRPLGBLT_print(contents); break; + case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_print(contents); break; + case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_print(contents); break; + case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_print(contents); break; + case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_print(contents); break; + case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_print(contents); break; + case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_print(contents); break; + case U_EMR_POLYGON16: U_EMRPOLYGON16_print(contents); break; + case U_EMR_POLYLINE16: U_EMRPOLYLINE16_print(contents); break; + case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_print(contents); break; + case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_print(contents); break; + case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_print(contents); break; + case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_print(contents); break; + case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_print(contents); break; + case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_print(contents); break; + case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_print(contents); break; + case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_print(contents); break; + case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_print(contents); break; + case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_print(contents); break; + case U_EMR_SETICMMODE: U_EMRSETICMMODE_print(contents); break; + case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_print(contents); break; + case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_print(contents); break; + case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_print(contents); break; + case U_EMR_GLSRECORD: U_EMRGLSRECORD_print(contents); break; + case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_print(contents); break; + case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_print(contents); break; + case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_print(contents); break; + case U_EMR_EXTESCAPE: U_EMREXTESCAPE_print(contents); break; + case U_EMR_UNDEF107: U_EMRUNDEF107_print(contents); break; + case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_print(contents); break; + case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_print(contents); break; + case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_print(contents); break; + case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_print(contents); break; + case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_print(contents); break; + case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_print(contents); break; + case U_EMR_ALPHABLEND: U_EMRALPHABLEND_print(contents); break; + case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_print(contents); break; + case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_print(contents); break; + case U_EMR_UNDEF117: U_EMRUNDEF117_print(contents); break; + case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_print(contents); break; + case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_print(contents); break; + case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_print(contents); break; + case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_print(contents); break; + case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_print(contents); break; + default: U_EMRNOTIMPLEMENTED_print("?",contents); break; } //end of switch - return(regular); + return(size); } === modified file 'src/extension/internal/uemf_print.h' --- src/extension/internal/uemf_print.h 2012-09-23 17:19:33 +0000 +++ src/extension/internal/uemf_print.h 2013-01-24 22:25:55 +0000 @@ -4,11 +4,11 @@ /* File: uemf_print.h -Version: 0.0.3 -Date: 24-JUL-2012 +Version: 0.0.4 +Date: 13-JAN-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifndef _UEMF_PRINT_ @@ -18,7 +18,42 @@ extern "C" { #endif -// prototypes +/* prototypes for objects used in EMR records */ +void hexbytes_print(uint8_t *buf,unsigned int num); +void colorref_print(U_COLORREF color); +void rgbquad_print(U_RGBQUAD color); +void rectl_print(U_RECTL rect); +void sizel_print(U_SIZEL sz); +void pointl_print(U_POINTL pt); +void point16_print(U_POINT16 pt); +void lcs_gamma_print(U_LCS_GAMMA lg); +void lcs_gammargb_print(U_LCS_GAMMARGB lgr); +void trivertex_print(U_TRIVERTEX tv); +void gradient3_print(U_GRADIENT3 g3); +void gradient4_print(U_GRADIENT4 g4); +void logbrush_print(U_LOGBRUSH lb); +void xform_print(U_XFORM xform); +void ciexyz_print(U_CIEXYZ ciexyz); +void ciexyztriple_print(U_CIEXYZTRIPLE cie3); +void logcolorspacea_print(U_LOGCOLORSPACEA lcsa); +void logcolorspacew_print(U_LOGCOLORSPACEW lcsa); +void panose_print(U_PANOSE panose); +void logfont_print(U_LOGFONT lf); +void logfont_panose_print(U_LOGFONT_PANOSE lfp); +void bitmapinfoheader_print(char *Bmih); +void bitmapinfo_print(char *Bmi); +void blend_print(U_BLEND blend); +void extlogpen_print(PU_EXTLOGPEN elp); +void logpen_print(U_LOGPEN lp); +void logpltntry_print(U_LOGPLTNTRY lpny); +void logpalette_print(PU_LOGPALETTE lp); +void rgndataheader_print(U_RGNDATAHEADER rdh); +void rgndata_print(PU_RGNDATA rd); +void coloradjustment_print(U_COLORADJUSTMENT ca); +void pixelformatdescriptor_print(U_PIXELFORMATDESCRIPTOR pfd); +void emrtext_print(char *emt, char *record, int type); + +/* prototypes for EMR records */ void U_EMRNOTIMPLEMENTED_print(char *name, char *contents, int recnum, int off); void U_EMRHEADER_print(char *contents, int recnum, int off); void U_EMRPOLYBEZIER_print(char *contents, int recnum, int off); @@ -125,7 +160,7 @@ void U_EMRTRANSPARENTBLT_print(char *contents, int recnum, int off); void U_EMRGRADIENTFILL_print(char *contents, int recnum, int off); void U_EMRCREATECOLORSPACEW_print(char *contents, int recnum, int off); -int U_emf_onerec_print(char *contents, int recnum, int off); +int U_emf_onerec_print(char *contents, char *blimit, int recnum, int off); #ifdef __cplusplus } === modified file 'src/extension/internal/uemf_utf.c' --- src/extension/internal/uemf_utf.c 2012-12-13 04:10:54 +0000 +++ src/extension/internal/uemf_utf.c 2013-01-24 23:27:50 +0000 @@ -10,11 +10,11 @@ /* File: uemf_utf.c -Version: 0.0.1 -Date: 04-DEC-2012 +Version: 0.0.3 +Date: 24-JAN-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2012 David Mathog and California Institute of Technology (Caltech) +Copyright: 2013 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -32,9 +32,14 @@ #include // for U_ROUND() #include "uemf_utf.h" +/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed +to be used in end user code. */ + +void U_swap2(void *ul, unsigned int count); + /* ******************************************************************************************** */ -//! @cond +/** \cond */ /* iconv() has a funny cast on some older systems, on most recent ones it is just char **. This tries to work around the issue. If you build this on another funky system this code may need to be modified, or define ICONV_CAST @@ -46,7 +51,7 @@ #if !defined(ICONV_CAST) #define ICONV_CAST (char **) #endif //ICONV_CAST -//! @endcond +/** \endcond */ /* ********************************************************************************************** These functions are used for development and debugging and should be be includied in production code. @@ -405,6 +410,69 @@ } /** + \brief Convert a UTF8 string to a Latin1 string. + \return pointer to new string or NULL if it fails + \param src Latin1 string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator + + + WMF uses latin1, others UTF-8, only some utf-8 can be converted to latin1. + +*/ +char *U_Utf8ToLatin1( + const char *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + size_t srclen,dstlen,status; + if(max){ srclen = max; } + else { srclen = strlen(src)+1; } // include terminator, length in BYTES + dstlen = (1 + srclen); // This should always work but might waste some space + dst2 = dst = calloc(dstlen,1); + if(!dst)return(NULL); + iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-8"); // translate what can be, fill in with something close for the rest + if ( conv == (iconv_t) -1)return(NULL); + status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1)return(NULL); + if(len)*len=strlen(dst2); + return((uint32_t *) dst2); +} + +/** + \brief Convert a Latin1 string to a UTF8 string. + \return pointer to new string or NULL if it fails + \param src Latin1 string to convert + \param max number of characters to convert, if 0, until terminator + \param len number of characters in new string, NOT including terminator + + + WMF uses latin1, others UTF-8, all Latin1 should be able to convert to utf-8. + +*/ +char *U_Latin1ToUtf8( + const char *src, + size_t max, + size_t *len + ){ + char *dst,*dst2; + size_t srclen,dstlen,status; + if(max){ srclen = max; } + else { srclen = strlen(src)+1; } // include terminator, will waste some space + dst2 = dst = calloc(dstlen,1); + if(!dst)return(NULL); + iconv_t conv = iconv_open("UTF-8", "LATIN1"); // everything should translate + if ( conv == (iconv_t) -1)return(NULL); + status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen); + iconv_close(conv); + if(status == (size_t) -1)return(NULL); + if(len)*len=strlen(dst2); + return((uint32_t *) dst2); +} + +/** \brief Single character replacement in a UTF-16LE string. Used solely for the Description field which contains === modified file 'src/extension/internal/uemf_utf.h' --- src/extension/internal/uemf_utf.h 2012-12-13 04:10:54 +0000 +++ src/extension/internal/uemf_utf.h 2013-01-24 23:27:23 +0000 @@ -21,6 +21,7 @@ #include #include +#include "uemf_endian.h" void wchar8show(const char *src); void wchar16show(const uint16_t *src); @@ -38,6 +39,8 @@ char *U_Utf32leToUtf8( const uint32_t *src, size_t max, size_t *len ); uint32_t *U_Utf16leToUtf32le( const uint16_t *src, size_t max, size_t *len ); char *U_Utf16leToUtf8( const uint16_t *src, size_t max, size_t *len ); +char *U_Utf8ToLatin1( const char *src, size_t max, size_t *len ); +char *U_Latin1ToUtf8( const char *src, size_t max, size_t *len ); uint16_t U_Utf16le(const uint16_t src); int U_Utf16leEdit( uint16_t *src, uint16_t find, uint16_t replace ); char *U_strdup(const char *s);