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@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) );