Cross-hatching

Discussions related to graphics (2D and 3D), animation and games programming
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Cross-hatching

Post by KenDown »

Somewhere there was a discussion recently involving a person who wanted to fill using cross-hatching instead of a solid colour. I remember that someone came up with just such a facility for the BBC Micro, but I'm pretty sure it involvd 6502 assembler, so no use to us.

Anyway, I happened to be looking at a page that mentioned the GDI Plus library or codec or whatever it is - I keep hoping that something will penetrate, but must confess that it all seems like gobbledy-gook to me - and I noticed that there is a facility for crosshatching of various patterns.

https://docs.microsoft.com/en-us/window ... attern-use

I wouldn't know where to begin, but I wonder if the GDIPLIB could be extended to include at least some of the patterns on offer?
DDRM

Re: Cross-hatching

Post by DDRM »

Hi Kendall,

Yes, it's possible: here's a proof of principle. Two of the hatch patterns are "checkerboards", but even the large one is quite small....

Before that, it's worth noting that this will only apply to BB4W, because it is relying on Windows systems calls, though it may well be possible to do something similar in SDL2. Furthermore, you'll need to do all your drawing (that you want to use the fill on) in GDIPlus, which is a little more demanding that the standard graphics (but on the plus side, it looks nicer!).

First we need to make a modification to GDIPLIB:

1) Find PROC_gdipinit, and add

Code: Select all

SYS "GetProcAddress", gdip%, "GdipCreateHatchBrush"  TO `GdipCreateHatchBrush`
to the list there (I added it just after the GdipCreateSolidFill line, which is used to (point to the call to) create a solid brush). Note the characters at the start and finish of the variable name! Best use copy and paste to copy the line above, and change the name into it!

2) Create a function to create a hatched brush: I stuck this just after the one for a solid brush:

Code: Select all

      REM Create hatched brush (hatch style, foreground colour, background colour)
      DEF FN_gdipcreatehatchedbrush(hatch_style%, FC%,BC%)
      LOCAL B%
      SYS `GdipCreateHatchBrush`, hatch_style%, FC%,BC%, ^B%
      = B%
...and that's just about it! You may wish to save it in the lib folder with a different name. Depending on how/where you've installed BB4W, you may need admin rights to do that.

Now you can create a hatched brush, in your chosen style, and pass it to any of the routines. Here's an example that shows the 53 patterns on offer:

Code: Select all

      REM Note that I've made a custom version of GDIPLIB...
      INSTALL @lib$+"GDIPLIB_HatchedBrush"

      MODE 21
      PROC_gdipinit

      pen1% = FN_gdipcreatepen(&FFF00000, 0, 5) :REM Solid pen for outline (behind fill, so you can see the edge)

      REM Let's try out all the hatch styles I've found documented
      REM My source (https://help.perforce.com/stingray/current/Stingray_Objective_Grid_dotNet_API_Documentation/html/html/T_Stingray_Grid_HatchStyle.htm)
      REM suggests 0 is "no fill", and the numbers run to 53...
      REM ...but trial and error suggests everything is moved down one, and fill 0 is  horizontal lines
      FOR x% = 0 TO 53
  
        REM First we need to create the brush for this style:
        brush2% = FN_gdipcreatehatchedbrush(x%,&FF00FF00,&FF00008F)
  
        REM Now draw an outline ellipse, to plot our filled one over, so we can see the edges clearly
        PROC_gdipellipse(pen1%, 100+250*(x% MOD 6),1100 - 120*(x% DIV 6), 100,50, 0)
        REM Now we plot a filled one(polygons and filled beziers also available, but not I think a flood fill)
        PROC_gdipellipsefill(brush2%, 100+250*(x% MOD 6),1100 - 120*(x% DIV 6), 100,50, 0,0)
  
        REM Delete the brush once we've finished with it
        PROC_gdipdeletebrush(brush2%)
      NEXT x%

      REM Tidy up...
      PROC_gdipdeletepen(pen1%)
      PROC_gdipexit
      END
It seems that the foreground colour is ORed with the background colour. Not sure if that is configurable.

Best wishes,

D
Hated Moron

Re: Cross-hatching

Post by Hated Moron »

KenDown wrote: Fri 16 Sep 2022, 07:46 I wonder if the GDIPLIB could be extended to include at least some of the patterns on offer?
No need to, really, since Hans van der Hoeven's extended GDI+ library already provides support for hatching:

https://groups.io/g/bb4w/files/Libraries/GDIplus_lib.bbc

There's a demo program for this library, which includes some hatching examples:

https://groups.io/g/bb4w/files/Graphics/GDIplus_demo.bbc

I didn't draw attention to this possibility because, these days, I'm primarily interested in solutions which can also be used in BBC BASIC for SDL 2.0 and GDI+ is of course Windows-specific. I'd be interested if somebody can reproduce a similar functionality in BBCSDL (I already offered a solution using gfxlib in the other thread).
DDRM

Re: Cross-hatching

Post by DDRM »

Hmm, OK!

Well, I had fun this morning reinventing the wheel (I see linear gradient brushes are also in there, which I've just got working!)...
...but I guess I learnt something...

:-)

D
Hated Moron

Re: Cross-hatching

Post by Hated Moron »

DDRM wrote: Fri 16 Sep 2022, 09:57 It seems that the foreground colour is ORed with the background colour.
Is it? I thought GDI+ didn't support logical colour operations like AND, OR and exclusive-OR at all. Indeed wasn't that one of the reasons why it was rejected as the main graphics sub-system for BBC BASIC for Windows, because GCOL required that functionality?
DDRM

Re: Cross-hatching

Post by DDRM »

Hmm. you've made me wonder, now. The comment was based on the appearance of running the code in the post above: the "green" lines crossing the blue background look distinctly cyan, at least to me on this monitor. But the fills that are virtually all foreground, with just a stippling of background, are pretty green, so not sure exactly what it going on!
Hated Moron

Re: Cross-hatching

Post by Hated Moron »

DDRM wrote: Sun 18 Sep 2022, 07:39 The comment was based on the appearance of running the code in the post above: the "green" lines crossing the blue background look distinctly cyan
I wouldn't be inclined to make a judgement on how it "looks", since the eye/brain are so easily fooled (as evidenced by 'optical illusions'). Rather I would suggest adding a routine to display, in the title bar, the colour under the mouse cursor. A timer interrupt is handy for this, because it doesn't interfere with the rest of the program:

Code: Select all

      ON TIME PROCsample : RETURN
      ... 

      DEF PROCsample
      LOCAL X%,Y%,B%
      MOUSE X%,Y%,B%
      B% = TINT(X%,Y%)
      SYS "SetWindowText", @hwnd%, STR$~B%
      ENDPROC
(in BBC BASIC for SDL 2.0 substitute SYS "SDL_SetWindowTitle", @hwnd%, STR$~B%, @memhdc%).

Of course you can display the red, green and blue components separately if you prefer.