From: Daniel Horn Subject: [PATCH] wineps.drv: Allow text copy/paste from print-to-pdf. Fixes caching bug in unicode composite glyphs (resend) Message-Id: Date: Mon, 14 Apr 2014 15:08:46 -0700 From c2ebfce260ffabed6d45a030284c7719c9fca049 Mon Sep 17 00:00:00 2001 From: Daniel Reiter Horn Date: Sat, 5 Apr 2014 21:46:26 +0000 Subject: [PATCH] wineps.drv: Allow text copy/paste from print-to-pdf. Fixes caching bug in unicode composite glyphs Fixes http://bugs.winehq.org/show_bug.cgi?id=6416 by using unicode encodings for fonts. This exposed a bug with caching composite unicode glyphs (if a ñ came before any n in the document, then all subsequent n's would appear as a box) This was because the glyph was marked as having been sent down when it was only a component of a more complex glyph. The patch has been tested on hundreds of print jobs under linux ubuntu 12.04 with a wide array of applications. --- dlls/wineps.drv/download.c | 17 ++++++++++------- dlls/wineps.drv/psdrv.h | 4 ++-- dlls/wineps.drv/text.c | 29 +++++++++++++++++++---------- dlls/wineps.drv/type42.c | 20 ++++++++++++++------ 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/dlls/wineps.drv/download.c b/dlls/wineps.drv/download.c index e5b57f7..3a14cd0 100644 --- a/dlls/wineps.drv/download.c +++ b/dlls/wineps.drv/download.c @@ -342,7 +342,7 @@ BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev, BOOL vertical) if(pdl->type == Type42) { char g_name[MAX_G_NAME + 1]; - get_glyph_name(dev->hdc, 0, g_name); + get_glyph_name(dev->hdc, FALSE, 0, g_name); T42_download_glyph(dev, pdl, 0, g_name); } } @@ -359,10 +359,12 @@ BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev, BOOL vertical) return TRUE; } -void get_glyph_name(HDC hdc, WORD index, char *name) +void get_glyph_name(HDC hdc, BOOL unicode, WORD index, char *name) { - /* FIXME */ - sprintf(name, "g%04x", index); + if(unicode) + sprintf(name, "uni%04X", index); + else + sprintf(name, "g%04x", index); return; } @@ -372,7 +374,8 @@ void get_glyph_name(HDC hdc, WORD index, char *name) * Download and write out a number of glyphs * */ -BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, const WORD *glyphs, +BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, UINT flags, const WORD *glyphs, + const LPCWSTR str, UINT count) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); @@ -383,7 +386,7 @@ BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, const WORD *glyphs, switch(physDev->font.fontinfo.Download->type) { case Type42: for(i = 0; i < count; i++) { - get_glyph_name(dev->hdc, glyphs[i], g_name); + get_glyph_name(dev->hdc, (flags & ETO_GLYPH_INDEX) == 0, str[i], g_name); T42_download_glyph(dev, physDev->font.fontinfo.Download, glyphs[i], g_name); PSDRV_WriteGlyphShow(dev, g_name); } @@ -391,7 +394,7 @@ BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, const WORD *glyphs, case Type1: for(i = 0; i < count; i++) { - get_glyph_name(dev->hdc, glyphs[i], g_name); + get_glyph_name(dev->hdc, (flags & ETO_GLYPH_INDEX) == 0, str[i], g_name); T1_download_glyph(dev, physDev->font.fontinfo.Download, glyphs[i], g_name); PSDRV_WriteGlyphShow(dev, g_name); } diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h index 229d04c..aeb247f 100644 --- a/dlls/wineps.drv/psdrv.h +++ b/dlls/wineps.drv/psdrv.h @@ -549,13 +549,13 @@ extern BOOL PSDRV_WriteBuiltinGlyphShow(PHYSDEV dev, LPCWSTR str, INT count) DEC extern BOOL PSDRV_SelectDownloadFont(PHYSDEV dev) DECLSPEC_HIDDEN; extern BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev, BOOL vertical) DECLSPEC_HIDDEN; -extern BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, const WORD *glpyhs, UINT count) DECLSPEC_HIDDEN; +extern BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, UINT flags, const WORD *glpyhs, const LPCWSTR str, UINT count) DECLSPEC_HIDDEN; extern BOOL PSDRV_EmptyDownloadList(PHYSDEV dev, BOOL write_undef) DECLSPEC_HIDDEN; extern DWORD write_spool( PHYSDEV dev, const void *data, DWORD num ) DECLSPEC_HIDDEN; #define MAX_G_NAME 31 /* max length of PS glyph name */ -extern void get_glyph_name(HDC hdc, WORD index, char *name) DECLSPEC_HIDDEN; +extern void get_glyph_name(HDC hdc, BOOL unicode, WORD index, char *name) DECLSPEC_HIDDEN; extern TYPE1 *T1_download_header(PHYSDEV dev, char *ps_name, RECT *bbox, UINT emsize) DECLSPEC_HIDDEN; diff --git a/dlls/wineps.drv/text.c b/dlls/wineps.drv/text.c index 96728ca..06c242b 100644 --- a/dlls/wineps.drv/text.c +++ b/dlls/wineps.drv/text.c @@ -205,27 +205,35 @@ BOOL PSDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect /*********************************************************************** * PSDRV_Text */ +#define DEFAULT_PARAGRAPH_SIZE 16384 static BOOL PSDRV_Text(PHYSDEV dev, INT x, INT y, UINT flags, LPCWSTR str, UINT count, BOOL bDrawBackground, const INT *lpDx) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); - WORD *glyphs = NULL; - + LPCWSTR glyphs = str; + WORD *allocatedGlyphs = NULL; + WORD glyphBacking[DEFAULT_PARAGRAPH_SIZE]; if (!count) return TRUE; if(physDev->font.fontloc == Download && !(flags & ETO_GLYPH_INDEX)) { - glyphs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WORD) ); - GetGlyphIndicesW( dev->hdc, str, count, glyphs, 0 ); - str = glyphs; + WORD * rwglyphs; + if (count > DEFAULT_PARAGRAPH_SIZE) { + allocatedGlyphs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WORD) ); + rwglyphs = allocatedGlyphs; + }else { + rwglyphs = glyphBacking; + } + GetGlyphIndicesW( dev->hdc, str, count, rwglyphs, 0 ); + glyphs = rwglyphs; } PSDRV_WriteMoveTo(dev, x, y); if(!lpDx) { if(physDev->font.fontloc == Download) - PSDRV_WriteDownloadGlyphShow(dev, str, count); + PSDRV_WriteDownloadGlyphShow(dev, flags, glyphs, str, count); else PSDRV_WriteBuiltinGlyphShow(dev, str, count); } @@ -235,7 +243,7 @@ static BOOL PSDRV_Text(PHYSDEV dev, INT x, INT y, UINT flags, LPCWSTR str, for(i = 0; i < count-1; i++) { if(physDev->font.fontloc == Download) - PSDRV_WriteDownloadGlyphShow(dev, str + i, 1); + PSDRV_WriteDownloadGlyphShow(dev, flags, glyphs + i, str + i, 1); else PSDRV_WriteBuiltinGlyphShow(dev, str + i, 1); if(flags & ETO_PDY) @@ -248,11 +256,12 @@ static BOOL PSDRV_Text(PHYSDEV dev, INT x, INT y, UINT flags, LPCWSTR str, PSDRV_WriteMoveTo(dev, x + offset.x, y + offset.y); } if(physDev->font.fontloc == Download) - PSDRV_WriteDownloadGlyphShow(dev, str + i, 1); + PSDRV_WriteDownloadGlyphShow(dev, flags, glyphs + i, str + i, 1); else PSDRV_WriteBuiltinGlyphShow(dev, str + i, 1); } - - HeapFree( GetProcessHeap(), 0, glyphs ); + if (allocatedGlyphs != NULL) { + HeapFree( GetProcessHeap(), 0, allocatedGlyphs ); + } return TRUE; } diff --git a/dlls/wineps.drv/type42.c b/dlls/wineps.drv/type42.c index c0cda50..6bbb19e 100644 --- a/dlls/wineps.drv/type42.c +++ b/dlls/wineps.drv/type42.c @@ -279,8 +279,8 @@ TYPE42 *T42_download_header(PHYSDEV dev, char *ps_name, -BOOL T42_download_glyph(PHYSDEV dev, DOWNLOAD *pdl, DWORD index, - char *glyph_name) +BOOL T42_download_glyph_helper(PHYSDEV dev, DOWNLOAD *pdl, DWORD index, + char *glyph_name, BOOL cache_font_as_downloaded) { DWORD start, end, i; char *buf; @@ -326,8 +326,8 @@ BOOL T42_download_glyph(PHYSDEV dev, DOWNLOAD *pdl, DWORD index, sg_index = GET_BE_WORD(sg_start + 2); TRACE("Sending subglyph %04x for glyph %04x\n", sg_index, index); - get_glyph_name(dev->hdc, sg_index, sg_name); - T42_download_glyph(dev, pdl, sg_index, sg_name); + get_glyph_name(dev->hdc, FALSE, sg_index, sg_name); + T42_download_glyph_helper(dev, pdl, sg_index, sg_name, FALSE); sg_start += 4; if(sg_flags & ARG_1_AND_2_ARE_WORDS) sg_start += 4; @@ -363,12 +363,20 @@ BOOL T42_download_glyph(PHYSDEV dev, DOWNLOAD *pdl, DWORD index, PSDRV_WriteSpool(dev, ">\n", 2); sprintf(buf, glyph_def, pdl->ps_name, index, glyph_name, index); PSDRV_WriteSpool(dev, buf, strlen(buf)); - - t42->glyph_sent[index] = TRUE; + if (cache_font_as_downloaded) { /* while making composite glyphs don't + record as having sent each subglyph */ + t42->glyph_sent[index] = TRUE; + } HeapFree(GetProcessHeap(), 0, buf); return TRUE; } +BOOL T42_download_glyph(PHYSDEV dev, DOWNLOAD *pdl, DWORD index, + char *glyph_name) +{ + return T42_download_glyph_helper(dev, pdl, index, glyph_name, TRUE); +} + void T42_free(TYPE42 *t42) { OTTable *table; -- 1.8.4.2