diff options
| -rw-r--r-- | src/extension/internal/emf-inout.cpp | 2 | ||||
| -rw-r--r-- | src/extension/internal/emf-inout.h | 1 | ||||
| -rw-r--r-- | src/extension/internal/emf-print.cpp | 40 | ||||
| -rw-r--r-- | src/extension/internal/emf-print.h | 3 | ||||
| -rw-r--r-- | src/extension/internal/text_reassemble.c | 137 | ||||
| -rw-r--r-- | src/extension/internal/text_reassemble.h | 7 | ||||
| -rw-r--r-- | src/extension/internal/wmf-inout.cpp | 44 | ||||
| -rw-r--r-- | src/libuemf/README | 6 | ||||
| -rw-r--r-- | src/libuemf/uemf_utf.c | 95 | ||||
| -rw-r--r-- | src/libuemf/uwmf.c | 22 |
10 files changed, 250 insertions, 107 deletions
diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index cca541c5b..276dee362 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -4,6 +4,7 @@ /* Authors: * Ulf Erikson <ulferikson@users.sf.net> * Jon A. Cruz <jon@joncruz.org> + * David Mathog * Abhishek Sharma * * Copyright (C) 2006-2008 Authors @@ -1563,6 +1564,7 @@ int Emf::myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DA tsp.vadvance = 0.0; /* meaningful only when a complex contains two or more lines */ tsp.taln = ALILEFT + ALIBASE; tsp.ldir = LDIR_LR; + tsp.spaces = 0; // this field is only used for debugging tsp.color.Red = 0; /* RGB Black */ tsp.color.Green = 0; /* RGB Black */ tsp.color.Blue = 0; /* RGB Black */ diff --git a/src/extension/internal/emf-inout.h b/src/extension/internal/emf-inout.h index 97f93e71b..a97cb0a54 100644 --- a/src/extension/internal/emf-inout.h +++ b/src/extension/internal/emf-inout.h @@ -3,6 +3,7 @@ */ /* Authors: * Ulf Erikson <ulferikson@users.sf.net> + * David Mathog * * Copyright (C) 2006-2008 Authors * diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 2680718cf..6d5bb6f4b 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -124,7 +124,7 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) char *rec; gchar const *utf8_fn = mod->get_param_string("destination"); - // Typially PX2WORLD is 1200/90, using inkscape's default dpi + // Typically PX2WORLD is 1200/90, using inkscape's default dpi PX2WORLD = 1200.0 / Inkscape::Util::Quantity::convert(1.0, "in", "px"); FixPPTCharPos = mod->get_param_bool("FixPPTCharPos"); FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); @@ -848,7 +848,7 @@ Geom::Path PrintEmf::pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, int vertices; Geom::Path pR = pathv_to_simple_polygon(pathv, &vertices); *is_rect = false; - if(vertices==4){ // or else it cannot be a rectangle rectangle + if(vertices==4){ // or else it cannot be a rectangle int vertex_count=0; /* Get the ends of the LAST line segment. Find minimum rotation to align rectangle with X,Y axes. (Very degenerate if it is rotated 45 degrees.) */ @@ -862,12 +862,17 @@ Geom::Path PrintEmf::pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, if(fabs(ang) < fabs(*angle))*angle = -ang; // y increases down, flips sign on angle } } + + /* For increased numerical stability, snap the angle to the nearest 1/100th of a degree. */ + double convert = 36000.0/ (2.0 * M_PI); + *angle = round(*angle * convert)/convert; for(Geom::Path::const_iterator cit = pR.begin(); cit != pR.end_open();++cit) { P1_lead = cit->finalPoint(); v1 = unit_vector(P1 - P1_trail); v2 = unit_vector(P1_lead - P1 ); - if(!Geom::are_near(dot(v1,v2), 0.0, 1e-5))break; // P1 is center of a turn that is not 90 degrees + // P1 is center of a turn that is not 90 degrees. Limit comes from cos(89.9) = .001745 + if(!Geom::are_near(dot(v1,v2), 0.0, 2e-3))break; P1_trail = P1; P1 = P1_lead; vertex_count++; @@ -985,12 +990,13 @@ unsigned int PrintEmf::fill( int rectDir=0; Geom::Path pathRect; if(FixPPTLinGrad && brush_stat && gv.mode == DRAW_LINEAR_GRADIENT){ - pathRect = pathv_to_rect(pathv, &is_Rect, &angle); + Geom::PathVector pvr = pathv * fill_transform; + pathRect = pathv_to_rect(pvr, &is_Rect, &angle); if(is_Rect){ /* Gradientfill records can only be used if the gradient is parallel to the sides of the rectangle. That must be checked here so that we can fall back to another form of gradient fill if it is not the case. */ - rectDir = vector_rect_alignment(angle, gv.p2 - gv.p1); + rectDir = vector_rect_alignment(angle, (gv.p2 - gv.p1) * fill_transform); if(!rectDir)is_Rect = false; } if(!is_Rect && !FixPPTGrad2Polys)brush_stat=0; // fall all the way back to a solid fill @@ -1094,26 +1100,27 @@ unsigned int PrintEmf::fill( U_XFORM tmpTransform; double wRect, hRect; - /* coordinates, w,h and transform for the ENTIRE retangle */ - ul = get_pathrect_corner(pathRect, angle, 0) * fill_transform * PX2WORLD; - ur = get_pathrect_corner(pathRect, angle, 1) * fill_transform * PX2WORLD; - lr = get_pathrect_corner(pathRect, angle, 2) * fill_transform * PX2WORLD; + /* coordinates: upper left, upper right, and lower right corners of the rectangle. + inkscape transform already applied, but needs to be scaled to EMF coordinates. */ + ul = get_pathrect_corner(pathRect, angle, 0) * PX2WORLD; + ur = get_pathrect_corner(pathRect, angle, 1) * PX2WORLD; + lr = get_pathrect_corner(pathRect, angle, 2) * PX2WORLD; wRect = Geom::distance(ul,ur); hRect = Geom::distance(ur,lr); /* The basic rectangle for all of these is placed with its UL corner at 0,0 with a size wRect,hRect. Apply a world transform to place/scale it into the appropriate position on the drawing. Actual gradientfill records are either this entire rectangle or slices of it as defined by the stops. + This rectangle has already been transformed by tf (whatever rotation/scale) Inkscape had applied to it. */ Geom::Affine tf2 = Geom::Rotate(-angle); // the rectangle may be drawn skewed to the coordinate system - tf2 *= tf; // the coordinate system of the rectangular path may be rotated tmpTransform.eM11 = tf2[0]; tmpTransform.eM12 = tf2[1]; tmpTransform.eM21 = tf2[2]; tmpTransform.eM22 = tf2[3]; - tmpTransform.eDx = (ul)[Geom::X]; - tmpTransform.eDy = (ul)[Geom::Y]; + tmpTransform.eDx = round((ul)[Geom::X]); // use explicit round for better stability + tmpTransform.eDy = round((ul)[Geom::Y]); rec = U_EMRSAVEDC_set(); if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { @@ -1138,10 +1145,10 @@ unsigned int PrintEmf::fill( gMode = U_GRADIENT_FILL_RECT_V; } doff_base = doff_range; - rcb.left = outUL[X]; - rcb.top = outUL[Y]; - rcb.right = outLR[X]; - rcb.bottom = outLR[Y]; + rcb.left = round(outUL[X]); // use explicit round for better stability + rcb.top = round(outUL[Y]); + rcb.right = round(outLR[X]); + rcb.bottom = round(outLR[Y]); sp_color_get_rgb_floatv(&tg->vector.stops[istop].color, rgb); opa = tg->vector.stops[istop].opacity; c2 = U_RGBA(255 * rgb[0], 255 * rgb[1], 255 * rgb[2], 255 * opa); @@ -1157,7 +1164,6 @@ unsigned int PrintEmf::fill( c1 = c2; // for next stop ug4.UpperLeft = 0; ug4.LowerRight= 1; - /* NEED to push world transform here for rotations */ rec = U_EMRGRADIENTFILL_set(rcb, 2, 1, gMode, ut, (uint32_t *) &ug4 ); if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { g_error("Fatal programming error in PrintEmf::fill at U_EMRGRADIENTFILL_set"); diff --git a/src/extension/internal/emf-print.h b/src/extension/internal/emf-print.h index 8fc9908e3..1e4970a46 100644 --- a/src/extension/internal/emf-print.h +++ b/src/extension/internal/emf-print.h @@ -1,8 +1,9 @@ /** @file * @brief Enhanced Metafile printing - implementation */ -/* Author: +/* Authors: * Ulf Erikson <ulferikson@users.sf.net> + * David Mathog * * Copyright (C) 2006-2008 Authors * diff --git a/src/extension/internal/text_reassemble.c b/src/extension/internal/text_reassemble.c index cd84910fc..e28e5effb 100644 --- a/src/extension/internal/text_reassemble.c +++ b/src/extension/internal/text_reassemble.c @@ -67,11 +67,11 @@ Optional compiler switches for development: File: text_reassemble.c -Version: 0.0.10 -Date: 06-MAY-2013 +Version: 0.0.12 +Date: 07-FEB-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2013 David Mathog and California Institute of Technology (Caltech) +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -665,7 +665,7 @@ FT_INFO *ftinfo_clear(FT_INFO *fti){ free(fsp->file); /* release memory holding copies of paths */ free(fsp->fontspec); /* release memory holding copies of font names */ FcPatternDestroy(fsp->fpat); /* release memory for FontConfig fpats */ - FcFontSetDestroy(fti->fonts[i].fontset); + FcFontSetDestroy(fsp->fontset); if(fsp->alts){ free(fsp->alts); } } free(fti->fonts); @@ -726,9 +726,10 @@ int ftinfo_find_loaded_by_src(const FT_INFO *fti, const uint8_t *filename){ */ int ftinfo_load_fontname(FT_INFO *fti, const char *fontspec){ - FcPattern *pattern, *fpat; - FcFontSet *fontset; - FcResult result = FcResultMatch; + FcPattern *pattern = NULL; + FcPattern *fpat = NULL; + FcFontSet *fontset = NULL; + FcResult result = FcResultMatch; char *filename; double fd; FNT_SPECS *fsp; @@ -738,38 +739,45 @@ int ftinfo_load_fontname(FT_INFO *fti, const char *fontspec){ if(!fti)return(-1); /* If it is already loaded, do not load it again */ - if((status = ftinfo_find_loaded_by_spec(fti, (uint8_t *) fontspec))>=0){ - return(status); - } + status = ftinfo_find_loaded_by_spec(fti, (uint8_t *) fontspec); + if(status >= 0){ return(status); } + status = 0; /* was -1, reset to 0 */ ftinfo_make_insertable(fti); fi_idx = fti->used; - if(!(pattern = FcNameParse((const FcChar8 *)fontspec)) )return(2); - if(!FcConfigSubstitute(NULL, pattern, FcMatchPattern) )return(3); - FcDefaultSubstitute(pattern); - /* get a fontset, trimmed to only those with new glyphs as needed, so that missing glyph's may be handled */ - if(!(fontset = FcFontSort (NULL,pattern, FcTrue, NULL, &result)) - || result != FcResultMatch)return(4); - if(!(fpat = FcFontRenderPrepare(NULL, pattern, fontset->fonts[0])) )return(405); - if(FcPatternGetString( fpat, FC_FILE, 0, (FcChar8 **)&filename) != FcResultMatch)return(5); - if(FcPatternGetDouble( fpat, FC_SIZE, 0, &fd) != FcResultMatch)return(6); - - /* copy these into memory for external use */ - fsp = &(fti->fonts[fti->used]); - fsp->fontset = fontset; - fsp->alts = NULL; /* Initially no links to alternate fonts */ - fsp->space = 0; - fsp->file = (uint8_t *) U_strdup((char *) filename); - fsp->fontspec = (uint8_t *) U_strdup((char *) fontspec); - fsp->fpat = fpat; - fsp->fsize = fd; - + pattern = FcNameParse((const FcChar8 *)fontspec); + while(1) { /* this is NOT a loop, it uses breaks to avoid gotos and deep nesting */ + if(!(pattern)){ status = -2; break; } + if(!FcConfigSubstitute(NULL, pattern, FcMatchPattern)){ status = -3; break; }; + FcDefaultSubstitute(pattern); + /* get a fontset, trimmed to only those with new glyphs as needed, so that missing glyph's may be handled */ + if(!(fontset = FcFontSort (NULL,pattern, FcTrue, NULL, &result)) || (result != FcResultMatch)){ status = -4; break; } + if(!(fpat = FcFontRenderPrepare(NULL, pattern, fontset->fonts[0]))){ status = -405; break; } + if(FcPatternGetString( fpat, FC_FILE, 0, (FcChar8 **)&filename) != FcResultMatch){ status = -5; break; } + if(FcPatternGetDouble( fpat, FC_SIZE, 0, &fd) != FcResultMatch){ status = -6; break; } + + /* copy these into memory for external use */ + fsp = &(fti->fonts[fti->used]); + fsp->fontset = fontset; + fsp->alts = NULL; /* Initially no links to alternate fonts */ + fsp->space = 0; + fsp->file = (uint8_t *) U_strdup((char *) filename); + fsp->fontspec = (uint8_t *) U_strdup((char *) fontspec); + fsp->fpat = fpat; + fsp->fsize = fd; + break; + } /* release FC's own memory related to this call that does not need to be kept around so that face will work */ - FcPatternDestroy(pattern); + if(pattern)FcPatternDestroy(pattern); /* done with this memory */ + if(status<0){ + if(fontset)FcFontSetDestroy(fontset); + if(fpat)FcPatternDestroy(fpat); + return(status); + } /* get the current face */ - if(FT_New_Face( fti->library, (const char *) fsp->file, 0, &(fsp->face) )){ return(8); } + if(FT_New_Face( fti->library, (const char *) fsp->file, 0, &(fsp->face) )){ return(-8); } if(FT_Set_Char_Size( fsp->face, /* handle to face object */ @@ -777,12 +785,12 @@ int ftinfo_load_fontname(FT_INFO *fti, const char *fontspec){ fd*64, /* char_height in 1/64th of points */ 72, /* horizontal device resolution, DPI */ 72) /* vebrical device resolution, DPI */ - ){ return(9); } + ){ return(-9); } /* The space advance is needed in various places. Get it now, and get it in the font units, so that it can be scaled later with the text size */ status = TR_getadvance(fti, fsp,' ',0,FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP, FT_KERNING_UNSCALED, NULL, NULL); - if(status < 0)return(7); + if(status < 0)return(-7); fsp->spcadv = ((double) status)/(64.0); fti->used++; @@ -1380,7 +1388,7 @@ printf("Overlap rprect (LL,UR) dst:(%lf,%lf),(%lf,%lf) src:(%lf,%lf),(%lf,%lf)\n } /** - \brief Check for a text element upstream from the start element and in the reversed direction. + \brief Check for various sorts of invalid text elements upstream (language dir changes, draw order backwards from language direction) \returns 0 on success (not upstream), 1 if upstream, anything else is an error. \param bri pointer to the BR_INFO structure \param dst index of the destination bounding rectangle. @@ -1405,6 +1413,12 @@ int brinfo_upstream(BR_INFO *bri, int dst, int src, int ddir, int sdir){ else if( ddir == LDIR_LR && sdir == LDIR_RL){ if((br_src->xll + br_src->xur)/2.0 <= br_dst->xll ){ status = 1; } } + else if( ddir == LDIR_RL && sdir == LDIR_RL){ + if(br_dst->xur <= (br_src->xll + br_src->xur)/2.0){ status = 1; } + } + else if( ddir == LDIR_LR && sdir == LDIR_LR){ + if((br_src->xll + br_src->xur)/2.0 <= br_dst->xll ){ status = 1; } + } return(status); } @@ -1490,13 +1504,19 @@ TR_INFO *trinfo_init(TR_INFO *tri){ !(tri->bri = brinfo_init()) || !(tri->cxi = cxinfo_init()) ){ tri = trinfo_release(tri); } + tri->out = NULL; /* This will allocate as needed, it might not ever be needed. */ + tri->qe = 0.0; + tri->esc = 0.0; + tri->x = DBL_MAX; + tri->y = DBL_MAX; + tri->dirty = 0; tri->use_kern = 1; - tri->usebk = BKCLR_NONE; tri->load_flags = FT_LOAD_NO_SCALE; tri->kern_mode = FT_KERNING_UNSCALED; - tri->out = NULL; /* This will allocate as needed, it might not ever be needed. */ tri->outspace = 0; tri->outused = 0; + tri->usebk = BKCLR_NONE; + memset(&(tri->bkcolor),0,sizeof(TRCOLORREF)); return(tri); } @@ -1552,9 +1572,6 @@ TR_INFO *trinfo_release_except_FC(TR_INFO *tri){ */ TR_INFO *trinfo_clear(TR_INFO *tri){ if(tri){ - tri->dirty = 0; /* set these back to their defaults */ - tri->esc = 0.0; - /* Do NOT modify use_kern, usebk, load_flags, or kern_mode */ if(tri->bri)tri->bri=brinfo_release(tri->bri); if(tri->tpi)tri->tpi=tpinfo_release(tri->tpi); @@ -1565,6 +1582,11 @@ TR_INFO *trinfo_clear(TR_INFO *tri){ tri->outused = 0; tri->outspace = 0; }; + /* Do NOT modify: qe, use_kern, usebk, load_flags, kern_mode, or bkcolor. Set the rest back to their defaults */ + tri->esc = 0.0; + tri->x = DBL_MAX; + tri->y = DBL_MAX; + tri->dirty = 0; if(!(tri->tpi = tpinfo_init()) || /* re-init the pieces just released */ !(tri->bri = brinfo_init()) || !(tri->cxi = cxinfo_init()) @@ -1958,7 +1980,7 @@ void TR_layout_2_svg(TR_INFO *tri){ cutat=strcspn((char *)fti->fonts[tsp->fi_idx].fontspec,":"); sprintf(obuf,"font-family:%.*s;",cutat,fti->fonts[tsp->fi_idx].fontspec); TRPRINT(tri, obuf); - sprintf(obuf,"\n\">%s</text>\n",tsp->string); + sprintf(obuf,"\n\">%s</text>\n",&tsp->string[tsp->spaces]); TRPRINT(tri, obuf); #endif /* DBG_TR_INPUT debugging code, original text objects */ } @@ -2278,7 +2300,10 @@ int TR_layout_analyze(TR_INFO *tri){ next logical piece of text is "upstream" positionally of its logical predecessor. The meaning of such a construct is at best ambiguous. The test is only applied with respect to the first text chunk. This sort of construct may appear when a valid initial construct like [1->English][2<-Hebrew][3->English] is edited - and the leading chunk of text removed. + and the leading chunk of text removed. + + Also reject reversed order text as in (English) <A><B><C> (draw order) arranged as <C><B><A>. This happens + if the language direction field is incorrect, perhaps due to a corrupt or malformed input file. */ if(brinfo_upstream(bri, dst_rt, /* index into bri for dst */ @@ -2422,10 +2447,28 @@ int TR_layout_analyze(TR_INFO *tri){ } } - /* if x or y kern is less than the quantization error it is probably noise, set it to zero */ - if(fabs(tspj->xkern)<tri->qe)tspj->xkern = 0.0; - if(fabs(tspj->ykern)<tri->qe)tspj->ykern = 0.0; - + /* if x or y kern is less than twice the quantization error it is probably noise, set it to zero */ + if(fabs(tspj->xkern) <= 2.0*tri->qe)tspj->xkern = 0.0; + if(fabs(tspj->ykern) <= 2.0*tri->qe)tspj->ykern = 0.0; + + /* reintroduce spaces on the leading edge of text "j" if the kerning can be in part or in whole replaced + with 1 or 2 spaces */ + if(tspj->ykern == 0.0){ + double spaces = tspj->xkern/spcadv; /* negative on RL language, positive on LR */ + if((ldir == LDIR_RL && (spaces <= -0.9 && spaces >= -2.1)) || + (ldir == LDIR_LR && (spaces >= 0.9 && spaces <= 2.1)) ){ + int ispaces = lround(spaces); + tspj->xkern -= ((double)ispaces*spcadv); + if(ispaces<0)ispaces=-ispaces; + size_t slen = strlen((char *)tspj->string); + uint8_t *newstring = malloc(1 + ispaces + slen); + sprintf((char *)newstring," "); /* start with two spaces, possibly overwrite one in the next line */ + memcpy(newstring+ispaces,tspj->string,slen+1); /* copy existing string to proper position */ + free(tspj->string); + tspj->string = newstring; + tspj->spaces = ispaces; // only needed to fix optional debugging SVG output later + } + } tspi = tspj; lastldir = ldir; @@ -2699,7 +2742,7 @@ int main(int argc, char *argv[]){ tsp.weight = 80; tsp.condensed = 100; tsp.decoration = 0; /* none */ - tsp.co = 0; + tsp.spaces = 0; /* none */ tsp.fi_idx = -1; /* set to an invalid */ tsp.rt_tidx = -1; /* set to an invalid */ tsp.xkern = tsp.ykern = 0.0; diff --git a/src/extension/internal/text_reassemble.h b/src/extension/internal/text_reassemble.h index d85b233be..6c1acafe5 100644 --- a/src/extension/internal/text_reassemble.h +++ b/src/extension/internal/text_reassemble.h @@ -4,11 +4,11 @@ See text_reassemble.c for notes File: text_reassemble.h -Version: 0.0.12 -Date: 14-MAY-2013 +Version: 0.0.13 +Date: 06-FEB-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2013 David Mathog and California Institute of Technology (Caltech) +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) */ #ifndef _TEXT_REASSEMBLE_ @@ -189,6 +189,7 @@ typedef struct { int weight; /**< weight, as in FontConfig */ int condensed; /**< condensed, as in FontConfig */ int decoration; /**< text decorations, ignored during assembly, used during output */ + int spaces; /**< count of spaces converted from wide kerning (1 or 2) */ TRCOLORREF decColor; /**< text decoration color, ignored during assembly, used during output */ int co; /**< condensed override, if set Font name included narrow */ int rt_tidx; /**< index of rectangle that contains it */ diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index a72c16a88..fc54350df 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -4,6 +4,7 @@ /* Authors: * Ulf Erikson <ulferikson@users.sf.net> * Jon A. Cruz <jon@joncruz.org> + * David Mathog * Abhishek Sharma * * Copyright (C) 2006-2008 Authors @@ -1079,6 +1080,28 @@ Wmf::select_brush(PWMF_CALLBACK_DATA d, int index) g_message("Please send WMF file to developers - select_brush U_WMR_DIBCREATEPATTERNBRUSH not bm16 or dib, not handled"); } } + else if(iType == U_WMR_CREATEPATTERNBRUSH){ + uint32_t tidx; + int cbPx; + U_BITMAP16 Bm16h; + const char *px; + if(U_WMRCREATEPATTERNBRUSH_get(record, &Bm16h, &cbPx, &px)){ + tidx = add_bm16_image(d, Bm16h, px); + if(tidx == 0xFFFFFFFF){ // Problem with the image, for instance, an unsupported bitmap16 type + double r, g, b; + r = SP_COLOR_U_TO_F( U_RGBAGetR(d->dc[d->level].textColor)); + g = SP_COLOR_U_TO_F( U_RGBAGetG(d->dc[d->level].textColor)); + b = SP_COLOR_U_TO_F( U_RGBAGetB(d->dc[d->level].textColor)); + d->dc[d->level].style.fill.value.color.set( r, g, b ); + d->dc[d->level].fill_mode = DRAW_PAINT; + } + else { + d->dc[d->level].fill_idx = tidx; + d->dc[d->level].fill_mode = DRAW_IMAGE; + } + d->dc[d->level].fill_set = true; + } + } } @@ -1488,6 +1511,7 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK tsp.vadvance = 0.0; /* meaningful only when a complex contains two or more lines */ tsp.taln = ALILEFT + ALIBASE; tsp.ldir = LDIR_LR; + tsp.spaces = 0; // this field is only used for debugging tsp.color.Red = 0; /* RGB Black */ tsp.color.Green = 0; /* RGB Black */ tsp.color.Blue = 0; /* RGB Black */ @@ -1498,6 +1522,7 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK tsp.condensed = 100; tsp.co = 0; tsp.fi_idx = -1; /* set to an invalid */ + tsp.rt_tidx = -1; /* set to an invalid */ SVGOStringStream dbg_str; @@ -1568,7 +1593,10 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK d->dc[d->level].sizeView.x = d->dc[d->level].sizeWnd.x = 0; d->dc[d->level].sizeView.y = d->dc[d->level].sizeWnd.y = 0; - // Upper left corner in device units, usually both 0, but not always + /* Upper left corner in device units, usually both 0, but not always. + If a placeable header is used, and later a windoworg/windowext are found, then + the placeable information will be ignored. + */ d->ulCornerInX = Placeable.Dst.left; d->ulCornerInY = Placeable.Dst.top; @@ -1805,6 +1833,8 @@ std::cout << "BEFORE DRAW" { dbg_str << "<!-- U_WMR_SETWINDOWORG -->\n"; nSize = U_WMRSETWINDOWORG_get(contents, &d->dc[d->level].winorg); + d->ulCornerOutX = 0.0; // In the examples seen to date if this record is used with a placeable header, that header is ignored + d->ulCornerOutY = 0.0; break; } case U_WMR_SETWINDOWEXT: @@ -2322,12 +2352,12 @@ std::cout << "BEFORE DRAW" break; case U_WMR_CREATEBRUSHINDIRECT: case U_WMR_DIBCREATEPATTERNBRUSH: + case U_WMR_CREATEPATTERNBRUSH: // <- this one did not display properly on XP, DIBCREATEPATTERNBRUSH works select_brush(d, index); break; case U_WMR_CREATEFONTINDIRECT: select_font(d, index); break; - case U_WMR_CREATEPATTERNBRUSH: // <- this one did not display properly on XP, DIBCREATEPATTERNBRUSH works case U_WMR_CREATEPALETTE: case U_WMR_CREATEBITMAPINDIRECT: case U_WMR_CREATEBITMAP: @@ -2376,6 +2406,7 @@ std::cout << "BEFORE DRAW" if(iType == U_WMR_TEXTOUT){ dbg_str << "<!-- U_WMR_TEXTOUT -->\n"; nSize = U_WMRTEXTOUT_get(contents, &Dst, &tlen, &text); + Opts=0; } else { dbg_str << "<!-- U_WMR_EXTTEXTOUT -->\n"; @@ -3053,7 +3084,14 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) // Scale and translate objects double scale = Inkscape::Util::Quantity::convert(1, "px", doc_unit); ShapeEditor::blockSetItem(true); - doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, doc->getHeight().value("px"))); + double dh; + if(SP_ACTIVE_DOCUMENT){ // for file menu open or import, or paste from clipboard + dh = SP_ACTIVE_DOCUMENT->getHeight().value("px"); + } + else { // for open via --file on command line + dh = doc->getHeight().value("px"); + } + doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, dh)); ShapeEditor::blockSetItem(false); Inkscape::DocumentUndo::setUndoSensitive(doc, saved); diff --git a/src/libuemf/README b/src/libuemf/README index 4c23cdd52..cfa322178 100644 --- a/src/libuemf/README +++ b/src/libuemf/README @@ -366,6 +366,12 @@ History (Note, version numbers in files represent the libUEMF release where it was last modified, so not all files will show the same version numbers in each release.) +0.1.11 2014-01-29 + Fixed bug in uwmf.c (wrong minimum record size on U_WMRTEXTOUT) + Fixed bug in uwmf.c (U_WMRCREATEPATTERNBRUSH not right) + Added error handling to uemf_utf.c for cases where src is a null pointer. + Added a test of createpatternbrush to testlib_wmf + 0.1.10 2014-01-14 Slight changes in documentation for uemf.h. Fixed typo in uemf_endian.c. diff --git a/src/libuemf/uemf_utf.c b/src/libuemf/uemf_utf.c index f329e74d9..bce60af4d 100644 --- a/src/libuemf/uemf_utf.c +++ b/src/libuemf/uemf_utf.c @@ -12,11 +12,11 @@ /* File: uemf_utf.c -Version: 0.0.4 -Date: 19-MAR-2013 +Version: 0.0.5 +Date: 29-JAN-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2013 David Mathog and California Institute of Technology (Caltech) +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -68,9 +68,14 @@ These functions are used for development and debugging and should be be includie void wchar8show( const char *src ){ - printf("char show\n"); - size_t srclen = 0; - while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + if(!src){ + printf("char show <NULL>\n"); + } + else { + printf("char show\n"); + size_t srclen = 0; + while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + } } /** @@ -80,9 +85,14 @@ void wchar8show( void wchar16show( const uint16_t *src ){ - printf("uint16_t show\n"); - size_t srclen = 0; - while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + if(!src){ + printf("uint16_t show <NULL>\n"); + } + else { + printf("uint16_t show\n"); + size_t srclen = 0; + while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + } } /** @@ -91,9 +101,14 @@ void wchar16show( void wchar32show( const uint32_t *src ){ - printf("uint32_t show\n"); - size_t srclen = 0; - while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + if(!src){ + printf("uint32_t show <NULL>\n"); + } + else { + printf("uint32_t show\n"); + size_t srclen = 0; + while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; } + } } /** @@ -104,13 +119,19 @@ void wchartshow( const wchar_t *src ){ uint32_t val; - printf("wchar_t show\n"); - size_t srclen = 0; - while(*src){ - val = *src; // because *src is wchar_t is not strictly an integer type, can cause warnings on next line - printf("%d %d %x\n",(int) srclen,val,val); - srclen++; - src++; + if(!src){ + printf("wchar_t show <NULL>\n"); + } + else { + printf("wchar_t show\n"); + size_t srclen = 0; + if(!src)return; + while(*src){ + val = *src; // because *src is wchar_t is not strictly an integer type, can cause warnings on next line + printf("%d %d %x\n",(int) srclen,val,val); + srclen++; + src++; + } } } @@ -127,7 +148,9 @@ size_t wchar16len( const uint16_t *src ){ size_t srclen = 0; - while(*src){ srclen++; src++; } + if(src){ + while(*src){ srclen++; src++; } + } return(srclen); } @@ -139,7 +162,9 @@ size_t wchar32len( const uint32_t *src ){ size_t srclen = 0; - while(*src){ srclen++; src++; } + if(src){ + while(*src){ srclen++; src++; } + } return(srclen); } @@ -154,9 +179,11 @@ void wchar16strncpy( const uint16_t *src, size_t nchars ){ - for(;nchars;nchars--,dst++,src++){ - *dst = *src; - if(!*src)break; + if(src){ + for(;nchars;nchars--,dst++,src++){ + *dst = *src; + if(!*src)break; + } } } @@ -172,8 +199,10 @@ void wchar16strncpypad( const uint16_t *src, size_t nchars ){ - for(;*src && nchars;nchars--,dst++,src++){ *dst = *src; } - for(;nchars;nchars--,dst++){ *dst = 0; } // Pad the remainder + if(src){ + for(;*src && nchars;nchars--,dst++,src++){ *dst = *src; } + for(;nchars;nchars--,dst++){ *dst = 0; } // Pad the remainder + } } /* For the following converstion functions, remember that iconv() modifies ALL of its parameters, @@ -197,6 +226,7 @@ uint16_t *U_Utf32leToUtf16le( char *dst,*dst2; size_t srclen,dstlen,status; + if(!src)return(NULL); if(max){ srclen = 4*max; } else { srclen = 4 + 4*wchar32len(src); } //include terminator, length in BYTES @@ -226,6 +256,8 @@ uint32_t *U_Utf16leToUtf32le( char *dst,*dst2; char *src2 = (char *) src; size_t srclen,dstlen,status; + + if(!src)return(NULL); if(max){ srclen = 2*max; } else { srclen = 2*wchar16len(src)+2; } // include terminator, length in BYTES dstlen = 2*(2 + srclen); // This should always work @@ -261,6 +293,8 @@ uint32_t *U_Latin1ToUtf32le( char *dst,*dst2; char *src2 = (char *) src; size_t srclen,dstlen,status; + + if(!src)return(NULL); if(max){ srclen = max; } else { srclen = strlen(src)+1; } // include terminator, length in BYTES dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space @@ -290,6 +324,8 @@ uint32_t *U_Utf8ToUtf32le( char *dst,*dst2; char *src2 = (char *) src; size_t srclen,dstlen,status; + + if(!src)return(NULL); if(max){ srclen = max; } else { srclen = strlen(src)+1; } // include terminator, length in BYTES dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space @@ -319,6 +355,8 @@ char *U_Utf32leToUtf8( char *dst,*dst2; char *src2 = (char *) src; size_t srclen,dstlen,status; + + if(!src)return(NULL); if(max){ srclen = 4*max; } else { srclen = 4*(1 + wchar32len(src)); } //include terminator, length in BYTES dstlen = 1 + srclen; // This should always work but might waste some space @@ -349,6 +387,7 @@ uint16_t *U_Utf8ToUtf16le( size_t srclen,dstlen,status; iconv_t conv; + if(!src)return(NULL); if(max){ srclen = max; } else { srclen = strlen(src)+1; } // include terminator, length in BYTES dstlen = 2 * (1 + srclen); // this will always work, but may waste space @@ -378,6 +417,8 @@ char *U_Utf16leToUtf8( char *dst, *dst2; char *ret=NULL; size_t srclen,dstlen,status; + + if(!src)return(NULL); if(max){ srclen = 2*max; } else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES dstlen = 1 + 2*srclen; // this will always work, but may waste space @@ -410,6 +451,8 @@ char *U_Utf16leToLatin1( char *dst, *dst2; char *ret=NULL; size_t srclen,dstlen,status; + + if(!src)return(NULL); if(max){ srclen = 2*max; } else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES dstlen = 1 + srclen; // this will always work as latin1 is always 1 byte/character diff --git a/src/libuemf/uwmf.c b/src/libuemf/uwmf.c index a6ac963cb..be1feadea 100644 --- a/src/libuemf/uwmf.c +++ b/src/libuemf/uwmf.c @@ -19,11 +19,11 @@ /* File: uwmf.c -Version: 0.0.12 -Date: 25-NOV-2013 +Version: 0.0.13 +Date: 30-JAN-2014 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2013 David Mathog and California Institute of Technology (Caltech) +Copyright: 2014 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -4271,13 +4271,12 @@ char *U_WMRCREATEPATTERNBRUSH_set( if(!Bm16 || !Pattern)return(NULL); cbPat = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; - irecsize = U_SIZE_METARECORD + 14 + 4 + 18 + cbPat; /* core WMR + truncated Bm16 + pattern */ + irecsize = U_SIZE_METARECORD + 14 + 18 + cbPat; /* core WMR + truncated Bm16 + 18 spaces bytes + pattern */ record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEPATTERNBRUSH); off = U_SIZE_METARECORD; - memcpy(record + off, Bm16, 14); off+=14; /* Truncated bitmap16 object*/ - memset(record + off, 0, 4); off+=4; /* 4 bytes of its "bits", which are ignored */ + memcpy(record + off, Bm16, 14); off+=14; /* Truncated bitmap16 object, last 4 bytes are to be ignored*/ memset(record + off, 0, 18); off+=18; /* 18 bytes of zero, which are ignored */ memcpy(record + off, Pattern, cbPat); /* The pattern array */ } @@ -5359,7 +5358,7 @@ int U_WMRTEXTOUT_get( ){ int16_t L2; int off; - int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRPATBLT)); + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRTEXTOUT)); if(!size)return(0); *Length = *(int16_t *)(contents + offsetof(U_WMRTEXTOUT, Length)); *string = contents + offsetof(U_WMRTEXTOUT, String); /* May not be null terminated!!! */ @@ -6851,12 +6850,15 @@ int U_WMRCREATEPATTERNBRUSH_get( const char **Pattern ){ int off = U_SIZE_METARECORD; - int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETDIBTODEV)); + /* size in next one is + 6 (core header) + 14 (truncated bitmap16) + 18 bytes reserved + 2 bytes (at least) for data */ + int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_METARECORD + 14 + 18 + 2)); if(!size)return(0); memset(Bm16, 0, U_SIZE_BITMAP16); - memcpy(Bm16, contents + off, 14); /* BM16 is truncated in this record type */ + /* BM16 is truncated in this record type to 14 bytes, last 4 bytes must be ignored, so they are not even copied */ + memcpy(Bm16, contents + off, 10); *pasize = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; - off += 36; /* skip [truncated bitmap16 object and 18 bytes of reserved */ + off += 32; /* skip [14 bytes of truncated bitmap16 object and 18 bytes of reserved */ *Pattern = (contents + off); return(size); } |
