summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Mathog <>2012-10-08 23:22:53 +0000
committer~suv <suv-sf@users.sourceforge.net>2012-10-08 23:22:53 +0000
commit3e19ae183993f58ae665839f556a02cde4814396 (patch)
treefbf4bc9259e1c3ee71df9984d0e30817ba776983 /src
parentmerge from trunk (r11760) (diff)
downloadinkscape-3e19ae183993f58ae665839f556a02cde4814396.tar.gz
inkscape-3e19ae183993f58ae665839f556a02cde4814396.zip
changes_2012_10_08a.patch:
- image import from EMR_BITBLT, EMR_STRETCHBLT, and EMR_MASKBLT records - sets a default font name (Arial) (for EMFs which specify for a font) - drops text that starts with any of the characters 0x0-0x1F (bzr r11668.1.26)
Diffstat (limited to 'src')
-rw-r--r--src/extension/internal/emf-inout.cpp208
-rw-r--r--src/extension/internal/uemf.h39
-rw-r--r--src/extension/internal/uemf_print.c51
3 files changed, 209 insertions, 89 deletions
diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp
index 550f05cf3..e1b20ee23 100644
--- a/src/extension/internal/emf-inout.cpp
+++ b/src/extension/internal/emf-inout.cpp
@@ -1310,9 +1310,18 @@ select_font(PEMF_CALLBACK_DATA d, int index)
d->dc[d->level].style.font_style.value = (pEmr->elfw.elfLogFont.lfItalic ? SP_CSS_FONT_STYLE_ITALIC : SP_CSS_FONT_STYLE_NORMAL);
d->dc[d->level].style.text_decoration.underline = pEmr->elfw.elfLogFont.lfUnderline;
d->dc[d->level].style.text_decoration.line_through = pEmr->elfw.elfLogFont.lfStrikeOut;
- if (d->dc[d->level].font_name){ free(d->dc[d->level].font_name); }
- d->dc[d->level].font_name =
- U_Utf16leToUtf8((uint16_t *) (pEmr->elfw.elfLogFont.lfFaceName), U_LF_FACESIZE, NULL);
+ // malformed EMF with empty filename may exist, ignore font change if encountered
+ char *ctmp = U_Utf16leToUtf8((uint16_t *) (pEmr->elfw.elfLogFont.lfFaceName), U_LF_FACESIZE, NULL);
+ if(ctmp){
+ if (d->dc[d->level].font_name){ free(d->dc[d->level].font_name); }
+ if(*ctmp){
+ d->dc[d->level].font_name = ctmp;
+ }
+ else { // Malformed EMF might specify an empty font name
+ free(ctmp);
+ d->dc[d->level].font_name = strdup("Arial"); // Default font, EMF spec says device can pick whatever it wants
+ }
+ }
d->dc[d->level].style.baseline_shift.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10; // use baseline_shift instead of text_transform to avoid overflow
}
@@ -1355,6 +1364,76 @@ uint32_t *unknown_chars(size_t count){
return res;
}
+void common_image_extraction(PEMF_CALLBACK_DATA d, void *pEmr, double l, double t, double r, double b,
+ uint32_t iUsage, uint32_t offBits, uint32_t cbBits, uint32_t offBmi, uint32_t cbBmi){
+ SVGOStringStream tmp_image;
+ tmp_image << " y=\"" << t << "\"\n x=\"" << l <<"\"\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 *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(!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)
+ {
+ toPNG( // Get the image from the RGBA px into mempng
+ &mempng,
+ width, height,
+ rgba_px);
+ free(rgba_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=\"" << b-t+1 << "\"\n width=\"" << r-l+1 << "\"\n";
+
+ *(d->outsvg) += "\n\t <image\n";
+ *(d->outsvg) += tmp_image.str().c_str();
+ *(d->outsvg) += "/> \n";
+ *(d->path) = "";
+}
/**
\fn myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DATA lpData)
@@ -2461,14 +2540,14 @@ std::cout << "BEFORE DRAW"
dbg_str << "<!-- U_EMR_BITBLT -->\n";
PU_EMRBITBLT pEmr = (PU_EMRBITBLT) lpEMFR;
+ double l = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double t = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double r = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
+ double b = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
// 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
- double l = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y);
- double t = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y);
- double r = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
- double b = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
SVGOStringStream tmp_rectangle;
tmp_rectangle << "\n\tM " << l << " " << t << " ";
@@ -2483,10 +2562,42 @@ std::cout << "BEFORE DRAW"
tmp_path << tmp_rectangle.str().c_str();
}
+ else {
+ common_image_extraction(d,pEmr,l,t,r,b,
+ pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc);
+ }
+ break;
+ }
+ case U_EMR_STRETCHBLT:
+ {
+ dbg_str << "<!-- U_EMR_STRETCHBLT -->\n";
+ PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) lpEMFR;
+ // Always grab image, ignore modes.
+ if (pEmr->cbBmiSrc) {
+ double l = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double t = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double r = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
+ double b = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
+ common_image_extraction(d,pEmr,l,t,r,b,
+ pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc);
+ }
+ break;
+ }
+ case U_EMR_MASKBLT:
+ {
+ dbg_str << "<!-- U_EMR_MASKBLT -->\n";
+ PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) lpEMFR;
+ // Always grab image, ignore masks and modes.
+ if (pEmr->cbBmiSrc) {
+ double l = pix_to_x_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double t = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y);
+ double r = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
+ double b = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y);
+ common_image_extraction(d,pEmr,l,t,r,b,
+ pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc);
+ }
break;
}
- case U_EMR_STRETCHBLT: dbg_str << "<!-- U_EMR_STRETCHBLT -->\n"; break;
- case U_EMR_MASKBLT: dbg_str << "<!-- U_EMR_MASKBLT -->\n"; break;
case U_EMR_PLGBLT: dbg_str << "<!-- U_EMR_PLGBLT -->\n"; break;
case U_EMR_SETDIBITSTODEVICE: dbg_str << "<!-- U_EMR_SETDIBITSTODEVICE -->\n"; break;
case U_EMR_STRETCHDIBITS:
@@ -2502,73 +2613,8 @@ std::cout << "BEFORE DRAW"
double t = pix_to_y_point( d, pEmr->Dest.x, pEmr->Dest.y );
double r = pix_to_x_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y );
double b = pix_to_y_point( d, pEmr->Dest.x + pEmr->cDest.x, pEmr->Dest.y + pEmr->cDest.y );
- SVGOStringStream tmp_image;
- tmp_image << " y=\"" << t << "\"\n x=\"" << l <<"\"\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 *px=NULL; // DIB pixels
- uint32_t width, height, colortype, numCt, invert;
- PU_RGBQUAD ct = NULL;
- if(!pEmr->cbBitsSrc ||
- !pEmr->cbBmiSrc ||
- (pEmr->iUsageSrc != U_DIB_RGB_COLORS) ||
- !get_DIB_params( // this returns pointers and values, but allocates no memory
- pEmr,
- pEmr->offBitsSrc,
- pEmr->offBmiSrc,
- &px,
- &ct,
- &numCt,
- &width,
- &height,
- &colortype,
- &invert
- )){
-
- if(!DIB_to_RGBA(
- px, // DIB pixel array
- ct, // DIB color table
- numCt, // DIB color table number of entries
- &rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free.
- width, // Width of pixel array
- 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)
- {
- toPNG( // Get the image from the RGBA px into mempng
- &mempng,
- width, height,
- rgba_px);
- free(rgba_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=\"" << b-t+1 << "\"\n width=\"" << r-l+1 << "\"\n";
-
- *(d->outsvg) += "\n\t <image\n";
- *(d->outsvg) += tmp_image.str().c_str();
- *(d->outsvg) += "/> \n";
- *(d->path) = "";
+ common_image_extraction(d,pEmr,l,t,r,b,
+ pEmr->iUsageSrc, pEmr->offBitsSrc, pEmr->cbBitsSrc, pEmr->offBmiSrc, pEmr->cbBmiSrc);
dbg_str << "<!-- U_EMR_STRETCHDIBITS -->\n";
break;
@@ -2661,6 +2707,11 @@ std::cout << "BEFORE DRAW"
char *ansi_text;
ansi_text = (char *) U_Utf32leToUtf8((uint32_t *)dup_wt, 0, NULL);
free(dup_wt);
+ // Empty string or starts with an invalid escape/control sequence, which is bogus text. Throw it out before g_markup_escape_text can make things worse
+ if(*ansi_text <= 0x1F){
+ free(ansi_text);
+ ansi_text=NULL;
+ }
if (ansi_text) {
// gchar *p = ansi_text;
@@ -2980,7 +3031,7 @@ std::cout << "BEFORE DRAW"
} //end of while
// When testing, uncomment the following to show the final SVG derived from the EMF
-// std::cout << *(d->outsvg) << std::endl;
+//std::cout << *(d->outsvg) << std::endl;
(void) emr_properties(U_EMR_INVALID); // force the release of the lookup table memory, returned value is irrelevant
return 1;
@@ -3035,7 +3086,8 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
d.dc[0].worldTransform.eM22 = 1.0;
d.dc[0].worldTransform.eDx = 0.0;
d.dc[0].worldTransform.eDy = 0.0;
-
+ d.dc[0].font_name = strdup("Arial"); // Default font, EMF spec says device can pick whatever it wants
+
if (uri == NULL) {
return NULL;
}
diff --git a/src/extension/internal/uemf.h b/src/extension/internal/uemf.h
index 7a025a67b..30ed611d6 100644
--- a/src/extension/internal/uemf.h
+++ b/src/extension/internal/uemf.h
@@ -309,11 +309,20 @@ extern "C" {
#define U_DIB_PAL_COLORS 1
/** @} */
-/** \defgroup U_EMR_COMMENT_PublicCommentIdentifier_Qualifiers EmrComment Enumeration
- For U_EMR_COMMENT_* PublicCommentIdentifier fields
+/** \defgroup U_EMRCOMMENT_* cIdent Qualifiers
+ For U_EMRCOMMENT_* cIdent fields
+ @{
+*/
+#define U_EMR_COMMENT_PUBLIC 0x43494447
+#define U_EMR_COMMENT_SPOOL 0x00000000
+#define U_EMR_COMMENT_SPOOLFONTDEF 0x544F4E46
+#define U_EMR_COMMENT_EMFPLUSRECORD 0x2B464D45
+/** @} */
+
+/** \defgroup U_EMR_COMMENT_PUBLIC, AKA EMRComment Enumeration
+ For U_EMRCOMMENT_PUBLI pcIdent fields
@{
*/
-#define U_EMR_COMMENT_IDENTIFIER 0x43494447
#define U_EMR_COMMENT_WINDOWS_METAFILE 0x80000001
#define U_EMR_COMMENT_BEGINGROUP 0x00000002
#define U_EMR_COMMENT_ENDGROUP 0x00000003
@@ -2169,6 +2178,30 @@ typedef struct {
uint8_t Data[1]; //!< Comment (any binary data, interpretation is program specific)
} U_EMRCOMMENT, *PU_EMRCOMMENT; //!< AKA GDICOMMENT
+/* variant comment types */
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Number of bytes in comment
+ uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_EMFPLUSRECORD
+ uint8_t Data[1]; //!< EMF Plus record
+} U_EMRCOMMENT_EMFPLUS, *PU_EMRCOMMENT_EMFPLUS; //!< EMF Plus comment
+
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Number of bytes in comment
+ uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_SPOOL
+ uint32_t esrIdent; //!< EMFSpoolRecordIdentifier, may be U_EMR_COMMENT_SPOOLFONTDEF
+ uint8_t Data[1]; //!< EMF Spool records
+} U_EMRCOMMENT_SPOOL, *PU_EMRCOMMENT_SPOOL; //!< EMF Spool comment
+
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Number of bytes in comment
+ uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_PUBLIC
+ uint32_t pcIdent; //!< Public Comment Identifier, from EMRComment Enumeration
+ uint8_t Data[1]; //!< Public comment data
+} U_EMRCOMMENT_PUBLIC, *PU_EMRCOMMENT_PUBLIC; //!< EMF Public comment
+
/* Index 71 */
typedef struct {
U_EMR emr; //!< U_EMR
diff --git a/src/extension/internal/uemf_print.c b/src/extension/internal/uemf_print.c
index ccfbc9008..d877c01db 100644
--- a/src/extension/internal/uemf_print.c
+++ b/src/extension/internal/uemf_print.c
@@ -4,8 +4,8 @@
/*
File: uemf_print.c
-Version: 0.0.4
-Date: 25-JUL-2012
+Version: 0.0.9
+Date: 19-SEP-2012
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
@@ -294,6 +294,7 @@ void logfont_panose_print(
printf("elfLogFont:"); logfont_print(lfp.elfLogFont);
string = U_Utf16leToUtf8(lfp.elfFullName, U_LF_FULLFACESIZE, NULL);
printf("elfFullName:%s ", string );
+ free(string);
string = U_Utf16leToUtf8(lfp.elfStyle, U_LF_FACESIZE, NULL);
printf("elfStyle:%s ", string );
free(string);
@@ -543,7 +544,7 @@ void pixelformatdescriptor_print(
/**
\brief Print a Pointer to a U_EMRTEXT record
\param emt Pointer to a U_EMRTEXT record
- \param record Pointer to the start of the record which contains this U_EMRTEXT
+ \param record Pointer to the start of the record which contains this U_ERMTEXT
\param type 0 for 8 bit character, anything else for 16
*/
void emrtext_print(
@@ -1710,16 +1711,50 @@ void U_EMRABORTPATH_print(char *contents, int recnum, size_t off){
*/
void U_EMRCOMMENT_print(char *contents, int recnum, size_t off){
char *string;
+ char *src;
+ uint32_t cIdent,cbData;
core5_print("U_EMRCOMMENT", contents, recnum, off);
PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(contents+off);
- printf(" cbData: %d\n",pEmr->cbData );
- if(pEmr->cbData){ // The data may not be printable, but try it just in case
- string = malloc(pEmr->cbData + 1);
- (void)strncpy(string, (char *)&(pEmr->Data), pEmr->cbData);
- string[pEmr->cbData] = '\0'; // it might not be terminated - it might not even be text!
+
+ /* There are several different types of comments */
+
+ cbData = pEmr->cbData;
+ printf(" cbData: %d\n",cbData );
+ src = (char *)&(pEmr->Data); // default
+ if(cbData >= 4){
+ cIdent = *(uint32_t *)&(pEmr->Data);
+ if( cIdent == U_EMR_COMMENT_PUBLIC ){
+ printf(" cIdent: Public\n");
+ PU_EMRCOMMENT_PUBLIC pEmrp = (PU_EMRCOMMENT_PUBLIC) pEmr;
+ printf(" pcIdent: %8.8x\n",pEmrp->pcIdent);
+ src = (char *)&(pEmrp->Data);
+ cbData -= 8;
+ }
+ else if(cIdent == U_EMR_COMMENT_SPOOL ){
+ printf(" cIdent: Spool\n");
+ PU_EMRCOMMENT_SPOOL pEmrs = (PU_EMRCOMMENT_SPOOL) pEmr;
+ printf(" esrIdent: %8.8x\n",pEmrs->esrIdent);
+ src = (char *)&(pEmrs->Data);
+ cbData -= 8;
+ }
+ else if(cIdent == U_EMR_COMMENT_EMFPLUSRECORD){
+ printf(" cIdent: EMF+\n");
+ PU_EMRCOMMENT_EMFPLUS pEmrpl = (PU_EMRCOMMENT_EMFPLUS) pEmr;
+ src = (char *)&(pEmrpl->Data);
+ cbData -= 4;
+ }
+ else {
+ printf(" cIdent: not (Public or Spool or EMF+)\n");
+ }
+ }
+ if(cbData){ // The data may not be printable, but try it just in case
+ string = malloc(cbData + 1);
+ (void)strncpy(string, src, cbData);
+ string[cbData] = '\0'; // it might not be terminated - it might not even be text!
printf(" Data: <%s>\n",string);
free(string);
}
+
}
// U_EMRFILLRGN 71