DPI and canvasgadget scaling

Just starting out? Need help? Post your questions and find answers here.
User avatar
captain_skank
Enthusiast
Enthusiast
Posts: 636
Joined: Fri Oct 06, 2006 3:57 pm
Location: England

DPI and canvasgadget scaling

Post by captain_skank »

Hi,

I'm getting some odd results using the canvasgadget on DPI enabled code and help is a bit light on explanation ( or i'm to thick ).

if i have a canvasgadget and want to fill it using a box do I multiply the width and the height by the result of DesktopScaledX(100)/100 and DesktopScaledY(100)/100 ??

So if my screen is scaled at 150% I would get 1.5 for both the X and Y scale. and would multiply x and y by these values ?

And is it the same for 2d and/or vector drawing ?

Or am i missunderstanding this.

Cheers
wombats
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Dec 29, 2011 5:03 pm

Re: DPI and canvasgadget scaling

Post by wombats »

I think you just use the returned value.

Code: Select all

height = DesktopScaledY(oldHeight)
I may be wrong, though.
User avatar
captain_skank
Enthusiast
Enthusiast
Posts: 636
Joined: Fri Oct 06, 2006 3:57 pm
Location: England

Re: DPI and canvasgadget scaling

Post by captain_skank »

Thanks, but i'm not sure thats right.

#PB_Gadget_RequiredSize always returns 0
wombats
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Dec 29, 2011 5:03 pm

Re: DPI and canvasgadget scaling

Post by wombats »

On macOS, the following example returns 21.

Code: Select all

If OpenWindow(0, 0, 0, 322, 205, "StringGadget Flags", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  StringGadget(0, 8,  10, 306, 20, "Normal StringGadget...")
  Debug GadgetHeight(0, #PB_Gadget_RequiredSize)
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
As far as I know, the DPI stuff is only relevant on Windows.
User avatar
mk-soft
Always Here
Always Here
Posts: 5387
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DPI and canvasgadget scaling

Post by mk-soft »

captain_skank wrote:Thanks, but i'm not sure thats right.

#PB_Gadget_RequiredSize always returns 0
Canvas gadget have not a required size. Its alway 0.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
captain_skank
Enthusiast
Enthusiast
Posts: 636
Joined: Fri Oct 06, 2006 3:57 pm
Location: England

Re: DPI and canvasgadget scaling

Post by captain_skank »

Sorry to resurrect this, but i've just come back to it :)

what is the correct way to scale a canvas gadget ?

Code: Select all

Global LVAR_font.i = LoadFont(#PB_Any,"Calibri Light", 18, #PB_Font_HighQuality)

wndw.i = OpenWindow(#PB_Any, 0, 0, 600, 100, "Grid Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget)

If wndw
  
  SetWindowColor(wndw, GVAR_colour_20)
  
  BTN_button.i = CanvasGadget(#PB_Any, 50, 20, 200, 50)
  LVAR_text.s = "The quick brown dog"
  
  If StartDrawing(CanvasOutput(BTN_button))
    DrawingFont(FontID(LVAR_font)) 
    LVAR_t_w.i = TextWidth(LVAR_text)
    LVAR_t_h.i = TextHeight(LVAR_text)
    StopDrawing()
  EndIf
  
  If LVAR_t_w + 6 < LVAR_t_h + 6
    ResizeGadget(BTN_button, #PB_Ignore, #PB_Ignore, LVAR_t_h + 6, LVAR_t_h + 6) 
  Else  
    ResizeGadget(BTN_button, #PB_Ignore, #PB_Ignore, LVAR_t_w + 6, LVAR_t_h + 6) 
  EndIf  
    
  If StartDrawing(CanvasOutput(BTN_button))
    ; fill the gadaget with the background colour
    Box(0, 0, GadgetWidth(BTN_button), GadgetHeight(BTN_button), GVAR_colour_15)
    ; draw the btn text
    DrawingFont(FontID(LVAR_font)) 
    LVAR_t_x.i = (GadgetWidth(BTN_button)-LVAR_t_w)/2
    LVAR_t_y.i = (GadgetHeight(BTN_button)-LVAR_t_h)/2
    DrawText(LVAR_t_x, LVAR_t_y, LVAR_text, GVAR_colour_25, GVAR_colour_15)
    StopDrawing()
  EndIf
  
EndIf

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
The above works fine on the default 100% display (1920x1080) but if i use it on a UHD display at 150% the text and background boxlook right but the canvas gadget is huge.. DPI is enable in compiler settings.

Any and all help appreciated.
User avatar
mk-soft
Always Here
Always Here
Posts: 5387
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DPI and canvasgadget scaling

Post by mk-soft »

Only 2D-Drawing need upscaling...

Code: Select all

;-TOP
; Comment : Object ButtonColorGadget Number 42 ;)
; Author  : mk-soft
; Version : v1.05
; Create  : 01.05.2019
; Update  : 29.07.2019 (DPI)
; OS      : All

; Link BaseClass : https://www.purebasic.fr/english/viewtopic.php?f=12&t=64305

IncludeFile "Modul_BaseClassSmall.pb"

EnableExplicit

; *****************************************************************************

;- Public

DeclareModule ButtonColorGadget
  
  UseModule BaseClass
  
  Interface iButtonColorGadget Extends iBaseClass
    Resize(x, y, Width, Height)
    SetText(Text.s)
    SetFont(FontID)
    SetColor(ColorType, Color)
    GetID()
    GetText.s()
    GetColor(ColorType)
  EndInterface
  
  UnuseModule BaseClass
  
  Declare Create(Gadget, x, y, Width, Height, Text.s, FrontColor = $000000, BackColor = $F5F5F5, Flags = 0)
  
EndDeclareModule

;- Private

Module ButtonColorGadget
  
  EnableExplicit
  
  UseModule BaseClass
  
  NewClass(iButtonColorGadget)
  
  Structure sButtonColorGadget Extends sBaseClass
    Gadget.i
    ; Params
    x.i
    y.i
    Width.i
    Height.i
    Text.s
    FontID.i
    LineColor.i
    FrontColor.i
    BackColor.i
    Flags.i
    ; Data
    Redraw.i
    State.i
  EndStructure
  
  ; ----
  
  Procedure.i BlendColor(Color1.i, Color2.i, Scale.i = 50) ; Thanks to Thorsten
    Protected.i R1, G1, B1, R2, G2, B2
    Protected.f Blend = Scale / 100
    R1 = Red(Color1): G1 = Green(Color1): B1 = Blue(Color1)
    R2 = Red(Color2): G2 = Green(Color2): B2 = Blue(Color2)
    ProcedureReturn RGB((R1*Blend) + (R2 * (1 - Blend)), (G1*Blend) + (G2 * (1 - Blend)), (B1*Blend) + (B2 * (1 - Blend)))
  EndProcedure
  
  ; ----
  
  Procedure DrawButton(*this.sButtonColorGadget)
    Protected LineColor, FrontColor, BackColor
    Protected Width, Height
    With *this
      Select \State
        Case #Null
          LineColor  = \LineColor
          FrontColor = \FrontColor
          BackColor  = \BackColor
        Case #PB_EventType_MouseEnter
          LineColor  = \LineColor
          FrontColor = BlendColor(\FrontColor, $FFFFFF, 80)
          BackColor  = BlendColor(\BackColor, $FFFFFF, 80)
        Case #PB_EventType_MouseLeave
          LineColor  = \LineColor
          FrontColor = \FrontColor
          BackColor  = \BackColor
        Case #PB_EventType_LeftButtonDown
          LineColor  = \LineColor
          FrontColor = BlendColor(\FrontColor, $000000, 80)
          BackColor  = BlendColor(\BackColor, $000000, 80)
        Case #PB_EventType_LeftButtonUp
          LineColor  = \LineColor
          FrontColor = BlendColor(\FrontColor, $FFFFFF, 80)
          BackColor  = BlendColor(\BackColor, $FFFFFF, 80)
      EndSelect
      
      Width = DesktopScaledX(\Width)
      Height = DesktopScaledY(\Height)
      If StartDrawing(CanvasOutput(\Gadget))
        Box(0, 0, Width, Height, LineColor)
        Box(1, 1, Width - 2, Height - 2, BackColor)
        DrawingFont(\FontID)
        DrawText(Width / 2 - TextWidth(\Text) / 2, Height / 2 - TextHeight(\Text) / 2, \Text, FrontColor, BackColor)
        StopDrawing()
      EndIf
    EndWith
    
  EndProcedure
  
  ; ----
  
  Procedure DoEvents()
    Protected *this.sButtonColorGadget = GetGadgetData(EventGadget())
    Protected state, redraw
    
    With *this
      If *this
        state = EventType()
        Select state
          Case #PB_EventType_MouseEnter : redraw = #True
          Case #PB_EventType_MouseLeave : redraw = #True
          Case #PB_EventType_MouseMove
          Case #PB_EventType_MouseWheel
          Case #PB_EventType_LeftButtonDown : redraw = #True
          Case #PB_EventType_LeftButtonUp : redraw = #True
          Case #PB_EventType_LeftClick
          Case #PB_EventType_LeftDoubleClick
          Case #PB_EventType_RightButtonDown
          Case #PB_EventType_RightButtonUp
          Case #PB_EventType_RightClick
          Case #PB_EventType_RightDoubleClick
          Case #PB_EventType_MiddleButtonDown
          Case #PB_EventType_MiddleButtonUp
          Case #PB_EventType_Focus
          Case #PB_EventType_LostFocus
          Case #PB_EventType_KeyDown
          Case #PB_EventType_KeyUp
          Case #PB_EventType_Input
          Case #PB_EventType_Resize
        EndSelect
        If redraw
          \State = state
          DrawButton(*this)
        EndIf
      EndIf
    EndWith
  EndProcedure
  
  ; ----
  
  Procedure SetText(*this.sButtonColorGadget, Text.s)
    With *this
      \Text = Text
      DrawButton(*this)
    EndWith
  EndProcedure : AsMethode(SetText)
  
  ; ----
  
  Procedure SetFont(*this.sButtonColorGadget, FontID)
    With *this
      \FontID = FontID
      DrawButton(*this)
    EndWith
  EndProcedure : AsMethode(SetFont)
  
  ; ----
  
  Procedure SetColor(*this.sButtonColorGadget, ColorType, Color)
    With *this
      Select ColorType
        Case #PB_Gadget_FrontColor
          \FrontColor = Color
        Case #PB_Gadget_BackColor
          \BackColor = Color
        Case #PB_Gadget_LineColor
          \LineColor = Color
      EndSelect
      DrawButton(*this)
    EndWith
  EndProcedure : AsMethode(SetColor)
  
  ; ----
  
  Procedure Resize(*this.sButtonColorGadget, x, y, Width, Height)
    With *this
      ResizeGadget(\Gadget, x, y, Width, Height)
      If x <> #PB_Ignore
        \x = x
      EndIf
      If y <> #PB_Ignore
        \y = y
      EndIf
      If Width <> #PB_Ignore
        \Width = Width
      EndIf
      If Height <> #PB_Ignore
        \Height = Height
      EndIf
      DrawButton(*this)
    EndWith
  EndProcedure : AsMethode(Resize)
  
  ; ----
  
  Procedure GetID(*this.sButtonColorGadget)
    ProcedureReturn *this\Gadget
  EndProcedure : AsMethode(GetID)
  
  ; ----
  
  Procedure.s GetText(*this.sButtonColorGadget)
    ProcedureReturn *this\Text
  EndProcedure : AsMethode(GetText)
  
  ; ----
  
  Procedure GetColor(*this.sButtonColorGadget, ColorType)
    Protected color
    With *this
      Select ColorType
        Case #PB_Gadget_FrontColor
          color = \FrontColor
        Case #PB_Gadget_BackColor
          color = \BackColor
        Case #PB_Gadget_LineColor
          color = \LineColor
      EndSelect
      ProcedureReturn color
    EndWith
  EndProcedure : AsMethode(GetColor)
  
  ; ----
  
  Procedure Initialize(*this.sButtonColorGadget)
    Protected result
    
    With *this
      result = CanvasGadget(\Gadget, \x, \y, \Width, \Height, \Flags)
      If result
        If \Gadget = #PB_Any
          \Gadget = result
        EndIf
        \FontID    = #PB_Default
        \LineColor = #Gray
        DrawButton(*this)
        SetGadgetData(\Gadget, *this)
        BindGadgetEvent(\Gadget, @DoEvents())
      EndIf
    EndWith
  EndProcedure : AsInitializeObject(Initialize)
  
  ; ----
  
  Procedure Dispose(*this.sButtonColorGadget)
    With *this
      If IsGadget(\Gadget)
        FreeGadget(\Gadget)
      EndIf
    EndWith
  EndProcedure : AsDisposeObject(Dispose)
  
  ; ----
  
  Procedure Create(Gadget, x, y, Width, Height, Text.s, FrontColor = $000000, BackColor = $F5F5F5, Flags = 0)
    Protected *object.sButtonColorGadget
    
    With *object
      AllocateObject(*object, sButtonColorGadget)
      If *object
        \Gadget     = Gadget
        \x          = x
        \y          = y
        \Width      = Width
        \Height     = Height
        \Text       = Text
        \FrontColor = FrontColor
        \BackColor  = BackColor
        \Flags      = Flags
      EndIf
      InitializeObject(*object)
      ProcedureReturn *object
    EndWith
  EndProcedure
  
  ; ----
  
  CheckInterface()
  
EndModule

; *****************************************************************************

;- Example

CompilerIf #PB_Compiler_IsMainFile
  
  Enumeration Windows
    #Main
  EndEnumeration
  
  Enumeration Gadgets
    #Button1
    #Button2
    #Button3
  EndEnumeration
  
  Enumeration Status
    #MainStatusBar
  EndEnumeration
  
  LoadFont(0, "Courier New", 20, #PB_Font_Bold)
  
  Procedure Main()
    ; Define button object
    Protected.ButtonColorGadget::iButtonColorGadget btn, btn2, btn3
    
    If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 480, 320, "Object ButtonColorGadget Number 42 ;)", #PB_Window_SystemMenu)
      btn  = ButtonColorGadget::Create(#Button1, 10, 10, 120, 30, "My Button", #Yellow, #Red)
      btn2 = ButtonColorGadget::Create(#Button2, 10, 80, 120, 30, "My Button 2")
      btn3 = ButtonColorGadget::Create(#Button3, 10, 120, 120, 30, "My Button 3")
      
      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_CloseWindow
            Break
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #Button1
                If EventType() = #PB_EventType_LeftClick
                  If GadgetWidth(#Button1) <= 120
                    btn\Resize(#PB_Ignore, #PB_Ignore, 240, 60)
                    btn\SetText("My Big Button")
                    btn\SetFont(FontID(0))
                    btn\SetColor(#PB_Gadget_BackColor, #Green)
                    btn\SetColor(#PB_Gadget_FrontColor, #Black)
                    btn\SetColor(#PB_Gadget_LineColor, #Red)
                  Else
                    btn\Resize(#PB_Ignore, #PB_Ignore, 120, 30)
                    btn\SetText("My Button")
                    btn\SetFont(#PB_Default)
                    btn\SetColor(#PB_Gadget_BackColor, #Red)
                    btn\SetColor(#PB_Gadget_FrontColor, #Yellow)
                    btn\SetColor(#PB_Gadget_LineColor, #Gray)
                  EndIf
                EndIf
            EndSelect
            
        EndSelect
      ForEver
      
      btn\Release()
      
    EndIf
    
  EndProcedure : Main()
  
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
captain_skank
Enthusiast
Enthusiast
Posts: 636
Joined: Fri Oct 06, 2006 3:57 pm
Location: England

Re: DPI and canvasgadget scaling

Post by captain_skank »

Thanks for that pointer, and that's what i have tried.

So to be clear the canvas gadget is DPI aware, but it's content is not and must be scaled accordingly ?

Having changed my code to include :

Code: Select all

Box(0, 0, DesktopScaledX(GadgetWidth(BTN_button)), DesktopScaledY(GadgetHeight(BTN_button)), GVAR_colour_15)
My results are as follows :

1920 x 1080 @ 100% no problem
1920 x 1080 @ 150% no problem
1024 x 768 @ 100% no problem
1024 x 768 @ 125% no problem
4096 x 2160 @ 100% scalling is all wrong - text is ok ganvasgadget and box( this is a 50" TV )
4096 x 2160 @ 225% scalling is all wrong ( this is a 50" TV )


Image

Image

In my experiments, text gadgets etc all display correctly.

So do i need to allow for the native resolution or DPI of the monitor when scalling ?

Any help appreciated.
User avatar
mk-soft
Always Here
Always Here
Posts: 5387
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DPI and canvasgadget scaling

Post by mk-soft »

Optional without Compiler-Option DPI

Show my Module ScaleGadgets :wink:
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply