My ideas for GSoC 2015

HuddenSin Yuan huddsinyuan2014 at gmail.com
Tue Mar 24 13:07:48 CDT 2015


Hello, everyone.

I’m Yuan Chen, a college student from China. I will have plenty of
time to join GSoC 2015 and I have send two patches about mshtml.dll
before and now I study gdi32 module and the Computer Graphics.

Here is my idea for GSoC 2015.

Improve the basic drawing functions and add GM_ADVANCED mode support
=====================================
I found several bugs which show many basic curve and fonts drawing
functions don’t support the GM_ADVANCED mode[1][2][3]. And the curve
will become odd under this mode. I have written a test case to show
these problems[9].

1.add GM_ADVANCED mode support
When I find that wine use polygon to fit the rect in GM_ADVANCED
mode(polygon function is not good enough according to [4]). So I think
we can use bezier spline or B spline to fit the curve like ellipse or
arc in GM_ADVANCED mode[5][6]. There is also a paper about fonts
capturing[7].
So the driver functions of curve and fonts like draw_arc, draw_glyph
will be improved and added the GM_ADVANCED support.

2.improve the basic drawing functions
In order to fix those above, we need to improve and add some basic
helper functions in dlls/gdi32/dibdrv/graphics.c.
get_arc_points will be improved and some helper functions will be
added which help to calculate the coordinate of points of the curves
in GM_ADVANCED mode.This part will take about three weeks.
The bezier function need to be improved to n points instead of 3n+1
points according to Bresenham’s Algorithm[8]. This function will take
less than one week.
And I also try to improve the ellipse_first_quadrant functions using
the Bresenham’s Algorithm.[10]

Perhaps my idea is not mature enough, I will be appreciate it  very
much if anyone give me some advice!
Thanks!

[1]https://bugs.winehq.org/show_bug.cgi?id=33190
[2]https://bugs.winehq.org/show_bug.cgi?id=35333
[3]https://bugs.winehq.org/show_bug.cgi?id=35169
[4]https://bugs.winehq.org/show_bug.cgi?id=36891
[5]http://sarahfrisken.com/efficientCurveFitting.pdf
[6]http://www.dtic.mil/dtic/tr/fulltext/u2/a350611.pdf
[7]http://www.cs.uml.edu/~wanthony/91.427_f2008/cglr1/reference.pdf
[8]http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
[9]see the attachment  “testforadvanced.txt"
[10]see the attachment
"0001-gdi32-Improve-the-algorithm-of-ellipse_first_quadrant.txt"

----------------------------------------
Best Regards ,
Yuan Chen
-------------- next part --------------
#include <windows.h>
#include <math.h>

#define  TIMER1      1

static LONG quarterx, quartery;
static POINT p[4];
static double Angel;

LRESULT CALLBACK Handle_fir(HWND, UINT, WPARAM, LPARAM);
void DrawPic(HDC, double);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
		   PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("Rectangle & Ellipse ");
    HWND hwnd1;
    MSG msg;
    WNDCLASS wndclass1;

    wndclass1.style = CS_HREDRAW | CS_VREDRAW;
    wndclass1.lpfnWndProc = Handle_fir;
    wndclass1.cbClsExtra = 0;
    wndclass1.cbWndExtra = 0;
    wndclass1.hInstance = hInstance;
    wndclass1.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass1.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass1.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass1.lpszMenuName = NULL;
    wndclass1.lpszClassName = szAppName;

    if (!(RegisterClass(&wndclass1))) {
	MessageBox(NULL, TEXT("Program requires Windows NT!"),
		   szAppName, MB_ICONERROR);
	return 0;
    }

    hwnd1 = CreateWindow(szAppName, TEXT("SetWorldTransform Test Origin"),
			 WS_OVERLAPPEDWINDOW,
			 CW_USEDEFAULT, CW_USEDEFAULT,
			 CW_USEDEFAULT, CW_USEDEFAULT,
			 NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd1, iCmdShow);
    UpdateWindow(hwnd1);

    while (GetMessage(&msg, NULL, 0, 0)) {
	TranslateMessage(&msg);
	DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK Handle_fir(HWND hwnd1, UINT message, WPARAM wParam,
			    LPARAM lParam)
{
    static int cxClient, cyClient;
    HDC hdc1;
    PAINTSTRUCT ps;
    RECT rt;

    switch (message) {

    case WM_CREATE:
	SetTimer(hwnd1, TIMER1, 50, NULL);
	Angel = 0.0;

	return 0;


    case WM_TIMER:
	InvalidateRect(hwnd1, NULL, TRUE);
	return 0;

    case WM_SIZE:
	cxClient = LOWORD(lParam);
	cyClient = HIWORD(lParam);

	quarterx = 1 * cxClient / 4;
	quartery = 1 * cyClient / 4;

	p[0].x = quarterx;
	p[0].y = 4 * quartery;
	p[1].x = 3 * quarterx;
	p[1].y = 4 * quartery;
	p[2].x = quarterx;
	p[2].y = 5 * quartery;
	p[3].x = 3 * quarterx;
	p[3].y = 5 * quartery;
	return 0;

    case WM_PAINT:
	{
	    hdc1 = BeginPaint(hwnd1, &ps);
	    Angel = Angel + 1.0;
	    if (Angel == 361.0)
		Angel = 1.0;

	    SetMapMode(hdc1, MM_ISOTROPIC);
	    SetWindowExtEx(hdc1, 1000, 1000, NULL);
	    SetViewportExtEx(hdc1, cxClient, cyClient, NULL);

	    SetWindowOrgEx(hdc1, 500, 500, NULL);
	    SetViewportOrgEx(hdc1, cxClient / 2, cyClient / 2, NULL);


	    GetClientRect(hwnd1, &rt);
	    FillRect(hdc1, &rt, WHITE_BRUSH);

	    int nGraphicMode = SetGraphicsMode(hdc1, GM_ADVANCED);
	    DrawPic(hdc1, Angel);

	    EndPaint(hwnd1, &ps);

	    return 0;
	}

    case WM_DESTROY:
	KillTimer(hwnd1, TIMER1);
	PostQuitMessage(0);
	return 0;
    }
    return DefWindowProc(hwnd1, message, wParam, lParam);
}

void DrawPic(HDC hdc1, double Angel)
{
    XFORM xForm;
    Angel = Angel * 3.1516926 / 180;
    float sinangel = sin(Angel);
    float cosangel = cos(Angel);

    xForm.eM11 = cosangel;
    xForm.eM12 = sinangel;
    xForm.eM21 = -sinangel;
    xForm.eM22 = cosangel;

    xForm.eDx =
	(float) (-2 * quarterx * cosangel + 2 * quartery * sinangel);
    xForm.eDy =
	(float) (-2 * quarterx * sinangel - 2 * quartery * cosangel);

    SetWorldTransform(hdc1, &xForm);

    OffsetWindowOrgEx(hdc1, -500, -500, NULL);

    MoveToEx(hdc1, 0, 15, NULL);
    LineTo(hdc1, 4 * quarterx, 15);


    RoundRect(hdc1, quarterx, 0, 5 * quarterx, 5 * quartery, quarterx / 2,
	      quartery / 2);

    Arc(hdc1, quarterx, 0, 2 * quarterx, 1 * quartery / 2,
	quarterx, 1 * quartery / 8, 5 * quarterx / 4, 3 * quartery / 8);

    Rectangle(hdc1, quarterx, quartery, 3 * quarterx, 3 * quartery);

    Ellipse(hdc1, quarterx, quartery, 3 * quarterx, 3 * quartery);

    Polygon(hdc1, p, 4);
}
-------------- next part --------------
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
index 2c865c0..b222610 100644
--- a/dlls/gdi32/dibdrv/graphics.c
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -172,40 +172,33 @@ static void add_pen_lines_bounds( dibdrv_physdev *dev, int count, const POINT *p
     add_clipped_bounds( dev, &bounds, dev->clip );
 }
 
-/* compute the points for the first quadrant of an ellipse, counterclockwise from the x axis */
+/* compute the points for the first quadrant of an ellipse */
 /* 'data' must contain enough space, (width+height)/2 is a reasonable upper bound */
 static int ellipse_first_quadrant( int width, int height, POINT *data )
 {
-    const int a = width - 1;
-    const int b = height - 1;
-    const INT64 asq = (INT64)8 * a * a;
-    const INT64 bsq = (INT64)8 * b * b;
-    INT64 dx  = (INT64)4 * b * b * (1 - a);
-    INT64 dy  = (INT64)4 * a * a * (1 + (b % 2));
-    INT64 err = dx + dy + a * a * (b % 2);
-    int pos = 0;
     POINT pt;
+    const int a = width/2;
+    const int b = height/2;
+    int pos = 0;
+    INT64 de, dx, dy, err;
 
-    pt.x = a;
-    pt.y = height / 2;
+    de = b;
+    pt.x = -a;
+    pt.y = 0;
+    dx = ( 1 + 2 * pt.x) * de * de;
+    dy = pt.x * pt.x;
+    err = dx + dy ;
 
-    /* based on an algorithm by Alois Zingl */
+    do{
+	    data[ pos++ ] = pt;
+        data[ pos-1 ].x = a - data[ pos-1 ].x;
+        data[ pos-1 ].y = b + data[ pos-1 ].y;
+        de = 2 * err;
+
+        if(de >= dx) { pt.x ++; err += dx += 2 * b * b; }
+        if(de <= dy) { pt.y ++; err += dy += 2 * a * a; }
+    }while( pt.x <= 0);
 
-    while (pt.x >= width / 2)
-    {
-        INT64 e2 = 2 * err;
-        data[pos++] = pt;
-        if (e2 >= dx)
-        {
-            pt.x--;
-            err += dx += bsq;
-        }
-        if (e2 <= dy)
-        {
-            pt.y++;
-            err += dy += asq;
-        }
-    }
     return pos;
 }
 


More information about the wine-devel mailing list