gdi32: Fix glyph orientation for inverted axis in compatible mode. (try 3)

Alexander Kochetkov al.kochet at gmail.com
Mon Feb 28 17:14:59 CST 2011


-------------- next part --------------
From f9681b936516c362a4849db7d95798afa1a69350 Mon Sep 17 00:00:00 2001
From: Alexander Kochetkov <al.kochet at gmail.com>
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


More information about the wine-patches mailing list