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