From: Alexander Kochetkov Subject: gdi32: Fix glyph orientation for inverted axis in compatible mode. (try 3) Message-Id: Date: Tue, 1 Mar 2011 02:14:59 +0300 From f9681b936516c362a4849db7d95798afa1a69350 Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Tue, 1 Mar 2011 02:01:21 +0300 Subject: [PATCH] gdi32: Fix glyph orientation for inverted axis in compatible mode. The direction of rotation of the glyph depends on the graphics mode and the polar axes. This is evident by the test application attached to bug #22996. I've attached a screenshot to the bug #22996, showing how the patch affects the output. The patch fixes the direction of rotation of glyphs using the orientation flag. I was unable to achieve the same result using the inverse of the coefficients in the transformation matrix. Also this patch fixes a typo from the previous version (the comparison of the field orientation). Also, this patch adds the orientation flag in the hash of winex11.drv (I saw an error without the change). Many thanks to Dmitry Timoshkov. Best regards, Alexander. --- dlls/gdi32/freetype.c | 17 +++++++++++++---- dlls/winex11.drv/xrender.c | 10 ++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 512e08b..c39d2c8 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -302,6 +302,7 @@ typedef struct { LOGFONTW lf; FMAT2 matrix; BOOL can_use_bitmap; + INT orientation; } FONT_DESC; typedef struct tagHFONTLIST { @@ -3251,6 +3252,7 @@ static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd) if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE; if(memcmp(&font->font_desc.lf, &fd->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE; if(!font->font_desc.can_use_bitmap != !fd->can_use_bitmap) return TRUE; + if(font->font_desc.orientation != fd->orientation) return TRUE; return strcmpiW(font->font_desc.lf.lfFaceName, fd->lf.lfFaceName); } @@ -3275,11 +3277,12 @@ static void calc_hash(FONT_DESC *pfd) if(!*pwc) break; } hash ^= !pfd->can_use_bitmap; + hash ^= pfd->orientation; pfd->hash = hash; return; } -static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pmat, BOOL can_use_bitmap) +static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pmat, BOOL can_use_bitmap, INT orientation) { GdiFont *ret; FONT_DESC fd; @@ -3289,6 +3292,7 @@ static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pma fd.lf = *plf; fd.matrix = *pmat; fd.can_use_bitmap = can_use_bitmap; + fd.orientation = orientation; calc_hash(&fd); /* try the child list */ @@ -3481,11 +3485,13 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) HFONTLIST *hflist; FMAT2 dcmat; FontSubst *psub = NULL; + INT orientation; if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL; lf.lfWidth = abs(lf.lfWidth); can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE; + orientation = lf.lfOrientation; TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n", debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic, @@ -3500,6 +3506,8 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) font scaling abilities. */ dcmat.eM11 = dcmat.eM22 = dc->vport2WorldValid ? fabs(dc->xformWorld2Vport.eM22) : 1.0; dcmat.eM21 = dcmat.eM12 = 0; + if (dc->vport2WorldValid && (dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0)) + orientation = -orientation; } /* Try to avoid not necessary glyph transformations */ @@ -3517,7 +3525,7 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) EnterCriticalSection( &freetype_cs ); /* check the cache first */ - if((ret = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) { + if((ret = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap, orientation)) != NULL) { TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont); LeaveCriticalSection( &freetype_cs ); return ret; @@ -3783,6 +3791,7 @@ found: GdiFont *cachedfont; /* FIXME: rotation of bitmap fonts is ignored */ + orientation = 0; height = abs(GDI_ROUND( (double)height * ret->font_desc.matrix.eM22 )); if (ret->aveWidth) ret->aveWidth = (double)ret->aveWidth * ret->font_desc.matrix.eM11; @@ -3790,7 +3799,7 @@ found: dcmat.eM11 = dcmat.eM22 = 1.0; /* As we changed the matrix, we need to search the cache for the font again, * otherwise we might explode the cache. */ - if((cachedfont = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap)) != NULL) { + if((cachedfont = find_in_cache(hfont, &lf, &dcmat, can_use_bitmap, orientation)) != NULL) { TRACE("Found cached font after non-scalable matrix rescale!\n"); free_font( ret ); LeaveCriticalSection( &freetype_cs ); @@ -3838,7 +3847,7 @@ found: select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN); } - ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0; + ret->orientation = orientation; ret->name = psub ? strdupW(psub->from.name) : strdupW(family->FamilyName); ret->underline = lf.lfUnderline ? 0xff : 0; ret->strikeout = lf.lfStrikeOut ? 0xff : 0; diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c index fde0b91..c14551f 100644 --- a/dlls/winex11.drv/xrender.c +++ b/dlls/winex11.drv/xrender.c @@ -119,6 +119,7 @@ typedef struct XFORM xform; SIZE devsize; /* size in device coords */ DWORD hash; + INT orientation; } LFANDSIZE; #define INITIAL_REALIZED_BUF_SIZE 128 @@ -641,6 +642,7 @@ static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2) if(memcmp(&p1->devsize, &p2->devsize, sizeof(p1->devsize))) return TRUE; if(memcmp(&p1->xform, &p2->xform, sizeof(p1->xform))) return TRUE; if(memcmp(&p1->lf, &p2->lf, offsetof(LOGFONTW, lfFaceName))) return TRUE; + if(p1->orientation != p2->orientation) return TRUE; return strcmpiW(p1->lf.lfFaceName, p2->lf.lfFaceName); } @@ -1033,6 +1035,7 @@ static void lfsz_calc_hash(LFANDSIZE *plfsz) hash ^= two_chars; if(!*pwc) break; } + hash ^= plfsz->orientation; plfsz->hash = hash; return; } @@ -1071,6 +1074,13 @@ BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE *physDev, HFONT hfont) TRACE("font transform %f %f %f %f\n", lfsz.xform.eM11, lfsz.xform.eM12, lfsz.xform.eM21, lfsz.xform.eM22); + lfsz.orientation = lfsz.lf.lfOrientation; + if (GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) + { + if (lfsz.xform.eM11 * lfsz.xform.eM22 < 0) + lfsz.orientation = -lfsz.orientation; + } + /* Not used fields, would break hashing */ lfsz.xform.eDx = lfsz.xform.eDy = 0; -- 1.7.0.4