diff options
| author | David Mathog <mathog@caltech.edu> | 2014-02-08 07:17:30 +0000 |
|---|---|---|
| committer | ~suv <suv-sf@users.sourceforge.net> | 2014-02-08 07:17:30 +0000 |
| commit | 042cc81dd7c3ca2f0d42b68356f4b450074c8473 (patch) | |
| tree | f9acbfb046848f7cd420a1fbdf718bdcd604ed11 /src/extension/internal/text_reassemble.c | |
| parent | Extensions->Render submenu. Scaling of input parameters into document units, ... (diff) | |
| download | inkscape-042cc81dd7c3ca2f0d42b68356f4b450074c8473.tar.gz inkscape-042cc81dd7c3ca2f0d42b68356f4b450074c8473.zip | |
EMF/WMF support: Various changes (see bug #1263242 c35 for details)
EMF support:
- linear gradients: improve numeric stability on round-trip editing
- linear gradients: fix scaling issue
libTERE/text_reassemble update:
- improve handling of whitespace created with large x kerns
- fix handling of absolute RTL-positioning of LTR text in EMF files
WMF support:
- fix support for 'textout' records and Placeable headers
- add support for CREATEPATTERNBRUSH
- fix offset on load if opened via GUI (bug #1250250)
Fixed bugs:
- https://launchpad.net/bugs/1263242
- https://launchpad.net/bugs/1250250
(bzr r13008)
Diffstat (limited to 'src/extension/internal/text_reassemble.c')
| -rw-r--r-- | src/extension/internal/text_reassemble.c | 137 |
1 files changed, 90 insertions, 47 deletions
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; |
