Beispiel #1
0
static
void X11DRV_DrawText_dbcs_2fonts( fontObject* pfo, Display* pdisp, Drawable d,
                                  GC gc, int x, int y, XTextItem16* pitems,
                                  int count )
{
    int i, nitems, prevfont = -1, curfont;
    XChar2b* pstr;
    XTextItem16* ptibuf;
    XTextItem16* pti;
    fontObject* pfos[X11FONT_REFOBJS_MAX+1];

    pfos[0] = XFONT_GetFontObject( pfo->prefobjs[0] );
    pfos[1] = pfo;
    if ( pfos[0] == NULL ) pfos[0] = pfo;

    nitems = 0;
    for ( i = 0; i < count; i++ )
	nitems += pitems->nchars;
    ptibuf = HeapAlloc( GetProcessHeap(), 0, sizeof(XTextItem16) * nitems );
    if ( ptibuf == NULL )
	return; /* out of memory */

    pti = ptibuf;
    while ( count-- > 0 )
    {
	pti->chars = pstr = pitems->chars;
	pti->delta = pitems->delta;
	pti->font = None;
	for ( i = 0; i < pitems->nchars; i++, pstr++ )
	{
	    curfont = ( pstr->byte1 != 0 ) ? 1 : 0;
	    if ( curfont != prevfont )
	    {
		if ( pstr != pti->chars )
		{
		    pti->nchars = pstr - pti->chars;
		    pti ++;
		    pti->chars = pstr;
		    pti->delta = 0;
		}
		pti->font = pfos[curfont]->fs->fid;
		prevfont = curfont;
	    }
	}
	pti->nchars = pstr - pti->chars;
	pitems ++; pti ++;
    }
    wine_tsx11_lock();
    XDrawText16( pdisp, d, gc, x, y, ptibuf, pti - ptibuf );
    wine_tsx11_unlock();
    HeapFree( GetProcessHeap(), 0, ptibuf );
}
Beispiel #2
0
Datei: text.c Projekt: bpon/wine
/***********************************************************************
 *           X11DRV_GetTextExtentExPoint
 */
BOOL X11DRV_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR str, INT count,
                                  INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size )
{
    X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
    fontObject* pfo = XFONT_GetFontObject( physDev->font );

    TRACE("%s %d\n", debugstr_wn(str,count), count);
    if( pfo ) {
	XChar2b *p = X11DRV_cptable[pfo->fi->cptable].punicode_to_char2b( pfo, str, count );
	if (!p) return FALSE;
        if( !pfo->lpX11Trans ) {
	    int dir, ascent, descent;
	    int info_width;
	    X11DRV_cptable[pfo->fi->cptable].pTextExtents( pfo, p,
				count, &dir, &ascent, &descent, &info_width,
				maxExt, lpnFit, alpDx );

          size->cx = info_width;
          size->cy = pfo->fs->ascent + pfo->fs->descent;
	} else {
	    INT i;
	    INT nfit = 0;
	    float x = 0.0, y = 0.0;
	    float scaled_x = 0.0, pixsize = pfo->lpX11Trans->pixelsize;
	    /* FIXME: Deal with *_char_or_byte2 != 0 situations */
	    for(i = 0; i < count; i++) {
	        x += pfo->fs->per_char ?
	   pfo->fs->per_char[p[i].byte2 - pfo->fs->min_char_or_byte2].attributes :
	   pfo->fs->min_bounds.attributes;
	        scaled_x = x * pixsize / 1000.0;
	        if (alpDx)
	            alpDx[i] = scaled_x;
	        if (scaled_x <= maxExt)
	            ++nfit;
	    }
	    y = pfo->lpX11Trans->RAW_ASCENT + pfo->lpX11Trans->RAW_DESCENT;
	    TRACE("x = %f y = %f\n", x, y);
	    size->cx = x * pfo->lpX11Trans->pixelsize / 1000.0;
	    size->cy = y * pfo->lpX11Trans->pixelsize / 1000.0;
	    if (lpnFit)
	        *lpnFit = nfit;
	}
	size->cx *= pfo->rescale;
	size->cy *= pfo->rescale;
	HeapFree( GetProcessHeap(), 0, p );
	return TRUE;
    }

    dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPoint );
    return dev->funcs->pGetTextExtentExPoint( dev, str, count, maxExt, lpnFit, alpDx, size );
}
Beispiel #3
0
static
void X11DRV_TextExtents_dbcs_2fonts( fontObject* pfo, XChar2b* pstr, int count,
                                     int* pdir, int* pascent, int* pdescent,
                                     int* pwidth, int max_extent, int* pfit,
                                     int* partial_extents )
{
    XCharStruct info;
    int ascent, descent, width;
    int i;
    int fit;
    int curfont;
    fontObject* pfos[X11FONT_REFOBJS_MAX+1];

    pfos[0] = XFONT_GetFontObject( pfo->prefobjs[0] );
    pfos[1] = pfo;
    if ( pfos[0] == NULL ) pfos[0] = pfo;

    width = 0;
    fit = 0;
    *pascent = 0;
    *pdescent = 0;
    wine_tsx11_lock();
    for ( i = 0; i < count; i++ )
    {
	curfont = ( pstr->byte1 != 0 ) ? 1 : 0;
	XTextExtents16( pfos[curfont]->fs, pstr, 1, pdir, &ascent, &descent, &info );
	if ( *pascent < ascent ) *pascent = ascent;
	if ( *pdescent < descent ) *pdescent = descent;
	width += info.width;
	if ( partial_extents ) partial_extents[i] = width;
	if ( width <= max_extent ) fit++;

	pstr ++;
    }
    wine_tsx11_unlock();
    *pwidth = width;
    if ( pfit ) *pfit = fit;
}
Beispiel #4
0
static
int X11DRV_TextWidth_dbcs_2fonts( fontObject* pfo, XChar2b* pstr, int count )
{
    int i;
    int width;
    int curfont;
    fontObject* pfos[X11FONT_REFOBJS_MAX+1];

    pfos[0] = XFONT_GetFontObject( pfo->prefobjs[0] );
    pfos[1] = pfo;
    if ( pfos[0] == NULL ) pfos[0] = pfo;

    width = 0;
    wine_tsx11_lock();
    for ( i = 0; i < count; i++ )
    {
	curfont = ( pstr->byte1 != 0 ) ? 1 : 0;
	width += XTextWidth16( pfos[curfont]->fs, pstr, 1 );
	pstr ++;
    }
    wine_tsx11_unlock();
    return width;
}
Beispiel #5
0
/***********************************************************************
 *           X11DRV_ExtTextOut
 */
BOOL CDECL
X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
                   const RECT *lprect, LPCWSTR wstr, UINT count,
                   const INT *lpDx )
{
    unsigned int i;
    fontObject*		pfo;
    XFontStruct*	font;
    BOOL		rotated = FALSE;
    XChar2b		*str2b = NULL;
    BOOL		dibUpdateFlag = FALSE;
    BOOL                result = TRUE;
    HRGN                saved_region = 0;

    if(physDev->has_gdi_font)
        return X11DRV_XRender_ExtTextOut(physDev, x, y, flags, lprect, wstr, count, lpDx);

    if (!X11DRV_SetupGCForText( physDev )) return TRUE;

    pfo = XFONT_GetFontObject( physDev->font );
    font = pfo->fs;

    if (pfo->lf.lfEscapement && pfo->lpX11Trans)
        rotated = TRUE;

    TRACE("hdc=%p df=%04x %d,%d %s, %d  flags=%d lpDx=%p\n",
	  physDev->hdc, (UINT16)(physDev->font), x, y,
	  debugstr_wn (wstr, count), count, flags, lpDx);

    if (lprect != NULL) TRACE("\trect=(%d,%d - %d,%d)\n",
                                     lprect->left, lprect->top,
                                     lprect->right, lprect->bottom );

      /* Draw the rectangle */

    if (flags & ETO_OPAQUE)
    {
        X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
        dibUpdateFlag = TRUE;
        wine_tsx11_lock();
        XSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel );
        XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
                        physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top,
                        lprect->right - lprect->left, lprect->bottom - lprect->top );
        wine_tsx11_unlock();
    }
    if (!count) goto END;  /* Nothing more to do */


      /* Set the clip region */

    if (flags & ETO_CLIPPED)
    {
        HRGN clip_region;

        clip_region = CreateRectRgnIndirect( lprect );
        /* make a copy of the current device region */
        saved_region = CreateRectRgn( 0, 0, 0, 0 );
        CombineRgn( saved_region, physDev->region, 0, RGN_COPY );
        X11DRV_SetDeviceClipping( physDev, saved_region, clip_region );
        DeleteObject( clip_region );
    }

      /* Draw the text background if necessary */

    if (!dibUpdateFlag)
    {
        X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
        dibUpdateFlag = TRUE;
    }


    /* Draw the text (count > 0 verified) */
    if (!(str2b = X11DRV_cptable[pfo->fi->cptable].punicode_to_char2b( pfo, wstr, count )))
        goto FAIL;

    wine_tsx11_lock();
    XSetForeground( gdi_display, physDev->gc, physDev->textPixel );
    wine_tsx11_unlock();
    if(!rotated)
    {
        if (!lpDx)
        {
            X11DRV_cptable[pfo->fi->cptable].pDrawString(
                           pfo, gdi_display, physDev->drawable, physDev->gc,
                           physDev->dc_rect.left + x, physDev->dc_rect.top + y, str2b, count );
        }
        else
        {
            XTextItem16 *items, *pitem;

            pitem = items = HeapAlloc( GetProcessHeap(), 0,
                                       count * sizeof(XTextItem16) );
            if(items == NULL) goto FAIL;

            for(i = 0; i < count; i++)
            {
                pitem->chars  = str2b + i;
                pitem->delta  = lpDx[i];
                pitem->nchars = 1;
                pitem->font   = None;
                pitem++;
            }

            X11DRV_cptable[pfo->fi->cptable].pDrawText( pfo, gdi_display,
                                  physDev->drawable, physDev->gc,
                                  physDev->dc_rect.left + x, physDev->dc_rect.top + y, items, pitem - items );
            HeapFree( GetProcessHeap(), 0, items );
        }
    }
    else /* rotated */
    {
        /* have to render character by character. */
        double offset = 0.0;
        UINT i;

        for (i=0; i<count; i++)
        {
            int char_metric_offset = str2b[i].byte2 + (str2b[i].byte1 << 8)
                - font->min_char_or_byte2;
            int x_i = IROUND((double) (physDev->dc_rect.left + x) + offset *
                             pfo->lpX11Trans->a / pfo->lpX11Trans->pixelsize );
            int y_i = IROUND((double) (physDev->dc_rect.top + y) - offset *
                             pfo->lpX11Trans->b / pfo->lpX11Trans->pixelsize );

            X11DRV_cptable[pfo->fi->cptable].pDrawString(
                                    pfo, gdi_display, physDev->drawable, physDev->gc,
                                    x_i, y_i, &str2b[i], 1);
            if (lpDx)
            {
                offset += lpDx[i];
            }
            else
            {
                offset += (double) (font->per_char ?
                                    font->per_char[char_metric_offset].attributes:
                                    font->min_bounds.attributes)
                    * pfo->lpX11Trans->pixelsize / 1000.0;
            }
        }
    }
    HeapFree( GetProcessHeap(), 0, str2b );

    if (flags & ETO_CLIPPED)
    {
        /* restore the device region */
        X11DRV_SetDeviceClipping( physDev, saved_region, 0 );
        DeleteObject( saved_region );
    }
    goto END;

FAIL:
    HeapFree( GetProcessHeap(), 0, str2b );
    result = FALSE;

END:
    if (dibUpdateFlag) X11DRV_UnlockDIBSection( physDev, TRUE );
    return result;
}
Beispiel #6
0
static void X11DRV_GetTextMetricsW_cp932( fontObject* pfo, LPTEXTMETRICW pTM )
{
    fontObject* pfo_ansi = XFONT_GetFontObject( pfo->prefobjs[0] );
    LPIFONTINFO16 pdf = &pfo->fi->df;
    LPIFONTINFO16 pdf_ansi;

    pdf_ansi = ( pfo_ansi != NULL ) ? (&pfo_ansi->fi->df) : pdf;

    if( ! pfo->lpX11Trans ) {
      pTM->tmAscent = pfo->fs->ascent;
      pTM->tmDescent = pfo->fs->descent;
    } else {
      pTM->tmAscent = pfo->lpX11Trans->ascent;
      pTM->tmDescent = pfo->lpX11Trans->descent;
    }

    pTM->tmAscent *= pfo->rescale;
    pTM->tmDescent *= pfo->rescale;

    pTM->tmHeight = pTM->tmAscent + pTM->tmDescent;

    if ( pfo_ansi != NULL )
    {
	pTM->tmAveCharWidth = floor((pfo_ansi->foAvgCharWidth * 2.0 + pfo->foAvgCharWidth) / 3.0 * pfo->rescale + 0.5);
	pTM->tmMaxCharWidth = max(pfo_ansi->foMaxCharWidth, pfo->foMaxCharWidth) * pfo->rescale;
    }
    else
    {
	pTM->tmAveCharWidth = floor((pfo->foAvgCharWidth * pfo->rescale + 1.0) / 2.0);
	pTM->tmMaxCharWidth = pfo->foMaxCharWidth * pfo->rescale;
    }

    pTM->tmInternalLeading = pfo->foInternalLeading * pfo->rescale;
    pTM->tmExternalLeading = pdf->dfExternalLeading * pfo->rescale;

    pTM->tmStruckOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT )
			? 1 : pdf->dfStrikeOut;
    pTM->tmUnderlined = (pfo->fo_flags & FO_SYNTH_UNDERLINE )
			? 1 : pdf->dfUnderline;

    pTM->tmOverhang = 0;
    if( pfo->fo_flags & FO_SYNTH_ITALIC )
    {
	pTM->tmOverhang += pTM->tmHeight/3;
	pTM->tmItalic = 1;
    } else
	pTM->tmItalic = pdf->dfItalic;

    pTM->tmWeight = pdf->dfWeight;
    if( pfo->fo_flags & FO_SYNTH_BOLD )
    {
	pTM->tmOverhang++;
	pTM->tmWeight += 100;
    }

    pTM->tmFirstChar = pdf_ansi->dfFirstChar;
    pTM->tmLastChar = pdf_ansi->dfLastChar;
    pTM->tmDefaultChar = pdf_ansi->dfDefaultChar;
    pTM->tmBreakChar = pdf_ansi->dfBreakChar;

    pTM->tmCharSet = pdf->dfCharSet;
    pTM->tmPitchAndFamily = pdf->dfPitchAndFamily;

    pTM->tmDigitizedAspectX = pdf->dfHorizRes;
    pTM->tmDigitizedAspectY = pdf->dfVertRes;
}
Beispiel #7
0
/**********************************************************************
 *           ExtEscape  (X11DRV.@)
 */
INT X11DRV_ExtEscape( X11DRV_PDEVICE *physDev, INT escape, INT in_count, LPCVOID in_data,
                      INT out_count, LPVOID out_data )
{
    switch(escape)
    {
    case QUERYESCSUPPORT:
        if (in_data)
        {
            switch (*(const INT *)in_data)
            {
            case DCICOMMAND:
                return DD_HAL_VERSION;
            case X11DRV_ESCAPE:
                return TRUE;
            }
        }
        break;

    case DCICOMMAND:
        if (in_data)
        {
            const DCICMD *lpCmd = in_data;
            if (lpCmd->dwVersion != DD_VERSION) break;
            return X11DRV_DCICommand(in_count, lpCmd, out_data);
        }
        break;

    case X11DRV_ESCAPE:
        if (in_data && in_count >= sizeof(enum x11drv_escape_codes))
        {
            switch(*(const enum x11drv_escape_codes *)in_data)
            {
            case X11DRV_GET_DISPLAY:
                if (out_count >= sizeof(Display *))
                {
                    *(Display **)out_data = gdi_display;
                    return TRUE;
                }
                break;
            case X11DRV_GET_DRAWABLE:
                if (out_count >= sizeof(Drawable))
                {
                    *(Drawable *)out_data = physDev->drawable;
                    return TRUE;
                }
                break;
            case X11DRV_GET_FONT:
                if (out_count >= sizeof(Font))
                {
                    fontObject* pfo = XFONT_GetFontObject( physDev->font );
		    if (pfo == NULL) return FALSE;
                    *(Font *)out_data = pfo->fs->fid;
                    return TRUE;
                }
                break;
            case X11DRV_SET_DRAWABLE:
                if (in_count >= sizeof(struct x11drv_escape_set_drawable))
                {
                    const struct x11drv_escape_set_drawable *data = (const struct x11drv_escape_set_drawable *)in_data;
                    if(physDev->xrender) X11DRV_XRender_UpdateDrawable( physDev );
                    physDev->dc_rect = data->dc_rect;
                    physDev->drawable = data->drawable;
                    physDev->drawable_rect = data->drawable_rect;
                    physDev->current_pf = pixelformat_from_fbconfig_id( data->fbconfig_id );
                    physDev->gl_drawable = data->gl_drawable;
                    physDev->pixmap = data->pixmap;
                    physDev->gl_copy = data->gl_copy;
                    wine_tsx11_lock();
                    XSetSubwindowMode( gdi_display, physDev->gc, data->mode );
                    wine_tsx11_unlock();
                    TRACE( "SET_DRAWABLE hdc %p drawable %lx gl_drawable %lx pf %u dc_rect %s drawable_rect %s\n",
                           physDev->hdc, physDev->drawable, physDev->gl_drawable, physDev->current_pf,
                           wine_dbgstr_rect(&physDev->dc_rect), wine_dbgstr_rect(&physDev->drawable_rect) );
                    return TRUE;
                }
                break;
            case X11DRV_START_EXPOSURES:
                wine_tsx11_lock();
                XSetGraphicsExposures( gdi_display, physDev->gc, True );
                wine_tsx11_unlock();
                physDev->exposures = 0;
                return TRUE;
            case X11DRV_END_EXPOSURES:
                if (out_count >= sizeof(HRGN))
                {
                    HRGN hrgn = 0, tmp = 0;

                    wine_tsx11_lock();
                    XSetGraphicsExposures( gdi_display, physDev->gc, False );
                    wine_tsx11_unlock();
                    if (physDev->exposures)
                    {
                        for (;;)
                        {
                            XEvent event;

                            wine_tsx11_lock();
                            XWindowEvent( gdi_display, physDev->drawable, ~0, &event );
                            wine_tsx11_unlock();
                            if (event.type == NoExpose) break;
                            if (event.type == GraphicsExpose)
                            {
                                int x = event.xgraphicsexpose.x - physDev->dc_rect.left;
                                int y = event.xgraphicsexpose.y - physDev->dc_rect.top;

                                TRACE( "got %d,%d %dx%d count %d\n", x, y,
                                       event.xgraphicsexpose.width,
                                       event.xgraphicsexpose.height,
                                       event.xgraphicsexpose.count );

                                if (!tmp) tmp = CreateRectRgn( 0, 0, 0, 0 );
                                SetRectRgn( tmp, x, y,
                                            x + event.xgraphicsexpose.width,
                                            y + event.xgraphicsexpose.height );
                                if (hrgn) CombineRgn( hrgn, hrgn, tmp, RGN_OR );
                                else
                                {
                                    hrgn = tmp;
                                    tmp = 0;
                                }
                                if (!event.xgraphicsexpose.count) break;
                            }
                            else
                            {
                                ERR( "got unexpected event %d\n", event.type );
                                break;
                            }
                        }
                        if (tmp) DeleteObject( tmp );
                    }
                    *(HRGN *)out_data = hrgn;
                    return TRUE;
                }
                break;
            case X11DRV_GET_DCE:
            case X11DRV_SET_DCE:
                FIXME( "%x escape no longer supported\n", *(const enum x11drv_escape_codes *)in_data );
                break;
            case X11DRV_GET_GLX_DRAWABLE:
                if (out_count >= sizeof(Drawable))
                {
                    *(Drawable *)out_data = get_glxdrawable(physDev);
                    return TRUE;
                }
                break;
            case X11DRV_SYNC_PIXMAP:
                if(physDev->bitmap)
                {
                    X11DRV_CoerceDIBSection(physDev, DIB_Status_GdiMod);
                    return TRUE;
                }
                return FALSE;
            case X11DRV_FLUSH_GL_DRAWABLE:
                flush_gl_drawable(physDev);
                return TRUE;
            }
        }
        break;
    }
    return 0;
}
Beispiel #8
0
Datei: text.c Projekt: bpon/wine
/***********************************************************************
 *           X11DRV_ExtTextOut
 */
BOOL X11DRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
                        const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx )
{
    X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
    BOOL restore_region = FALSE;
    unsigned int i;
    fontObject*		pfo = XFONT_GetFontObject( physDev->font );
    XFontStruct*	font;
    BOOL		rotated = FALSE;
    XChar2b		*str2b = NULL;
    BOOL		dibUpdateFlag = FALSE;
    BOOL                result = TRUE;

    if (!pfo)
    {
        dev = GET_NEXT_PHYSDEV( dev, pExtTextOut );
        return dev->funcs->pExtTextOut( dev, x, y, flags, lprect, wstr, count, lpDx );
    }

    if (!X11DRV_SetupGCForText( physDev )) return TRUE;

    font = pfo->fs;

    if (pfo->lf.lfEscapement && pfo->lpX11Trans)
        rotated = TRUE;

    TRACE("hdc=%p df=%04x %d,%d rc %s %s, %d  flags=%d lpDx=%p\n",
          dev->hdc, (UINT16)physDev->font, x, y, wine_dbgstr_rect(lprect),
	  debugstr_wn (wstr, count), count, flags, lpDx);

      /* Draw the rectangle */

    if (flags & ETO_OPAQUE)
    {
        X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
        dibUpdateFlag = TRUE;
        wine_tsx11_lock();
        XSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel );
        XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
                        physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top,
                        lprect->right - lprect->left, lprect->bottom - lprect->top );
        wine_tsx11_unlock();
    }
    if (!count) goto END;  /* Nothing more to do */


      /* Set the clip region */

    if (flags & ETO_CLIPPED)
    {
        HRGN clip_region = CreateRectRgnIndirect( lprect );
        restore_region = add_extra_clipping_region( physDev, clip_region );
        DeleteObject( clip_region );
    }

      /* Draw the text background if necessary */

    if (!dibUpdateFlag)
    {
        X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
        dibUpdateFlag = TRUE;
    }


    /* Draw the text (count > 0 verified) */
    if (!(str2b = X11DRV_cptable[pfo->fi->cptable].punicode_to_char2b( pfo, wstr, count )))
    {
        result = FALSE;
        goto END;
    }

    wine_tsx11_lock();
    XSetForeground( gdi_display, physDev->gc, physDev->textPixel );
    wine_tsx11_unlock();
    if(!rotated)
    {
        if (!lpDx)
        {
            X11DRV_cptable[pfo->fi->cptable].pDrawString(
                           pfo, gdi_display, physDev->drawable, physDev->gc,
                           physDev->dc_rect.left + x, physDev->dc_rect.top + y, str2b, count );
        }
        else
        {
            XTextItem16 *items;

            items = HeapAlloc( GetProcessHeap(), 0, count * sizeof(XTextItem16) );
            if(items == NULL)
            {
                result = FALSE;
                goto END;
            }
            items[0].chars = str2b;
            items[0].delta = 0;
            items[0].nchars = 1;
            items[0].font = None;
            for(i = 1; i < count; i++)
            {
                items[i].chars  = str2b + i;
                items[i].delta  = (flags & ETO_PDY) ? lpDx[(i - 1) * 2] : lpDx[i - 1];
                items[i].delta -= X11DRV_cptable[pfo->fi->cptable].pTextWidth( pfo, str2b + i - 1, 1 );
                items[i].nchars = 1;
                items[i].font   = None;
            }
            X11DRV_cptable[pfo->fi->cptable].pDrawText( pfo, gdi_display,
                                  physDev->drawable, physDev->gc,
                                  physDev->dc_rect.left + x, physDev->dc_rect.top + y, items, count );
            HeapFree( GetProcessHeap(), 0, items );
        }
    }
    else /* rotated */
    {
        /* have to render character by character. */
        double offset = 0.0;
        UINT i;

        for (i=0; i<count; i++)
        {
            int char_metric_offset = str2b[i].byte2 + (str2b[i].byte1 << 8)
                - font->min_char_or_byte2;
            int x_i = IROUND((double) (physDev->dc_rect.left + x) + offset *
                             pfo->lpX11Trans->a / pfo->lpX11Trans->pixelsize );
            int y_i = IROUND((double) (physDev->dc_rect.top + y) - offset *
                             pfo->lpX11Trans->b / pfo->lpX11Trans->pixelsize );

            X11DRV_cptable[pfo->fi->cptable].pDrawString(
                                    pfo, gdi_display, physDev->drawable, physDev->gc,
                                    x_i, y_i, &str2b[i], 1);
            if (lpDx)
            {
                offset += (flags & ETO_PDY) ? lpDx[i * 2] : lpDx[i];
            }
            else
            {
                offset += (double) (font->per_char ?
                                    font->per_char[char_metric_offset].attributes:
                                    font->min_bounds.attributes)
                    * pfo->lpX11Trans->pixelsize / 1000.0;
            }
        }
    }

END:
    HeapFree( GetProcessHeap(), 0, str2b );
    if (dibUpdateFlag) X11DRV_UnlockDIBSection( physDev, TRUE );
    if (restore_region) restore_clipping_region( physDev );
    return result;
}