/*
 * GraphApp - Cross-Platform Graphics Programming Library.
 *
 * File: drawing.c -- all the drawing functions are here.
 * Platform: Windows  Version: 2.40  Date: 1998/05/05
 *
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
 * Version: 1.60  Changes: drawarc/fillarc(r,0,360) now encloses.
 *    New fillellipse() function replaces Windows Ellipse().
 * Version: 2.00  Changes: New class system implemented.
 * Version: 2.02  Changes: Added support for functions like MoveToEx.
 * Version: 2.15  Changes: Fixed brush origins problem.
 * Version: 2.20  Changes: Moved some arrays from context.c to here.
 * Version: 2.40  Changes: Moved drawimage to this file.
 */

/* Copyright (C) 1993-1998 Lachlan Patrick

   This file is part of GraphApp, a cross-platform C graphics library.

   GraphApp is free software; you can redistribute it and/or modify it
   under the terms of the GNU Library General Public License.
   GraphApp is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY.

   See the file COPYLIB.TXT for details.
*/

/*  Copyright (C) 2004	The R Foundation

    Changes for R:

    Remove assumption of current->dest being non-NULL

 */

#include "internal.h"

#if (WINVER < 0x030a)

#define MoveToEx move_to_ex
#define GetCurrentPositionEx get_current_position_ex
#define GetTextExtentPoint get_text_extent_point

int move_to_ex(HDC hdc, int x, int y, POINT *p);
int get_current_position_ex(HDC hdc, POINT *p);
int get_text_extent_point(HDC hdc, const char *str, int len, SIZE *s);

static int move_to_ex(HDC hdc, int x, int y, POINT *p)
{
    DWORD result = MoveTo(hdc, x, y);
    if (p) {
	p->x = LOWORD(result);
	p->y = HIWORD(result);
    }
    return 1;
}

static int get_current_position_ex(HDC hdc, POINT *p)
{
    DWORD result = GetCurrentPosition(hdc);
    if (p) {
	p->x = LOWORD(result);
	p->y = HIWORD(result);
    }
    return 1;
}

static int get_text_extent_point(HDC hdc, const char *str, int len, SIZE *s)
{
    DWORD result = GetTextExtent(hdc, str, len);
    if (s) {
	s->cx = LOWORD(result);
	s->cy = HIWORD(result);
    }
    return 1;
}

#endif  /* WINVER < 0x030a */

/*
 *  Windows transfer modes corresponding to bitblt operations.
 */
static long copy_mode[16] = {
    BLACKNESS,	/* Zeros */
    NOTSRCERASE,	/* DnorS */
    0x00220326L,	/* DandnotS */
    NOTSRCCOPY,	/* notS */
    SRCERASE,	/* notDandS */
    DSTINVERT,	/* notD */
    SRCINVERT,	/* DxorS */
    0x007700E6L,	/* DnandS */
    SRCAND,		/* DandS */
    0x00990066L,	/* DxnorS */
    0x00AA0029L,	/* D */			/* = no-op */
    MERGEPAINT,	/* DornotS */
    SRCCOPY,	/* S */
    0x00DD0228L,	/* notDorS */
    SRCPAINT,	/* DorS */
    WHITENESS	/* Ones */
};

/*
 *  Windows transfer modes corresponding to patblt operations.
 */
static long pat_mode[16] = {
    BLACKNESS,	/* Zeros */
    0x000500A9L,	/* DnorP */
    0x000A0329L,	/* DandnotP */
    0x000F0001L,	/* notP */
    0x00500325L,	/* notDandP */
    DSTINVERT,	/* notD */
    PATINVERT,	/* DxorP */
    0x005F00E9L,	/* DnandP */
    0x00A000C9L,	/* DandP */
    0x00A50065L,	/* DxnorP */
    0x00AA0029L,	/* D */			/* = no-op */
    0x00AF0229L,	/* DornotP */
    PATCOPY,	/* P */
    0x00F50225L,	/* notDorP */
    0x00FA0089L,	/* DorP */
    WHITENESS	/* Ones */
};

/*
 *  Windows transfer modes corresponding to pen drawing.
 */
static int pen_mode[16] = {
    R2_BLACK,	/* Zeros */
    R2_NOTMERGEPEN,	/* DnorS */
    R2_MASKNOTPEN,	/* DandnotS */
    R2_NOTCOPYPEN,	/* notS */
    R2_MASKPENNOT,	/* notDandS */
    R2_NOT,		/* notD */
    R2_XORPEN,	/* DxorS */
    R2_NOTMASKPEN,	/* DnandS */
    R2_MASKPEN,	/* DandS */
    R2_NOTXORPEN,	/* DxnorS */
    R2_NOP,		/* D */			/* = no-op */
    R2_MERGENOTPEN,	/* DornotS */
    R2_COPYPEN,	/* S */
    R2_MERGEPENNOT,	/* notDorS */
    R2_MERGEPEN,	/* DorS */
    R2_WHITE	/* Ones */
};

/*
 *  Some clipping functions.
 */
rect getcliprect(void)
{
    RECT R;
    rect r;

    GetClipBox(dc, &R);
    r.x = R.left;
    r.y = R.top;
    r.width = R.right - R.left;
    r.height = R.bottom - R.top;
    return r;
}

void setcliprect(rect r)
{
    HRGN rgn;

    rgn = CreateRectRgn(r.x, r.y, r.x+r.width, r.y+r.height);
    SelectClipRgn(dc, rgn);
    DeleteObject(rgn);
}

/*
 *  Ensure that drawing is possible by creating DCs and windows
 *  as necessary.
 */
PROTECTED
window simple_window(void)
{
    window w;
    w = newwindow("Graphics", rect(0,0,0,0), StandardWindow);
    show(w);
    return w;
}

/*
 *  Fix brush origins.
 */
PROTECTED
void fix_brush(HDC dc, drawing obj, HBRUSH brush)
{
    POINT p;
    HWND hwnd;
    drawing parent;

    parent = parentwindow(obj);
    if (! parent)
	return;
    hwnd = parent->handle;
    p.x = p.y = 0;
    ClientToScreen(hwnd, &p);
    if (brush)
	UnrealizeObject(brush);
#if (WINVER <= 0x030a)
    /* Microsoft keeps changing which functions they include in GDI.DLL */
    /* But this function should work on systems before Win 95 */
    SetBrushOrg(dc, p.x, p.y);
#else
    /* And this function should work on Win 95 and NT */
    SetBrushOrgEx(dc, p.x, p.y, &p);
#endif
}

/*
 *  All drawing functions call enabledrawing.
 */
static void enable_drawing(void)
{
    if (! current->dest) {
	if (! current_window)
	    current_window = simple_window();
	show(current_window);
	drawto(current_window);
    }
    if (! dc)
	dc = get_context(current->dest);

    fix_brush(dc, current->dest, the_brush);
}

/*
 *  Drawing functions begin here.
 */
void bitblt(bitmap db, bitmap sb, point p, rect r, int mode)
{
    HDC src;
    HDC dst;

    dst = get_context((object)db);
    src = get_context((object)sb);

    BitBlt(dst, p.x, p.y, r.width, r.height, src, r.x, r.y,
	   copy_mode[mode&0x0F]);
}

void scrollrect(point dp, rect r)
{
    rect cliprect;
    if (current->dest) cliprect = getrect(current->dest);
    else return;

    enable_drawing();
    ScrollDC(dc, dp.x-r.x, dp.y-r.y,
	     rect2RECT(&r), rect2RECT(&cliprect), 0, NULL);
}

void copyrect(bitmap sb, point p, rect r)
{
    enable_drawing();
    if (current->dest) bitblt(current->dest, sb, p, r, S);
}

void texturerect(bitmap sb, rect dr)
{
    long x, y, sw, sh, sdx, sdy;
    long right, bottom;
    rect sr,r;

    enable_drawing();
    sr = getrect(sb);
    sw = sr.width;
    sh = sr.height;
    right = dr.x + dr.width;
    bottom = dr.y + dr.height;

    for (y = dr.y; y <= bottom; y += sh)
	for (x = dr.x; x <= right; x += sw) {

	    /* reduce size of source rectangle for clipping */
	    if (x+sw > right)	sdx = right - x;
	    else			sdx = sw;
	    if (y+sh > bottom)	sdy = bottom - y;
	    else			sdy = sh;

	    r = rect(sr.x, sr.y, sdx, sdy);
	    copyrect(sb, pt(x,y), r);
	}
}

void invertrect(rect r)
{
    enable_drawing();
    PatBlt(dc, r.x, r.y, r.width, r.height, DSTINVERT);
}

rgb getpixel(point p)
{
    rgb c;

    enable_drawing();
    c = GetPixel(dc, p.x, p.y);
    c = ((c&0x000000FFL)<<16) | (c&0x0000FF00L) |
	((c&0x00FF0000L)>>16);
    return c;
}

void setpixel(point p, rgb c)
{
    rgb old = current->hue;

    enable_drawing();
    setrgb(c);
    SelectObject(dc, the_brush);
    PatBlt(dc, p.x, p.y, 1, 1, pat_mode[current->mode]);
    SelectObject(dc, GetStockObject(NULL_BRUSH));
    setrgb(old);
}

void moveto(point p)
{
    current->p = p;
}

void lineto(point p)
{
    drawline(current->p, p);
    moveto(p);
}

void drawpoint(point p)
{
    setpixel(p, current->hue);
}

void drawline(point p1, point p2)
{
    if ((p1.x == p2.x) && (p1.y == p2.y))
	return; /* same point so draw nothing */

    enable_drawing();
    SelectObject(dc, the_pen);
    SetROP2(dc, pen_mode[current->mode]);
    MoveToEx(dc, p1.x, p1.y, NULL);
    LineTo(dc, p2.x, p2.y);
    SelectObject(dc, GetStockObject(NULL_PEN));
}

void drawrect(rect r)
{
    enable_drawing();
    SelectObject(dc, the_pen);
    SetROP2(dc, pen_mode[current->mode]);
    Rectangle(dc, r.x, r.y, r.x+r.width, r.y+r.height);
    SelectObject(dc, GetStockObject(NULL_PEN));
}

void fillrect(rect r)
{
    enable_drawing();
    SelectObject(dc, the_brush);
    PatBlt(dc, r.x, r.y, r.width, r.height, pat_mode[current->mode]);
    SelectObject(dc, GetStockObject(NULL_BRUSH));
}

#define deg2rad(deg) ((deg)*2*Pi/360)

void drawarc(rect r, int start_angle, int end_angle)
{
    point p0, p1, p2;
    double start, end;
    int fudge;

    enable_drawing();

    if (start_angle == end_angle)
	return;
    if (((end_angle - start_angle) % 360) == 0) {
	drawarc(r, 0, 180);
	drawarc(r, 180, 360);
	return;
    }

    start = deg2rad(start_angle);
    end = deg2rad(end_angle);
    p0 = midpt(topleft(r), bottomright(r));
    p1.x = p0.x + (int)(cos(start) * 512); /* arbitrary hypotenuse */
    p1.y = p0.y - (int)(sin(start) * 512);
    p2.x = p0.x + (int)(cos(end) * 512);
    p2.y = p0.y - (int)(sin(end) * 512);

    SelectObject(dc, the_pen);
    SetROP2(dc, pen_mode[current->mode]);
    if (current->linewidth % 2) /* Ask Bill Gates why we need this */
	fudge = 0;
    else
	fudge = 1;
    Arc(dc, r.x, r.y, r.x+r.width+fudge, r.y+r.height+fudge,
	p1.x, p1.y, p2.x, p2.y);
    SelectObject(dc, GetStockObject(NULL_PEN));
}

void fillarc(rect r, int start_angle, int end_angle)
{
    point p0, p1, p2;
    double start, end;

    enable_drawing();

    if (start_angle == end_angle)
	return;
    if (((end_angle - start_angle) % 360) == 0) {
	fillellipse(r);
	return;
    }

    start = deg2rad(start_angle);
    end = deg2rad(end_angle);
    p0 = midpt(topleft(r), bottomright(r));
    p1.x = p0.x + (int)(cos(start) * 512); /* arbitrary hypotenuse */
    p1.y = p0.y - (int)(sin(start) * 512);
    p2.x = p0.x + (int)(cos(end) * 512);
    p2.y = p0.y - (int)(sin(end) * 512);

    SelectObject(dc, the_brush);
    SetROP2(dc, pen_mode[current->mode]);
    Pie(dc, r.x, r.y, r.x+r.width+1, r.y+r.height+1,
	p1.x, p1.y, p2.x, p2.y);
    SelectObject(dc, GetStockObject(NULL_BRUSH));
}

void drawellipse(rect r)
{
    enable_drawing();
    SelectObject(dc, the_pen);
    SetROP2(dc, pen_mode[current->mode]);
    Ellipse(dc, r.x, r.y, r.x+r.width, r.y+r.height);
    SelectObject(dc, GetStockObject(NULL_PEN));
}

/*
 *  The old fillellipse function.
 *
 *  This function used the inbuilt Windows Ellipse function,
 *  which is not symmetric and also produces strange results
 *  at low sizes (the 'ellipses' look egg-shaped).
 */
void oldfillellipse(rect r)
{
    enable_drawing();
    SelectObject(dc, the_brush);
    SetROP2(dc, pen_mode[current->mode]);
    Ellipse(dc, r.x, r.y, r.x+r.width+1, r.y+r.height+1);
    SelectObject(dc, GetStockObject(NULL_BRUSH));
}

/*
 *  Fill an ellipse using a stored rectangle algorithm.
 *
 *  This algorithm is horizontally and vertically symmetrical,
 *  unlike the inbuilt Windows 3.1 algorithm, and also
 *  produces better looking ellipses at small sizes.
 */
#define fastfillrect(x,y,w,h) PatBlt(dc,(x),(y),(w),(h),mode)

void fillellipse(rect r)
{			/* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
    register long mode = pat_mode[current->mode];

    int w_odd = (r.width & 0x0001);
    int h_odd = (r.height & 0x0001);
    int a = r.width >> 1;
    int b = r.height >> 1;
    point c = pt(r.x+a,r.y+b);
    int x = 0;
    int y = b;
    long a2 = a*a;
    long b2 = b*b;
    long xcrit = ((a2+a2+a2) >> 2) + 1;
    long ycrit = ((b2+b2+b2) >> 2) + 1;
    long t = b2 + a2 - (a2+a2)*b;	/* t = e(x+1,y-1) */
    long dxt = b2*(3+x+x);
    long dyt = a2*(3-y-y);
    int d2xt = b2+b2;
    int d2yt = a2+a2;
    int stored = 0;
    int sx = 0, sy = 0, sh = 0; /* stored values of x, y, height */

    if ((r.width > 31) && (r.height > 31)) {
	oldfillellipse(r);
	return;
    }
    if ((r.width < 3) || (r.height < 3)) {
	fillrect(r);
	return;
    }

    enable_drawing();
    SelectObject(dc, the_brush);

    if (w_odd == 0) {
	fastfillrect(c.x-1,c.y-b,2,r.height);
    }

    while (y > 0) {

	if (stored) {
	    if (sx != x) { /* output stored rect */
		fastfillrect(c.x-sx,c.y-sy,
			     sx+sx+w_odd,sh);
		fastfillrect(c.x-sx,c.y+sy+h_odd-sh,
			     sx+sx+w_odd,sh);
		stored = 0;
	    }
	    else /* increment height of stored rect */
		sh++;
	}

	if (t + a2*y < xcrit) { /* e(x+1,y-1/2) <= 0 */
	    /* move left and right to encounter edge */
	    x += 1;
	    t += dxt;
	    dxt += d2xt;
	} else if (t - b2*x >= ycrit) { /* e(x+1/2,y-1) > 0 */
	    /* drop down one line */
	    if (!stored) {
		sx = x;
		sy = y;
		sh = 1;
		stored = 1;
	    }
	    y -= 1;
	    t += dyt;
	    dyt += d2yt;
	} else {
	    /* drop diagonally down and out */
	    if (!stored) {
		sx = x;
		sy = y;
		sh = 1;
		stored = 1;
	    }

	    x += 1;
	    y -= 1;
	    t += dxt + dyt;
	    dxt += d2xt;
	    dyt += d2yt;
	}
    }
    if (stored) { /* output stored rectangle */
	fastfillrect(c.x-sx,c.y-sy,sx+sx+w_odd,sh);
	fastfillrect(c.x-sx,c.y+sy+h_odd-sh,sx+sx+w_odd,sh);
	stored = 0;
    }
    if (x <= a){
	fastfillrect(c.x-a,c.y-y,a+a+w_odd,1);
	fastfillrect(c.x-a,c.y+y-1+h_odd,a+a+w_odd,1);
    }

    SelectObject(dc, GetStockObject(NULL_BRUSH));
}

void drawroundrect(rect r)
{
    int minimum, radius;

    enable_drawing();
    SelectObject(dc, the_pen);
    SetROP2(dc, pen_mode[current->mode]);
    minimum = min(r.width, r.height);
    if ((radius = minimum/2) < 16)
	radius = 16;
    RoundRect(dc, r.x, r.y, r.x+r.width, r.y+r.height,
	      radius, radius);
    SelectObject(dc, GetStockObject(NULL_PEN));
}

void fillroundrect(rect r)
{
    int minimum, radius;

    enable_drawing();
    SelectObject(dc, the_brush);
    SetROP2(dc, pen_mode[current->mode]);
    minimum = min(r.width, r.height);
    if ((radius = minimum/2) < 16)
	radius = 16;
    RoundRect(dc, r.x, r.y, r.x+r.width+1, r.y+r.height+1,
	      radius, radius);
    SelectObject(dc, GetStockObject(NULL_BRUSH));
}

void drawpolygon(point *p, int n)
{
    enable_drawing();
    SelectObject(dc, the_pen);
    SetROP2(dc, pen_mode[current->mode]);
    Polyline(dc, (POINT FAR *) p, n);
    SelectObject(dc, GetStockObject(NULL_PEN));
}

void fillpolygon(point *p, int n)
{
    enable_drawing();
    SelectObject(dc, the_brush);
    SetROP2(dc, pen_mode[current->mode]);
    Polygon(dc, (POINT FAR *) p, n);
    SelectObject(dc, GetStockObject(NULL_BRUSH));
}

/*
 *  String drawing functions.
 */

/*
 *  Drawstr returns the width of the string drawn.
 */
int drawstr(point p, const char *s)
{
    POINT curr_pos;
    int width;
    HFONT old;

    enable_drawing();
    SetTextColor(dc, win_rgb); /* set colour */
    if (! current->fnt)
	current->fnt = SystemFont;
    old = SelectObject(dc, current->fnt->handle);
    MoveToEx(dc, p.x, p.y, NULL);
    SetBkMode(dc, TRANSPARENT);
    SetTextAlign(dc, TA_LEFT | TA_UPDATECP);

    TextOut(dc, p.x, p.y, s, strlen(s));

    GetCurrentPositionEx(dc, &curr_pos);
    width = curr_pos.x - p.x;
    SelectObject(dc, old);
    /* always leave a DC with no real font selected */

    return width;
}

rect strrect(font f, const char *s)
{
    SIZE size;
    long h;
    HFONT old;
    HDC dc;

    if (! f)
	f = SystemFont;

    h = getheight(f);

    dc = GetDC(0); /* get screen dc */
    old = SelectObject(dc, f->handle);
    GetTextExtentPoint(dc, (LPSTR) s, strlen(s), &size);
    SelectObject(dc, old);
    ReleaseDC(0, dc);

    return rect(0,0,size.cx, h);
}

point strsize(font f, const char *s)
{
    rect r = strrect(f,s);
    return pt(r.width, r.height);
}

int strwidth(font f, const char *s)
{
    rect r = strrect(f,s);
    return r.width;
}

/*
 *  Draw an image:
 */
void drawimage(image img, rect dr, rect sr)
{
    bitmap b;
    image i = img;

    if (! img)
	return;
    enable_drawing();
    dr = rcanon(dr);
    if ((dr.width != img->width) || (dr.height != img->height))
	i = scaleimage(img, rect(0,0,dr.width,dr.height), sr);
    b = imagetobitmap(i);
    copyrect(b, pt(dr.x,dr.y), getrect(b));
    del(b);
    if (i != img)
	del(i);
}
