Skip to content

Instantly share code, notes, and snippets.

@maludwig
Created February 25, 2019 00:12
Show Gist options
  • Save maludwig/fe5a1d73ed039717767d43d0ea2f807f to your computer and use it in GitHub Desktop.
Save maludwig/fe5a1d73ed039717767d43d0ea2f807f to your computer and use it in GitHub Desktop.
Describes a bug with retina displays
import colorsys
from itertools import cycle
from math import floor
import arcade
from arcade.color import WHITE, RED, GREEN, BLUE
from pyglet import gl
WINDOW_WIDTH = 1000
WINDOW_HEIGHT = 600
PIXEL_COUNT = WINDOW_WIDTH * WINDOW_HEIGHT
MSG = """
Window Size: {}
Viewport Size: {}
HDPI Scaling Factor: {}
Is Retina Display: {}
"""
issue_text_y = 0
def generate_fully_bright_colors(count):
color_list = []
for i in range(count):
h = ((i * 3) % count) / count
r, g, b = [floor(fp * 255) for fp in colorsys.hls_to_rgb(h, 0.7, 1)]
color_list.append((r, g, b))
return color_list
def ruler_from(x, y):
# Weirdly draws one point every 2 actual pixels
# But this helps to see the issues also
arcade.draw_point(x, y, WHITE, 1)
arcade.draw_point(x, y + 1, RED, 1)
arcade.draw_point(x, y + 2, BLUE, 1)
arcade.draw_point(x, y + 3, GREEN, 1)
def disable_antialiasing():
# Disables fancy line blending for easier visualization of the problems
def noop(*args):
pass
gl.glEnable = noop
gl.glDisable(gl.GL_BLEND)
gl.glDisable(gl.GL_LINE_SMOOTH)
color_cycle = cycle(generate_fully_bright_colors(11))
issue_color = next(color_cycle)
def highlight_issue(grid_x, grid_y, text=""):
global issue_text_y, issue_color
if text != "":
issue_color = next(color_cycle)
issue_text_y += 50
arcade.draw_text(text, 500, issue_text_y, issue_color)
center_x = 25 + (grid_x * 50)
center_y = 25 + (grid_y * 50)
arcade.draw_rectangle_outline(center_x, center_y, 50, 50, issue_color, 3)
# Open the window. Set the window title and dimensions (width and height)
arcade.open_window(WINDOW_WIDTH, WINDOW_HEIGHT, "Retina Bug Examples")
arcade.start_render()
# You don't need to do this, but it does make things a lot easier to see
disable_antialiasing()
# Detect if its a retina display
v = arcade.get_viewport()
win = arcade.get_window()
win_size = win.get_size()
viewport_size = win.get_viewport_size()
hdpi_scaling_factor = viewport_size[0] / win_size[0]
is_retina_display = hdpi_scaling_factor != 1
print(MSG.format(win_size, viewport_size, hdpi_scaling_factor, is_retina_display))
# Shows the various issues
for w in range(0, 10):
for h in range(0, 10):
x_offset = 50 * w + 10
y_offset = 50 * h + 10
ruler_from(x_offset - 2, y_offset)
l, r, t, b = x_offset, x_offset + w, y_offset + h, y_offset
if (w + h) % 2 == 0:
arcade.draw_lrtb_rectangle_filled(l, r, t, b, next(color_cycle))
else:
arcade.draw_line(l, b, r, t, next(color_cycle), 1)
# print(l, r, t, b)
# Adjacent rectangles
arcade.draw_lrtb_rectangle_filled(10, 19, 540, 510, next(color_cycle))
arcade.draw_lrtb_rectangle_filled(20, 29, 540, 510, next(color_cycle))
# Rectangles
arcade.draw_rectangle_outline(125, 525, 10, 10, next(color_cycle), 3)
ruler_from(117, 529)
# Adjacent lines
arcade.draw_line(210, 540, 240, 510, next(color_cycle))
arcade.draw_line(211, 540, 241, 510, next(color_cycle))
# Highlight issues
highlight_issue(0, 0, "Adjacent pixels are not adjacent")
highlight_issue(6, 0, "Filled rectangles fail to fill when l=r or t=b")
highlight_issue(1, 1, "Sometimes things are offset by one pixel")
highlight_issue(1, 3)
highlight_issue(2, 4)
highlight_issue(0, 7, "Lines have a 1px width, when they should have 2")
highlight_issue(0, 10, "Adjacent Rectangles are not adjacent")
highlight_issue(2, 10, "Rectangle border width is not scaled, is 3px instead of 6px")
highlight_issue(4, 10, "Adjacent Lines are not adjacent")
arcade.finish_render()
arcade.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment