Page 1 of 1

CustomFilterCallback: lParam

Posted: Tue Dec 10, 2013 8:12 pm
by netmaestro
For the project I'm currently working on I would like to produce crossplatform code. I know several ways to draw 24bit images transparently, they're all fast and they all work well - and they're all windows-specific. So I tested the native 2DDrawing library (which is awesome btw) and found that a custom filter callback is:

a) suited to the purpose
b) fast enough for seamless animation

So, great! a native crossplatform solution. However, we cannot pass anything in the way of further information to the callback. All it gets and all it wants are x, y, SourceColor, TargetColor and those are passed by the 2DDrawing library. I can add nothing to it. So I have to make my transparent color global or something. Not optimal.

If the prototype of the FilterCallback were CustomFilterProc(x, y, SourceColor, TargetColor, [, lParam]) then current code wouldn't break and I could pass the transparent color (or a pointer to a structure with lots of info in it), generally enhancing the usability of the callback.

btw, I'm saying lParam because I code for windows and that's the term I'm used to. But userdata, customdata, etc. might be more suitable choices for a crossplatform library.

Code: Select all

Procedure FilterCallback(x, y, SourceColor, TargetColor)
  If SourceColor&$FFFFFF = RGB(255,0,255) ; I'm hardcoding this here because I can't pass it as parameter :-(
    ProcedureReturn TargetColor
  Else
    ProcedureReturn SourceColor
  EndIf
EndProcedure

CreateImage(1, 128,128,24,RGB(255,0,255)) ; pink for a transparent color
StartDrawing(ImageOutput(1))
  Circle(64,64,60,#Blue)
StopDrawing()

If OpenWindow(0, 0, 0, 256,256, "2DDrawing Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowColor(0, RGB(255,255,223))
  
  If CreateImage(0, 128, 128, 24, GetWindowColor(0)) And StartDrawing(ImageOutput(0))
      DrawingMode(#PB_2DDrawing_CustomFilter)      
      CustomFilterCallback(@FilterCallback())
      DrawImage(ImageID(1), 0, 0)
    StopDrawing() 
    ImageGadget(0, 64, 64, 0, 00, ImageID(0))
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf

Re: CustomFilterCallback: lParam

Posted: Tue Dec 10, 2013 9:00 pm
by freak
> So I have to make my transparent color global or something. Not optimal.

I thought about it, but the 2ddrawing lib would just store the value in a global variable too and then pass it back to the function. It would be no different, just not visible.

> CustomFilterProc(x, y, SourceColor, TargetColor, lParam=0)

Unfortunately this is not possible. Callbacks must have a fixed number of parameters. So its either always with the extra parameter or never.

Re: CustomFilterCallback: lParam

Posted: Tue Dec 10, 2013 9:08 pm
by netmaestro
Fair enough, I can live with that.

Re: CustomFilterCallback: lParam

Posted: Tue Dec 10, 2013 10:00 pm
by netmaestro
I made a codeblock I can just stick at the top of my program and forget about. It allows me to use the feature just as if it were actually there:

Code: Select all

;////////////////////////////////////////////////////////////////////

; Boilerplate code - do not edit                                  

Global gFilterUserData                                            

Macro UseFilterProc(callback, lParam=0)                           
  gFilterUserData.i = lParam                                      
  CustomFilterCallback(callback)                                  
EndMacro                                                          

Procedure TransparentDrawing24(x, y, SourceColor, TargetColor)    
  If SourceColor&$FFFFFF = gFilterUserData                        
    ProcedureReturn TargetColor                                   
  Else                                                            
    ProcedureReturn SourceColor                                   
  EndIf                                                           
EndProcedure                                                      
;////////////////////////////////////////////////////////////////////

CreateImage(1, 128,128,24,RGB(255,0,255)) ; pink for a transparent color
StartDrawing(ImageOutput(1))
  Circle(64,64,60,#Blue)
StopDrawing()

If OpenWindow(0, 0, 0, 256,256, "2DDrawing Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowColor(0, RGB(255,255,223))
  
  If CreateImage(0, 128, 128, 24, GetWindowColor(0)) And StartDrawing(ImageOutput(0))
      DrawingMode(#PB_2DDrawing_CustomFilter)      
      UseFilterProc(@TransparentDrawing24(), RGB(255,0,255))
      x=ElapsedMilliseconds()
      DrawImage(ImageID(1), 0, 0)
      y=ElapsedMilliseconds()
    StopDrawing() 
    ImageGadget(0, 64, 64, 0, 00, ImageID(0))
  EndIf
  SetWindowTitle(0, "Drawing time: "+Str(y-x)+" ms")
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf