Maniphest T66673

Python: BLF does not provide a way to account for monitor DPI scaling and displays inconsistently on different monitors
Closed, Archived

Assigned To
Germano Cavalcante (mano-wii)
Authored By
eldee smith (eldee)
Jul 10 2019, 7:27 PM
Tags
  • BF Blender
Subscribers
Brecht Van Lommel (brecht)
eldee smith (eldee)
Germano Cavalcante (mano-wii)

Description

System Information
Operating system: Windows-10-10.0.17763 64 Bits
Graphics card: GeForce GTX 1080/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 390.77

Blender Version
Broken: version: 2.80 (sub 74), branch: master, commit date: 2019-07-03 09:54, hash: rBf990c23bcfb5
Worked: (optional)

Short description of error
See the two attached screenshots- in the first, it is a 4k monitor with windows dpi scaling set to 150%. The second screenshot is a 1080p monitor with the default dpi scaling (100%). The attached script was written and targeted for the 4k monitor, but shows up for 1080p users as in the second shot. There is no way that I have found to reconcile this difference.

4k:

1080p:

Exact steps for others to reproduce the error
Execute the following script on a 4k display, and again on a 1080p display to reproduce the attached results.

import bpy
import bgl
import blf

def draw():
    
    font_size = 16
    font_dpi = 72
    line_height = font_size * 1.25 # ensures a bit of space between each line
    
    # Draw 3 lines of text just below the selected object name in the 3D viewport.
    lines = ["The quick brown fox", "jumped over the lazy", "bug report"]

    
    # calculate the top and left position based on whether or not the toolbar and header is visible so the text aligns with the built-in viewport text
    tool_region = None
    header_region = None
    window_region = None
    
    for r in bpy.context.area.regions:
        if r.type == "TOOLS":
            tool_region = r
        if r.type == "HEADER":
            header_region = r
        if r.type == "WINDOW":
            window_region = r
            
    desired_top = int(window_region.height) - 100
    left = 30

    if tool_region != None:
        left = tool_region.width + left
    
    if header_region != None:
        desired_top -= header_region.height
            
    
    blf.size(0, font_size, font_dpi)
    actual_top = desired_top - int(line_height * len(lines))
        
    for i, line in enumerate(lines):
        y_offset = (i - len(lines)) * -1
        blf.position(0, left, actual_top + (y_offset * line_height), 0)
        blf.draw(0, line)


try:
    bpy.types.SpaceView3D.draw_handler_remove(draw, "WINDOW")
except:
    # wasn't added yet, first run.
    pass

bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')

Event Timeline

eldee smith (eldee) created this task.Jul 10 2019, 7:27 PM
Germano Cavalcante (mano-wii) changed the task status from Unknown Status to Archived.Jul 11 2019, 6:07 PM
Germano Cavalcante (mano-wii) claimed this task.
Germano Cavalcante (mano-wii) added a subscriber: Germano Cavalcante (mano-wii).

This seems to be more a feature request than a bug.
Have you tried it with C.preferences.system.dpi?
What the blf module does is just to expose Blender's BLF built-in functions to python.

eldee smith (eldee) added a comment.Jul 11 2019, 6:26 PM

It's not a feature request, so far as I know, unless I'm missing something. The issue is that there is no way to ensure the end result is 100% identical on different displays that have different dpi. it doesn't matter what I set the dpi to in blf.size, it will look incorrect regardless. For example, if I set the dpi in blf.size to bpy.context.preferences.system.dpi, I get the following result in my 4k monitor (with a dpi of 108, according to system.dpi):

and this result in my 1080p monitor (with a dpi of 72):

I can't create a consistent user experience across all display types when using BLF

Brecht Van Lommel (brecht) added a subscriber: Brecht Van Lommel (brecht).Jul 11 2019, 6:29 PM

system.dpi should not be used, it's deprecated.

Instead scale any UI elements including text by this:
https://docs.blender.org/api/master/bpy.types.PreferencesSystem.html?highlight=system%20dpi#bpy.types.PreferencesSystem.ui_scale

eldee smith (eldee) added a comment.Jul 11 2019, 6:33 PM
In T66673#718427, @Brecht Van Lommel (brecht) wrote:

system.dpi should not be used, it's deprecated.

Instead scale any UI elements including text by this:
https://docs.blender.org/api/master/bpy.types.PreferencesSystem.html?highlight=system%20dpi#bpy.types.PreferencesSystem.ui_scale

the UI scale value has not been changed between those two shots, they are both 1.

Brecht Van Lommel (brecht) added a comment.EditedJul 11 2019, 6:38 PM

This is not equal to the value in the preferences, it takes into account DPI. Did you check that bpy.preferences.system.ui_scale is actually the same on both?

eldee smith (eldee) added a comment.Jul 11 2019, 7:05 PM

Aha! now that is a detail that I was not aware of. I had incorrectly assumed that ui_scale was simply the value that appears in preferences->interface, I never actually queried the value. It does correctly report a ui_scale that takes dpi into consideration, and now that I have a multiplier I can create consistent results on any display. Thanks for the guidance!