/*
 *	PostScript driver text functions
 *
 *	Copyright 1998  Huw D M Davies
 *
 */
#include <string.h>
#include "psdrv.h"
#include "debugtools.h"
#include "winspool.h"

DEFAULT_DEBUG_CHANNEL(psdrv)

static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
		       BOOL bDrawBackground);

/***********************************************************************
 *           PSDRV_ExtTextOut
 */
BOOL PSDRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags,
		       const RECT *lprect, LPCWSTR str, UINT count,
		       const INT *lpDx )
{
    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
    BOOL bResult = TRUE;
    BOOL bClipped = FALSE;
    BOOL bOpaque = FALSE;
    RECT rect;

    TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d)\n", x, y,
	  flags, debugstr_wn(str, count), count);

    /* write font if not already written */
    PSDRV_SetFont(dc);

    /* set clipping and/or draw background */
    if ((flags & (ETO_CLIPPED | ETO_OPAQUE)) && (lprect != NULL))
    {
	rect.left = XLPTODP(dc, lprect->left);
	rect.right = XLPTODP(dc, lprect->right);
	rect.top = YLPTODP(dc, lprect->top);
	rect.bottom = YLPTODP(dc, lprect->bottom);

	PSDRV_WriteGSave(dc);
	PSDRV_WriteRectangle(dc, rect.left, rect.top, rect.right - rect.left, 
			     rect.bottom - rect.top);

	if (flags & ETO_OPAQUE)
	{
	    bOpaque = TRUE;
	    PSDRV_WriteGSave(dc);
	    PSDRV_WriteSetColor(dc, &physDev->bkColor);
	    PSDRV_WriteFill(dc);
	    PSDRV_WriteGRestore(dc);
	}

	if (flags & ETO_CLIPPED)
	{
	    bClipped = TRUE;
	    PSDRV_WriteClip(dc);
	}

	bResult = PSDRV_Text(dc, x, y, str, count, !(bClipped && bOpaque)); 
	PSDRV_WriteGRestore(dc);
    }
    else
    {
	bResult = PSDRV_Text(dc, x, y, str, count, TRUE); 
    }

    return bResult;
}

/***********************************************************************
 *           PSDRV_Text
 */
static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
		       BOOL bDrawBackground)
{
    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
    LPWSTR strbuf;
    SIZE sz;

    strbuf = HeapAlloc( PSDRV_Heap, 0, (count + 1) * sizeof(WCHAR));
    if(!strbuf) {
        WARN("HeapAlloc failed\n");
        return FALSE;
    }

    if(dc->w.textAlign & TA_UPDATECP) {
	x = dc->w.CursPosX;
	y = dc->w.CursPosY;
    }

    x = XLPTODP(dc, x);
    y = YLPTODP(dc, y);

    GetTextExtentPoint32W(dc->hSelf, str, count, &sz);
    sz.cx = XLSTODS(dc, sz.cx);
    sz.cy = YLSTODS(dc, sz.cy);

    switch(dc->w.textAlign & (TA_LEFT | TA_CENTER | TA_RIGHT) ) {
    case TA_LEFT:
        if(dc->w.textAlign & TA_UPDATECP)
	    dc->w.CursPosX = XDPTOLP(dc, x + sz.cx);
	break;

    case TA_CENTER:
	x -= sz.cx/2;
	break;

    case TA_RIGHT:
	x -= sz.cx;
	if(dc->w.textAlign & TA_UPDATECP)
	    dc->w.CursPosX = XDPTOLP(dc, x);
	break;
    }

    switch(dc->w.textAlign & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) {
    case TA_TOP:
        y += physDev->font.tm.tmAscent;
	break;

    case TA_BASELINE:
	break;

    case TA_BOTTOM:
        y -= physDev->font.tm.tmDescent;
	break;
    }

    memcpy(strbuf, str, count * sizeof(WCHAR));
    *(strbuf + count) = '\0';
    
    if ((dc->w.backgroundMode != TRANSPARENT) && (bDrawBackground != FALSE))
    {
	PSDRV_WriteGSave(dc);
	PSDRV_WriteNewPath(dc);
	PSDRV_WriteRectangle(dc, x, y - physDev->font.tm.tmAscent, sz.cx, 
			     physDev->font.tm.tmAscent + 
			     physDev->font.tm.tmDescent);
	PSDRV_WriteSetColor(dc, &physDev->bkColor);
	PSDRV_WriteFill(dc);
	PSDRV_WriteGRestore(dc);
    }

    PSDRV_WriteMoveTo(dc, x, y);
    PSDRV_WriteShow(dc, strbuf, lstrlenW(strbuf));

    /*
     * Underline and strikeout attributes.
     */
    if ((physDev->font.tm.tmUnderlined) || (physDev->font.tm.tmStruckOut)) {

        /* Get the thickness and the position for the underline attribute */
        /* We'll use the same thickness for the strikeout attribute       */

        float thick = physDev->font.afm->UnderlineThickness * physDev->font.scale;
        float pos   = -physDev->font.afm->UnderlinePosition * physDev->font.scale;
        SIZE size;
        INT escapement =  physDev->font.escapement;

        TRACE("Position = %f Thickness %f Escapement %d\n",
              pos, thick, escapement);

        /* Get the width of the text */

        PSDRV_GetTextExtentPoint(dc, strbuf, lstrlenW(strbuf), &size);
        size.cx = XLSTODS(dc, size.cx);

        /* Do the underline */

        if (physDev->font.tm.tmUnderlined) {
            if (escapement != 0)  /* rotated text */
            {
                PSDRV_WriteGSave(dc);  /* save the graphics state */
                PSDRV_WriteMoveTo(dc, x, y); /* move to the start */

                /* temporarily rotate the coord system */
                PSDRV_WriteRotate(dc, -escapement/10); 
                
                /* draw the underline relative to the starting point */
                PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
            }
            else
                PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);

            PSDRV_WriteFill(dc);

            if (escapement != 0)  /* rotated text */
                PSDRV_WriteGRestore(dc);  /* restore the graphics state */
        }

        /* Do the strikeout */

        if (physDev->font.tm.tmStruckOut) {
            pos = -physDev->font.tm.tmAscent / 2;

            if (escapement != 0)  /* rotated text */
            {
                PSDRV_WriteGSave(dc);  /* save the graphics state */
                PSDRV_WriteMoveTo(dc, x, y); /* move to the start */

                /* temporarily rotate the coord system */
                PSDRV_WriteRotate(dc, -escapement/10);

                /* draw the underline relative to the starting point */
                PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
            }
            else
                PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);

            PSDRV_WriteFill(dc);

            if (escapement != 0)  /* rotated text */
                PSDRV_WriteGRestore(dc);  /* restore the graphics state */
        }
    }

    HeapFree(PSDRV_Heap, 0, strbuf);
    return TRUE;
}
