/*
 *	PostScript driver text functions
 *
 *	Copyright 1998  Huw D M Davies
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>

#include "windef.h"
#include "wingdi.h"
#include "psdrv.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(psdrv);

typedef struct tagRun {
    INT start;
    BOOL vertical;
    INT x;
    INT y;
}Run;

static BOOL PSDRV_Text(PHYSDEV dev, INT x, INT y, UINT flags,
		       LPCWSTR str, UINT count,
		       BOOL bDrawBackground, const INT *lpDx);

extern const unsigned short vertical_orientation_table[] DECLSPEC_HIDDEN;

static BOOL check_unicode_tategaki(WCHAR uchar)
{
    unsigned short orientation = vertical_orientation_table[vertical_orientation_table[vertical_orientation_table[uchar >> 8]+((uchar >> 4) & 0x0f)]+ (uchar & 0xf)];

    /* Type: U or Type: Tu */
    /* TODO Type: Tr,  Normally the logic for Tr would be that if
       Typographical substitution occurs, then do not rotate. However
       we have no facility at present to determine if GetGlyphIndices is
       successfully performing substitutions (well formed font) or not.
       Thus we are erroring on the side of the font being well formed,
       doing typographical substitution,  and so we are not doing rotation */
    return (orientation ==  1 || orientation == 2 || orientation == 3);
}

static Run* build_vertical_runs(PHYSDEV dev, UINT flags, LPCWSTR str, UINT count, INT *run_count)
{
    BOOL last_vert;
    INT start, end;
    INT array_size = 5;
    Run *run = HeapAlloc(GetProcessHeap(),0,sizeof(Run)*array_size);
    int index = 0;
    LOGFONTW lf;

    if (count && str && (!(flags & ETO_GLYPH_INDEX)) && GetObjectW( GetCurrentObject(dev->hdc, OBJ_FONT), sizeof(lf), &lf ) && (lf.lfFaceName[0] == '@'))
    {
        last_vert = check_unicode_tategaki(str[0]);
        start = end = 0;
        while (start < count)
        {
            int offset = 0;

            while (end < count && check_unicode_tategaki(str[end]) == last_vert)
                end++;

            run[index].start = start;
            run[index].vertical = last_vert;
            run[index].x = 0;
            run[index].y = 0;

            if (run[index].vertical)
            {
                TEXTMETRICW tm;
                GetTextMetricsW(dev->hdc, &tm);
                offset += PSDRV_XWStoDS(dev, tm.tmAscent - tm.tmInternalLeading);
            }

            if (start > 0)
            {
                SIZE size;
                GetTextExtentPointW(dev->hdc, str, start, &size);
                offset += PSDRV_XWStoDS(dev, size.cx);
            }

            if (offset)
            {
                double angle;
                angle = (lf.lfEscapement / 10.0) * M_PI / 180.0;
                run[index].y = -offset * sin(angle);
                run[index].x = -offset * cos(angle);
            }

            index ++;
            if (index >= array_size)
            {
                array_size *=2;
                run = HeapReAlloc(GetProcessHeap(), 0, run, sizeof(Run)*array_size);
            }
            start = end;
            if (start < count)
                last_vert = check_unicode_tategaki(str[end]);
        }
    }
    else
    {
        run[0].start = 0;
        run[0].vertical = 0;
        run[0].x = 0;
        run[0].y = 0;
        index = 1;
    }
    *run_count = index;
    return run;
}

/***********************************************************************
 *           PSDRV_ExtTextOut
 */
BOOL PSDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, UINT count,
                       const INT *lpDx )
{
    PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
    BOOL bResult = TRUE;
    BOOL bClipped = FALSE;
    BOOL bOpaque = FALSE;
    Run *runs = NULL;
    int run_count = 0;
    int i = 0;

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

    if(physDev->job.id == 0) return FALSE;

    runs = build_vertical_runs(dev, flags, str, count, &run_count);

    /* set draw background */
    if ((flags & ETO_OPAQUE) && (lprect != NULL))
    {
        PSDRV_SetClip(dev);
        PSDRV_WriteGSave(dev);
        PSDRV_WriteRectangle(dev, lprect->left, lprect->top, lprect->right - lprect->left,
                     lprect->bottom - lprect->top);

        bOpaque = TRUE;
        PSDRV_WriteSetColor(dev, &physDev->bkColor);
        PSDRV_WriteFill(dev);

        PSDRV_WriteGRestore(dev);
        PSDRV_ResetClip(dev);
    }

    while (i < run_count)
    {
        int cnt;

        if (i != run_count - 1)
            cnt = runs[i+1].start- runs[i].start;
        else
            cnt = count - runs[i].start;

        PSDRV_SetFont(dev, runs[i].vertical);

        PSDRV_SetClip(dev);

        /* set clipping */
        if ((flags & ETO_CLIPPED) && (lprect != NULL))
        {
            PSDRV_WriteGSave(dev);

            PSDRV_WriteRectangle(dev, lprect->left, lprect->top, lprect->right - lprect->left,
                     lprect->bottom - lprect->top);

            bClipped = TRUE;
            PSDRV_WriteClip(dev);

            bResult = PSDRV_Text(dev, runs[i].x+x, runs[i].y+y, flags, &str[runs[i].start], cnt, !(bClipped && bOpaque), (lpDx)?&lpDx[runs[i].start]:NULL);

            PSDRV_WriteGRestore(dev);
        }
        else
            bResult = PSDRV_Text(dev, runs[i].x+x, runs[i].y+y, flags, &str[runs[i].start], cnt, TRUE, (lpDx)?&lpDx[runs[i].start]:NULL);

        i++;
        PSDRV_ResetClip(dev);
    }

    HeapFree(GetProcessHeap(),0,runs);
    return bResult;
}

/***********************************************************************
 *           PSDRV_Text
 */
static BOOL PSDRV_Text(PHYSDEV dev, INT x, INT y, UINT flags, LPCWSTR str,
		       UINT count, BOOL bDrawBackground, const INT *lpDx)
{
    PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
    WORD *glyphs = NULL;

    if (!count)
	return TRUE;

    if(physDev->font.fontloc == Download && !(flags & ETO_GLYPH_INDEX))
    {
        glyphs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WORD) );
        GetGlyphIndicesW( dev->hdc, str, count, glyphs, 0 );
        str = glyphs;
    }

    PSDRV_WriteMoveTo(dev, x, y);

    if(!lpDx) {
        if(physDev->font.fontloc == Download)
	    PSDRV_WriteDownloadGlyphShow(dev, str, count);
	else
	    PSDRV_WriteBuiltinGlyphShow(dev, str, count);
    }
    else {
        UINT i;
	POINT offset = {0, 0};

        for(i = 0; i < count-1; i++) {
	    if(physDev->font.fontloc == Download)
	        PSDRV_WriteDownloadGlyphShow(dev, str + i, 1);
	    else
	        PSDRV_WriteBuiltinGlyphShow(dev, str + i, 1);
            if(flags & ETO_PDY)
            {
                offset.x += lpDx[i * 2];
                offset.y += lpDx[i * 2 + 1];
            }
            else
                offset.x += lpDx[i];
	    PSDRV_WriteMoveTo(dev, x + offset.x, y + offset.y);
	}
	if(physDev->font.fontloc == Download)
	    PSDRV_WriteDownloadGlyphShow(dev, str + i, 1);
	else
	    PSDRV_WriteBuiltinGlyphShow(dev, str + i, 1);
    }

    HeapFree( GetProcessHeap(), 0, glyphs );
    return TRUE;
}
