News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Problem with GdiPlus and GdipCreateCustomLineCap

Started by jj2007, January 08, 2016, 07:16:13 AM

Previous topic - Next topic

jj2007

I am using
invoke GdipCreateCustomLineCap, 0, gdiPath, LineCapFlat, 0, addr custCap
invoke GdipSetCustomLineCapStrokeCaps, custCap, LineCapTriangle, LineCapRound

in the WM_CREATE handler, then, in the WM_PAINT handler:
      invGdip GdipSetPenEndCap, pPen, LineCapArrowAnchor
      invGdip GdipDrawLineI, gdiDC, pPen, 20, 100, 400, 180
     
      invGdip GdipSetPenCustomEndCap, pPen, custCap      ; PB example
      invGdip GdipDrawLineI, gdiDC, pPen, 20, 120, 400, 200


The first one works fine, the custom cap doesn't - it just draws the start point but no line and no end point. All GdiPlus calls return S_OK. The PB example uses cloning, but 1. I see no reason why and 2. same result :(

Any ideas? Full code attached, as plain Masm32.

guga

Maybe this can help ?

http://www.jose.it-berater.org/smfforum/index.php?topic=1980.0
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

qWord

MREAL macros - when you need floating point arithmetic while assembling!

jj2007

Quote from: guga on January 08, 2016, 08:14:48 AM
Maybe this can help ?

http://www.jose.it-berater.org/smfforum/index.php?topic=1980.0

Thanks, Gustavo - José Roca is indeed my main source of inspiration, when it comes to Gdi+ ;)

But the real problem (pun intended) was on another José Roca page in the C++ example:
   //Create a Path, and add two lines to it.
   Point points[3] = {Point(-15, -15), Point(0, 0), Point(15, -15)};


Looks like an array of integers, but...

Quote from: qWord on January 08, 2016, 08:28:26 AM
PointF != POINT

Thanks, qWord :t

mabdelouahab


.DATA
_ccPts REAL4 -15.0 , -15.0
REAL4 0.0 , 0.0
REAL4 15.0 , -15.0

jj2007

Thanks, mabdelouahab. It works fine now:

invGdip GdipAddPathPolygon, gdiPath, addr ccPts, (sizeof ccPts)/PointF
(invGdip is a macro that works like invoke but checks ret values in debug mode, and displays a text error if eax!=S_OK)

Now I am fighting with:
wm_create:
invGdip GdipCreateSolidFill, RgbCol(255, 0, 255, 255), addr pSolidBrush
...
wm_paint:
  invGdip GdipFillPath, gdiDC, pSolidBrush, custCap
  invGdip GdipSetPenCustomEndCap, pPen, custCap


Works fine to fill a rectangle in the WM_PAINT handler, but I would like to fill the endcap triangle; and that doesn't work, invGdip barks GdipFillPath: ObjectBusy :(

qWord

First make sure that the path passed to CustomLineCap-Constructor is closed (GdipClosePathFigure(s)).
To get filled shapes, pass the path as first constructor argument and set the stroke-path to zero.
For custom arrows there is also the special class AdjustableArrowCap, which is derived from CustomLineCap.

Tip: take a look into the Gdiplus headers coming with the windows SDK. The class definitions shows how to use the flat API, e.g. which parameters are optional.
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

Quote from: qWord on January 09, 2016, 12:36:58 AM
First make sure that the path passed to CustomLineCap-Constructor is closed (GdipClosePathFigure(s)).
To get filled shapes, pass the path as first constructor argument and set the stroke-path to zero.
For custom arrows there is also the special class AdjustableArrowCap, which is derived from CustomLineCap.

Thanks, qWord. I had already discovered AdjustableArrowCap, and it works fine, see lower array below:
invGdip GdipCreateAdjustableArrowCap, FP4(6.0), FP4(5.0), TRUE, addr custCapFilled
Re path as first constructor argument, that gives me "not implemented" for some reason (very unlikely, so the reason is elsewhere). With GdipAddPathPolygon, it works but the result looks odd, see second image below.

qWord

I currently can't find any documentation how the cap-coordinates are handled, but a quick test shows that everything above the x-axes is clipped away. The line comes from -Infinity along the y-axes and ends in the origin (0,0). With the function GdipSetCustomLineCapBaseInset you can set the line end to whatever negative y-coordinate to make room for the cap. Otherwise, as in your case, the line and the cap interferes.

Code ("jwasm") Select
mov ccPts[0*PointF].x, -15.0
mov ccPts[0*PointF].y, -15.0
mov ccPts[1*PointF].x, 0
mov ccPts[1*PointF].y, 0
mov ccPts[2*PointF].x, 15.0
mov ccPts[2*PointF].y, -15.0

invoke GdipCreatePath, FillModeAlternate, addr gdiPath
invoke GdipAddPathLine2, gdiPath, addr ccPts, 3
invoke GdipClosePathFigure,gdiPath

invoke GdipCreateCustomLineCap, 0, gdiPath, LineCapFlat, 0, addr custCap
invoke GdipCreateCustomLineCap, gdiPath, 0, LineCapFlat, 0, addr custCap0

invoke GdipCreatePen1, 0ffffff00h, FP4(5.0), UnitWorld, addr pPen

; make room for cap
invoke GdipSetCustomLineCapBaseInset,custCap, FP4(15.0)
invoke GdipSetCustomLineCapBaseInset,custCap0, FP4(15.0)

; fill
invoke GdipSetPenCustomStartCap,pPen, custCap0
invoke GdipSetPenCustomEndCap, pPen, custCap0
invoke GdipDrawLineI, gdiDC, pPen, 20, 120, 400, 200

invoke GdipSetPenColor,pPen,0ffff0000h

; outline
invoke GdipSetPenCustomStartCap,pPen, custCap
invoke GdipSetPenCustomEndCap, pPen, custCap
invoke GdipDrawLineI, gdiDC, pPen, 20, 120, 400, 200
MREAL macros - when you need floating point arithmetic while assembling!

jj2007


guga

I remember seeing a wrapper for GDIPlus in plain C that seems to be documented. I´ll look in my files and see if i can find it for you guys.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

Found it

https://github.com/mono/libgdiplus

https://github.com/mono/libgdiplus/blob/master/src/customlinecap.c

Indeed, they some parameters are pointer to floats


static GpStatus gdip_custom_linecap_setup (GpGraphics *graphics, GpCustomLineCap *cap);
static GpStatus gdip_custom_linecap_clone_cap (GpCustomLineCap *cap, GpCustomLineCap **clonedCap);
static GpStatus gdip_custom_linecap_destroy (GpCustomLineCap *cap);
static GpStatus gdip_custom_linecap_draw (GpGraphics *graphics, GpPen *pen, GpCustomLineCap *cap, float x, float y, float otherend_x, float otherend_y);

GpStatus
GdipGetCustomLineCapBaseInset (GpCustomLineCap *customCap, float *inset)
{
if (!customCap || !inset)
return InvalidParameter;

*(inset) = customCap->base_inset;

return Ok;
}


Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com