Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » Draw, Display, Images, Bitmaps, Icons » Bug: Missing width in DrawArc on X11
Bug: Missing width in DrawArc on X11 [message #35763] Sat, 17 March 2012 22:28 Go to next message
steffen is currently offline  steffen
Messages: 38
Registered: May 2007
Location: Denmark
Member

Hi,

I am working on a set of widgets for an embedded touch screen project I recently started. First running on x86, but it should end up running on an Arm9 board currently under development.

I am trying to make some widgets with round corners and ran into a problem with DrawArc.

It seems like SystemDraw::DrawArcOp in DrawOpX11.cpp is not using the width parameter.
I think it is mising a call to SetLineStyle.

When I add the following to my paint function, it works:
((SystemDraw&)w).SetLineStyle(3);

Is there a reason that SetLineStyle is not part of Draw? The type casting seems a bit ugly.

Regards,
Steffen

Edit:
I'm using Upp-4193 on Ubuntu 10.10 64-bit.

[Updated on: Mon, 19 March 2012 22:47]

Report message to a moderator

Re: Bug: Missing width in DrawArc on X11 [message #35819 is a reply to message #35763] Fri, 23 March 2012 20:44 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

I agree with you: There should definitely be a SetLineStyle() call in the beginning of DrawArcOp() in file DrawOpX11.cpp as follows:

void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
	GuiLock __;
	SetLineStyle(width);     // This needs to be added
	XGCValues gcv, gcv_old;
	XGetGCValues(Xdisplay, GetGC(), GCForeground, &gcv_old);
	Point offset = GetOffset();
        ...


Hope someone in the core team commits this soon. (I guess the DrawArc is a very little used functionality -- at least on X11 platforms -- since nobody has discovered and fixed it before.)

The SetLineStyle() should not be needed in applications since all drawing primitives should call it as needed for desired results.

Best regards,

Tom
Re: Bug: Missing width in DrawArc on X11 [message #35854 is a reply to message #35819] Wed, 28 March 2012 11:05 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

As it turns out, there is a related issue in DrawOpX11.cpp SystemDraw::DrawPolyPolylineOp and DrawPolyPolyPolygonOp. Neither of them call SetLineStyle for the outline. Instead, both of them use XGetGCValues() and XChangeGC(), but fail to update state of dashing causing unexpected results when used after drawing a dashed line -- or attempting to draw a dashed polyline or polygon-outline.

Using SetLineStyle() in proper places (and skipping GCLineWidth) fixes this issue.

Here are the relevant parts that need to be fixed for Polyline, Polygon and Arc to work properly:

	
void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count,
	                          const int *counts, int count_count,
	                          int width, Color color, Color doxor)
{
	GuiLock __;
	ASSERT(count_count > 0 && vertex_count > 0);
	if(vertex_count < 2 || IsNull(color))
		return;
	SetLineStyle(width);  // Added
	XGCValues gcv_old, gcv_new;
	XGetGCValues(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_old);
//	XGetGCValues(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_old);
	gcv_new.function = IsNull(doxor) ? X11_ROP2_COPY : X11_ROP2_XOR;
	gcv_new.foreground = GetXPixel(color) ^ (IsNull(doxor) ? 0 : GetXPixel(doxor));
//	gcv_new.line_width = width;
	XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_new);
//	XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_new);
	enum { REQUEST_LENGTH = 256 }; // X server XDrawLines request length (heuristic)
	Point offset = GetOffset();
	if(vertex_count == 2)
		XDrawLine(Xdisplay, GetDrawable(), GetGC(),
			vertices[0].x + offset.x, vertices[0].y + offset.y,
			vertices[1].x + offset.x, vertices[1].y + offset.y);
	else if(count_count == 1 || vertex_count > count_count * (REQUEST_LENGTH + 2)) {
		for(; --count_count >= 0; counts++)
		{
			Buffer<XPoint> part(*counts);
			for(XPoint *vo = part, *ve = vo + *counts; vo < ve; vo++, vertices++)
			{
				vo -> x = (short)(vertices -> x + offset.x);
				vo -> y = (short)(vertices -> y + offset.y);
			}
			XDrawLines(Xdisplay, GetDrawable(), GetGC(), part, *counts, CoordModeOrigin);
		}
	}
	else {
		int segment_count = vertex_count - count_count;
		Buffer<XSegment> segments(segment_count);
		XSegment *so = segments;
		while(--count_count >= 0)
		{
			const Point *end = vertices + *counts++;
			so -> x1 = (short)(vertices -> x + offset.x);
			so -> y1 = (short)(vertices -> y + offset.y);
			vertices++;
			so -> x2 = (short)(vertices -> x + offset.x);
			so -> y2 = (short)(vertices -> y + offset.y);
			so++;
			while(++vertices < end) {
				so -> x1 = so[-1].x2;
				so -> y1 = so[-1].y2;
				so -> x2 = (short)(vertices -> x + offset.x);
				so -> y2 = (short)(vertices -> y + offset.y);
				so++;
			}
		}
		ASSERT(so == segments + segment_count);
		XDrawSegments(Xdisplay, GetDrawable(), GetGC(), segments, segment_count);
	}
	XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_old);
//	XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_old);
}

...

void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
	 const int *subpolygon_counts, int subpolygon_count_count,
	const int *disjunct_polygon_counts, int disjunct_polygon_count_count,
	Color color, int width, Color outline, uint64 pattern, Color doxor)
{
	GuiLock __;
	if(vertex_count == 0)
		return;

	if(!IsNull(outline)) SetLineStyle(width); // Added
	bool is_xor = !IsNull(doxor);
	XGCValues gcv_old, gcv_new;
	XGetGCValues(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_old);
//	XGetGCValues(Xdisplay, GetGC(), GCForeground | GCFunction | GCLineWidth, &gcv_old);
	unsigned xor_pixel = (is_xor ? GetXPixel(doxor) : 0);
	if(!IsNull(color))
	{
		gcv_new.foreground = GetXPixel(color) ^ xor_pixel;
		gcv_new.function = is_xor ? X11_ROP2_XOR : X11_ROP2_COPY;
		XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_new);
		DrawPolyPolyPolygonRaw(*this, vertices, vertex_count,
			subpolygon_counts, subpolygon_count_count,
			disjunct_polygon_counts, disjunct_polygon_count_count);
	}
	if(!IsNull(outline))
	{
		gcv_new.foreground = GetXPixel(outline) ^ xor_pixel;
		//gcv_new.line_width = width;
		XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv_new);
		//XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth, &gcv_new);
		Point offset = GetOffset();
		for(const int *sp = subpolygon_counts, *se = sp + subpolygon_count_count; sp < se; sp++)
		{
			Buffer<XPoint> segment(*sp + 1);
			XPoint *out = segment;
			for(const Point *end = vertices + *sp; vertices < end; vertices++, out++)
			{
				out -> x = (short)(vertices -> x + offset.x);
				out -> y = (short)(vertices -> y + offset.y);
			}
			*out = segment[0];
			XDrawLines(Xdisplay, GetDrawable(), GetGC(), segment, *sp + 1, CoordModeOrigin);
		}
	}
	XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_old);
//	XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction | GCLineWidth, &gcv_old);
}


...


void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
	GuiLock __;
	SetLineStyle(width);	// Added
	XGCValues gcv, gcv_old;
	XGetGCValues(Xdisplay, GetGC(), GCForeground, &gcv_old);
	Point offset = GetOffset();
	gcv.foreground = GetXPixel(color);
	XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv);
	Point centre = rc.CenterPoint();
	int angle1 = fround(360 * 64 / (2 * M_PI) *
	                    atan2(centre.y - start.y, start.x - centre.x));
	int angle2 = fround(360 * 64 / (2 * M_PI) *
	                    atan2(centre.y - end.y, end.x - centre.x));
	if(angle2 <= angle1)
		angle2 += 360 * 64;
	angle2 -= angle1;
	XDrawArc(Xdisplay, GetDrawable(), GetGC(), rc.left + offset.x, rc.top + offset.y,
		rc.Width(), rc.Height(), angle1, angle2);
	XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv_old);
}


Best regards,

Tom
Re: Bug: Missing width in DrawArc on X11 [message #35904 is a reply to message #35854] Sun, 01 April 2012 16:47 Go to previous message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Patch applied, thank you.
Previous Topic: Centering text in a rectange
Next Topic: Problem in dasher.cpp and proposed solution
Goto Forum:
  


Current Time: Thu Mar 28 15:55:39 CET 2024

Total time taken to generate the page: 0.01090 seconds