Fix round-off issues in font spacing calculations

Warren_Baird at cimmetry.com Warren_Baird at cimmetry.com
Thu Feb 6 08:54:25 CST 2003



ChangeLog:

     Fix round-off issue in font spacing calculation in ExtTextOut in XRender.

Description:

     Using cummulative spacing offsets reduces round-off errors when
     converting from logical to device coordinates. Without this fix, the
     relative space between the last characters of a given input string varies
     when the scaling factor between logical and device coordinates changes.

Warren Baird : Warren_Baird at cimmetry.com
Dave Belanger

diff -ur clean/wine/dlls/x11drv/xrender.c wine/dlls/x11drv/xrender.c
--- clean/wine/dlls/x11drv/xrender.c     Wed Jan 29 15:30:55 2003
+++ wine/dlls/x11drv/xrender.c     Thu Jan 30 11:10:40 2003
@@ -916,7 +916,7 @@
     HDC hdc = physDev->hdc;
     DC *dc = physDev->dc;
     int textPixel, backgroundPixel;
-    INT *deltas = NULL;
+    INT *offsets = NULL;
     INT char_extra;

     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
@@ -1008,26 +1008,29 @@

     TRACE("real x,y %d,%d\n", x, y);

-    if((char_extra = GetTextCharacterExtra(physDev->hdc)) != 0) {
+    // Using cummulative spacing offsets reduces round-off errors when
+    // converting from logical to device coordinates.
+    if((char_extra = GetTextCharacterExtra(physDev->hdc)) != 0 || lpDx) {
         INT i;
-    SIZE tmpsz;
-        deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
-    for(i = 0; i < count; i++) {
-        deltas[i] = char_extra;
-        if(lpDx)
-            deltas[i] += lpDx[i];
-        else {
-            GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
-         deltas[i] += tmpsz.cx;
-        }
-    }
-    } else if(lpDx)
-        deltas = (INT*)lpDx;
-
-    if(deltas) {
-    width = 0;
-    for(idx = 0; idx < count; idx++)
-        width += deltas[idx];
+         long currentOffset = 0;
+        SIZE tmpsz;
+        offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
+        for(i = 0; i < count; i++) {
+             currentOffset += char_extra;
+            if(lpDx) {
+                currentOffset += lpDx[i];
+             }
+            else {
+                GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
+                   currentOffset += tmpsz.cx;
+            }
+              offsets[i] = currentOffset;
+        }
+    }
+
+    if(offsets) {
+        // Don't forget that offsets are cummulative.
+        width = offsets[count-1];
     } else {
     if(!done_extents) {[count-1];ets
         GetTextExtentPointI(hdc, glyphs, count, &sz);
@@ -1113,11 +1116,14 @@

     if ((data = X11DRV_GetRegionData( dc->hGCClipRgn, 0 )))
     {
+         if (data->rdh.nCount)
+         {
         wine_tsx11_lock();
         pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
                               physDev->org.x, physDev->org.y,
                               (XRectangle *)data->Buffer, data->rdh.nCount );
         wine_tsx11_unlock();
+         }
         HeapFree( GetProcessHeap(), 0, data );
     }
     }
@@ -1200,7 +1206,7 @@

     if(X11DRV_XRender_Installed) {
         wine_tsx11_lock();
-    if(!deltas)
+    if(!offsets)
         pXRenderCompositeString16(gdi_display, render_op,
                          physDev->xrender->tile_pict,
                          physDev->xrender->pict,
@@ -1218,7 +1224,8 @@
                           0, 0, physDev->org.x + x + xoff,
                           physDev->org.y + y + yoff,
                           glyphs + idx, 1);
-         offset += INTERNAL_XWSTODS(dc, deltas[idx]);
+              // Don't forget that offsets are cummulative.
+              offset = INTERNAL_XWSTODS(dc, offsets[idx]);
          xoff = offset * cosEsc;
          yoff = offset * -sinEsc;
         }
@@ -1236,8 +1243,8 @@
                      physDev->org.y + y + yoff,
                      entry->bitmaps[glyphs[idx]],
                      &entry->gis[glyphs[idx]]);
-         if(deltas) {
-             offset += INTERNAL_XWSTODS(dc, deltas[idx]);
+         if(offsets) {
+             offset = INTERNAL_XWSTODS(dc, offsets[idx]);
              xoff = offset * cosEsc;
              yoff = offset * -sinEsc;

@@ -1252,8 +1259,8 @@
                      physDev->org.y + y + yoff,
                      entry->bitmaps[glyphs[idx]],
                      &entry->gis[glyphs[idx]]);
-         if(deltas) {
-             offset += INTERNAL_XWSTODS(dc, deltas[idx]);
+         if(offsets) {
+             offset = INTERNAL_XWSTODS(dc, offsets[idx]);
              xoff = offset * cosEsc;
              yoff = offset * -sinEsc;

@@ -1286,8 +1293,8 @@
              extents.right = cur.x - entry->gis[glyphs[idx]].x +
entry->gis[glyphs[idx]].width;
          if(extents.bottom < cur.y - entry->gis[glyphs[idx]].y +
entry->gis[glyphs[idx]].height)
              extents.bottom = cur.y - entry->gis[glyphs[idx]].y +
entry->gis[glyphs[idx]].height;
-         if(deltas) {
-             offset += INTERNAL_XWSTODS(dc, deltas[idx]);
+         if(offsets) {
+             offset = INTERNAL_XWSTODS(dc, offsets[idx]);
              cur.x = offset * cosEsc;
              cur.y = offset * -sinEsc;
          } else {
@@ -1363,8 +1370,8 @@
                    entry->bitmaps[glyphs[idx]],
                    &entry->gis[glyphs[idx]],
                    dc->textColor);
-         if(deltas) {
-             offset += INTERNAL_XWSTODS(dc, deltas[idx]);
+         if(offsets) {
+             offset = INTERNAL_XWSTODS(dc, offsets[idx]);
              xoff = offset * cosEsc;
              yoff = offset * -sinEsc;
          } else {
@@ -1382,9 +1389,9 @@
     }
     LeaveCriticalSection(&xrender_cs);

-    if(deltas && deltas != lpDx)
-        HeapFree(GetProcessHeap(), 0, deltas);
-
+    if(offsets)
+        HeapFree(GetProcessHeap(), 0, offsets);
+
     if (flags & ETO_CLIPPED)
         RestoreVisRgn16( HDC_16(hdc) );






More information about the wine-patches mailing list