test-kivy-app/kivy_venv/lib/python3.11/site-packages/kivy/tests/test_graphics.py

1150 lines
34 KiB
Python
Raw Permalink Normal View History

2024-09-15 12:12:16 +00:00
'''
Graphics tests
==============
Testing the simple vertex instructions
'''
import sys
import pytest
import itertools
from threading import Thread
from kivy.tests.common import GraphicUnitTest, requires_graphics
class BoxShadowTest(GraphicUnitTest):
def test_create(self):
from kivy.graphics.boxshadow import BoxShadow
from kivy.uix.widget import Widget
from kivy.graphics import Color
r = self.render
# with initial arguments
wid = Widget()
with wid.canvas:
Color(1, 0, 0, 1)
bs = BoxShadow(
pos=(50, 50),
size=(150, 150),
offset=(0, 10),
spread_radius=(10, -10),
border_radius=(10, 10, 10, 10),
blur_radius=80,
)
r(wid)
wid = Widget()
with wid.canvas:
Color(0, 1, 0, 1)
bs = BoxShadow(
inset=True,
pos=(50, 50),
size=(150, 150),
offset=(0, 10),
spread_radius=(10, -10),
border_radius=(10, 10, 10, 10),
blur_radius=80,
)
r(wid)
# changing properties later
wid = Widget()
with wid.canvas:
Color(0, 0, 1, 1)
bs = BoxShadow()
bs.inset = True
bs.pos = [50, 50]
bs.size = [150, 150]
bs.offset = [0, 10]
bs.spread_radius = [10, -10]
bs.border_radius = [10, 10, 10, 10]
bs.blur_radius = 40
r(wid)
def test_adjusted_size(self):
from kivy.graphics.boxshadow import BoxShadow
raw_size = 150, 150
bs = BoxShadow()
bs.pos = 50, 50
bs.size = raw_size
bs.blur_radius = 80
bs.spread_radius = -10, 10
# The size of the rectangle containing the FBO texture (shadow) needs
# to be adjusted according to the size of the shadow, otherwise there
# will be an unwanted cropping behavior.
adjusted_size = (
max(
0,
raw_size[0] + bs.blur_radius * 3 + bs.spread_radius[0] * 2,
),
max(
0,
raw_size[1] + bs.blur_radius * 3 + bs.spread_radius[1] * 2,
),
)
assert bs.size == adjusted_size
# Now we will turn on the inset mode, it is expected that
# there will be no size adjustments.
bs.inset = True
assert bs.size == raw_size
# Now turning off, and reverting back to the default mode.
bs.inset = False
assert bs.size == adjusted_size
# Testing with initial arguments
bs = BoxShadow(
inset=True,
pos=(50, 50),
size=raw_size,
blur_radius=80,
spread_radius=(10, -10)
)
adjusted_size = (
max(
0,
raw_size[0] + bs.blur_radius * 3 + bs.spread_radius[0] * 2,
),
max(
0,
raw_size[1] + bs.blur_radius * 3 + bs.spread_radius[1] * 2,
),
)
assert bs.size == raw_size
# Now turning off, and reverting back to the default mode.
bs.inset = False
assert bs.size == adjusted_size
# Now we will turn on the inset mode, it is expected that
# there will be no size adjustments.
bs.inset = True
assert bs.size == raw_size
def test_adjusted_pos(self):
from kivy.graphics.boxshadow import BoxShadow
raw_pos = 50, 50
raw_size = 150, 150
offset = 10, -100
bs = BoxShadow()
bs.pos = raw_pos
bs.size = raw_size
bs.offset = offset
bs.blur_radius = 80
bs.spread_radius = -10, 10
# If the size of the rectangle containing the FBO texture (shadow)
# changes, its position will need to be adjusted.
adjusted_pos = (
raw_pos[0]
- bs.blur_radius * 1.5
- bs.spread_radius[0]
+ bs.offset[0],
raw_pos[0]
- bs.blur_radius * 1.5
- bs.spread_radius[1]
+ bs.offset[1],
)
assert bs.pos == adjusted_pos
# Now we will turn on the inset mode, it is expected that
# there will be no position adjustments.
bs.inset = True
assert bs.pos == raw_pos
# Now turning off, and reverting back to the default mode.
bs.inset = False
assert bs.pos == adjusted_pos
# Testing with initial arguments
bs = BoxShadow(
inset=True,
pos=raw_pos,
size=raw_size,
offset=offset,
blur_radius=80,
spread_radius=(10, -10)
)
adjusted_pos = (
raw_pos[0]
- bs.blur_radius * 1.5
- bs.spread_radius[0]
+ bs.offset[0],
raw_pos[0]
- bs.blur_radius * 1.5
- bs.spread_radius[1]
+ bs.offset[1],
)
assert bs.pos == raw_pos
# Now turning off, and reverting back to the default mode.
bs.inset = False
assert bs.pos == adjusted_pos
# Now we will turn on the inset mode, it is expected that
# there will be no position adjustments.
bs.inset = True
assert bs.pos == raw_pos
def test_bounded_properties(self):
from kivy.graphics.boxshadow import BoxShadow
bs = BoxShadow()
bs.pos = 50, 50
bs.size = 150, 150
bs.offset = 10, -100
bs.blur_radius = -80
bs.spread_radius = -200, -100
bs.border_radius = 0, 0, 100, 0
assert bs.size == (0, 0)
assert bs.blur_radius == 0
# There is a bug in RoundedRectangle that distorts the texture if the
# radius value is less than 1. Otherwise, it could be 0.
assert bs.border_radius == tuple(
map(
lambda value: max(1.0, min(value, min(bs.size) / 2)),
bs.border_radius,
)
)
# Testing with initial arguments
bs = BoxShadow(
pos=(50, 50),
size=(150, 150),
offset=(10, -100),
blur_radius=-80,
spread_radius=(-200, -100),
border_radius=(0, 0, 100, 0),
)
assert bs.size == (0, 0)
assert bs.blur_radius == 0
assert bs.border_radius == tuple(
map(
lambda value: max(1.0, min(value, min(bs.size) / 2)),
bs.border_radius,
)
)
def test_canvas_management(self):
from kivy.graphics.boxshadow import BoxShadow
from kivy.uix.widget import Widget
from kivy.graphics import Color
r = self.render
wid = Widget()
with wid.canvas:
bs = BoxShadow()
r(wid)
assert bs in wid.canvas.children
wid = Widget()
bs = BoxShadow()
wid.canvas.add(Color(1, 0, 0, 1))
wid.canvas.add(bs)
r(wid)
assert bs in wid.canvas.children
wid.canvas.remove(bs)
assert bs not in wid.canvas.children
wid.canvas.insert(1, bs)
assert bs in wid.canvas.children
assert wid.canvas.children.index(bs) == 1
class VertexInstructionTest(GraphicUnitTest):
def test_circle(self):
from kivy.uix.widget import Widget
from kivy.graphics import Ellipse, Color
r = self.render
# basic circle
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
Ellipse(pos=(100, 100), size=(100, 100))
r(wid)
# reduced circle
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
Ellipse(pos=(100, 100), size=(100, 100), segments=10)
r(wid)
# moving circle
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
self.e = Ellipse(pos=(100, 100), size=(100, 100))
self.e.pos = (10, 10)
r(wid)
def test_ellipse(self):
from kivy.uix.widget import Widget
from kivy.graphics import Ellipse, Color
r = self.render
# ellipse
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
self.e = Ellipse(pos=(100, 100), size=(200, 100))
r(wid)
def test_point(self):
from kivy.uix.widget import Widget
from kivy.graphics import Point, Color
r = self.render
# 1 point
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
Point(points=(10, 10))
r(wid)
# 25 points
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
Point(points=[x * 5 for x in range(50)])
r(wid)
def test_point_add(self):
from kivy.uix.widget import Widget
from kivy.graphics import Point, Color
r = self.render
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
p = Point(pointsize=10)
p.add_point(10, 10)
p.add_point(90, 10)
p.add_point(10, 90)
p.add_point(50, 50)
p.add_point(10, 50)
p.add_point(50, 10)
r(wid)
def test_line_rounded_rectangle(self):
from kivy.uix.widget import Widget
from kivy.graphics import Line, Color
r = self.render
# basic rounded_rectangle
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
line = Line(
rounded_rectangle=(100, 100, 100, 100, 10, 20, 30, 40, 100)
)
r(wid)
assert line.rounded_rectangle == (
100, 100, 100, 100, 10, 20, 30, 40, 100
)
# The largest angle allowed is equal to the smallest dimension (width
# or height) minus the largest angle value between the anterior angle
# and the posterior angle.
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
line = Line(
rounded_rectangle=(
100, 100, 100, 100, 100, 20, 10, 30, 100
)
)
r(wid)
assert line.rounded_rectangle == (
100, 100, 100, 100, 70, 20, 10, 30, 100
)
# Same approach as above
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
line = Line(
rounded_rectangle=(
100, 100, 100, 100, 100, 25, 100, 50, 100
)
)
r(wid)
assert line.rounded_rectangle == (
100, 100, 100, 100, 50, 25, 50, 50, 100
)
# A circle should be generated if width and height are equal, and all
# angles passed are greater than or equal to the smallest dimension.
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
line = Line(
rounded_rectangle=(
100, 100, 100, 100, 150, 50, 50.001, 51, 100
)
)
r(wid)
assert line.rounded_rectangle == (
100, 100, 100, 100, 50, 50, 50, 50, 100
)
# Currently the minimum radius should be 1, to avoid rendering issues
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
line = Line(
rounded_rectangle=(
100, 100, 100, 100, 0, 0, 0, 0, 100
)
)
r(wid)
assert line.rounded_rectangle == (
100, 100, 100, 100, 1, 1, 1, 1, 100
)
# Angles adjustment + avoid issue if radius is less than 1
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
line = Line(
rounded_rectangle=(
100, 100, 100, 100, 100, 0, 0, 0, 100
)
)
r(wid)
assert line.rounded_rectangle == (
100, 100, 100, 100, 99, 1, 1, 1, 100
)
def test_smoothline_rounded_rectangle(self):
from kivy.uix.widget import Widget
from kivy.graphics import SmoothLine, Color
r = self.render
# If width and/or height < 2px, the figure should not be rendered.
# This avoids some known SmoothLine rendering issues.
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
line = SmoothLine(
rounded_rectangle=(100, 100, 0.5, 1.99, 30, 30, 30, 30, 100)
)
r(wid)
assert line.rounded_rectangle is None
def test_enlarged_line(self):
from kivy.uix.widget import Widget
from kivy.graphics import Line, Color, PushMatrix, PopMatrix, Scale, \
Translate
r = self.render
wid = Widget()
with wid.canvas:
Color(1, 1, 1)
# Normal line with width 1
Line(
points=(10, 10, 10, 90),
width=1
)
# Normal line with width 3
Line(
points=(20, 10, 20, 90),
width=3
)
# Enlarged line that should look width 3
PushMatrix()
Translate(30, 10, 1) # So the enlargement goes around 0, 0, 0
Scale(3, 1, 1) # X scaled by 3 so the line width should become 3
Line(
points=(0, 0, 0, 80),
width=1,
force_custom_drawing_method=True
)
PopMatrix()
r(wid)
class SmoothVertexInstructionTest(GraphicUnitTest):
# Code defined in the points setter of AntiAliasingLine class.
def _convert_points(self, points):
if points and isinstance(points[0], (list, tuple)):
return list(itertools.chain(*points))
else:
return list(points)
# The same function present in the AntiAliasingLine code,
# externalized for testing.
def _filtered_points(self, points):
index = 0
p = self._convert_points(points)
# At least 3 points are required, otherwise we will return an empty
# list, which means there are no valid points.
if len(p) < 6:
return []
while index < len(p) - 2:
x1, y1 = p[index], p[index + 1]
x2, y2 = p[index + 2], p[index + 3]
if abs(x2 - x1) < 1.0 and abs(y2 - y1) < 1.0:
del p[index + 2: index + 4]
else:
index += 2
if abs(p[0] - p[-2]) < 1.0 and abs(p[1] - p[-1]) < 1.0:
del p[:2]
return p
def _get_texture(self):
from kivy.graphics.texture import Texture
return Texture.create()
def test_antialiasing_line(self):
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle, Instruction
from kivy.graphics.vertex_instructions import AntiAliasingLine
r = self.render
# We expect a type error to be thrown if stencil_mask is not an object
# of type Instruction.
with pytest.raises(TypeError):
AntiAliasingLine(None, points=[10, 20, 30, 20, 30, 10])
# No TypeError here.
target_rect = Rectangle()
AntiAliasingLine(target_rect, points=[10, 20, 30, 40, 50, 60])
# Test the gradient responsible for the "smooth line" effect.
pixels = b"\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\x00"
instruction = Instruction()
aa_line = AntiAliasingLine(instruction)
assert aa_line.texture.pixels == pixels
# check the width, defined through tests with the custom texture.
assert aa_line.width == 2.5
# This set of points must remain unchanged.
points_1 = [51.0, 649.0, 199.0, 649.0, 199.0, 501.0, 51.0, 501.0]
# This set of points should be reduced from 16 to 8.
points_2 = [
261.0, 275.0,
335.0, 349.0,
335.0, 349.0,
409.0, 275.0,
409.0, 275.0,
335.0, 201.0,
335.0, 201.0,
261.0, 275.0
]
# This set of points should be reduced from 72 to 50.
points_3 = [
260.0, 275.0,
261.0, 275.0,
261.0, 275.0,
261.999999999999, 275.99999999,
261.06667650085353, 278.14064903651496,
261.26658584785304, 281.2756384111877,
261.56658584785305, 281.3756384111877,
261.5993677908431, 284.39931866126904,
262.0644226342696, 287.50606070381684,
262.0644226342696, 287.50606070381684,
262.6609123178712, 290.59026597968375,
263.3877619269211, 293.6463765424993,
264.2436616292954, 296.66888507446475,
265.22706903587977, 299.65234481091227,
265.22706903587977, 299.65234481091227,
266.3362119800583, 302.59137935574284,
267.5690917112779, 305.48069237005546,
268.9234864969319, 308.31507711650784,
270.39695562607204, 311.089425842209,
270.89695562607204, 311.589425842209,
271.98684380773494, 313.7987389832352,
273.69028595595563, 316.4381341741821,
275.50421235284637, 319.00285504651725,
275.50421235284637, 319.00285504651725,
277.4253541804354, 321.48827979987755,
279.45024941129833, 323.8899295308661,
281.57524904736516, 326.20347630433844,
283.79652369566156, 328.4247509526349,
283.99652369566156, 328.7247509526349,
286.1100704691339, 330.54975058870167,
288.5117202001224, 332.5746458195646,
288.5117202001224, 332.5746458195646,
290.99714495348275, 334.4957876471537,
293.5618658258179, 336.3097140440444,
293.5618658258179, 336.3097140440444,
293.2618658258179, 336.1097140440444
]
# This set of points should be reduced to [].
points_4 = [100, 100, 200, 100]
# line closed (default)
for points in (points_1, points_2, points_3, points_4):
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
inst = Instruction()
aa_line = AntiAliasingLine(inst, points=points)
r(wid)
filtered_points = self._filtered_points(points)
assert aa_line.points == filtered_points + filtered_points[:2]
# without closing the line
for points in (points_1, points_2, points_3, points_4):
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
inst = Instruction()
aa_line = AntiAliasingLine(inst, points=points, close=0)
r(wid)
assert aa_line.points == self._filtered_points(points)
def test_smoothrectangle(self):
from kivy.uix.widget import Widget
from kivy.graphics import Color, SmoothRectangle
r = self.render
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
rect = SmoothRectangle(pos=(100, 100), size=(150, 150))
r(wid)
filtered_points = self._filtered_points(rect.points)
assert (
rect.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# test if antialiasing is disabled if the graphic has one of its
# dimensions decreased to less than 4px.
rect.size = (150, -2)
r(wid)
assert rect.antialiasing_line_points == []
rect.size = (150, 2)
r(wid)
assert rect.antialiasing_line_points == []
# re-enable antialiasing line rendering.
rect.size = (150, 150)
r(wid)
assert (
rect.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# disabling antialiasing.
rect.texture = self._get_texture()
r(wid)
assert rect.antialiasing_line_points == []
# re-enable antialiasing.
rect.source = ""
r(wid)
assert (
rect.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# test if antialiasing is disabled if the graphic is initialized with
# at least one of its dimensions less than 4px.
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
rect = SmoothRectangle(pos=(100, 100), size=(150, -3))
r(wid)
assert rect.antialiasing_line_points == []
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
rect = SmoothRectangle(pos=(100, 100), size=(3.99, 3.99))
r(wid)
assert rect.antialiasing_line_points == []
def test_smoothroundedrectangle(self):
from kivy.uix.widget import Widget
from kivy.graphics import Color, SmoothRoundedRectangle
r = self.render
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
rounded_rect = SmoothRoundedRectangle(
pos=(100, 100),
size=(150, 150),
radius=[(10, 50), (100, 50), (0, 150), (200, 50)],
segments=60,
)
r(wid)
filtered_points = self._filtered_points(rounded_rect.points)
assert (
rounded_rect.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# test if antialiasing is disabled if the graphic has one of its
# dimensions decreased to less than 4px.
rounded_rect.size = (150, -2)
r(wid)
assert rounded_rect.antialiasing_line_points == []
rounded_rect.size = (150, 2)
r(wid)
assert rounded_rect.antialiasing_line_points == []
# re-enable antialiasing line rendering.
rounded_rect.size = (150, 150)
r(wid)
assert (
rounded_rect.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# disabling antialiasing.
rounded_rect.texture = self._get_texture()
r(wid)
assert rounded_rect.antialiasing_line_points == []
# re-enable antialiasing.
rounded_rect.source = ""
r(wid)
assert (
rounded_rect.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
rounded_rect = SmoothRoundedRectangle(
pos=(100, 100), size=(150, 150), segments=0
)
r(wid)
filtered_points = self._filtered_points(rounded_rect.points)
assert (
rounded_rect.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# test if antialiasing is disabled if the graphic is initialized with
# at least one of its dimensions less than 4px.
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
rounded_rect = SmoothRoundedRectangle(
pos=(100, 100), size=(150, -3)
)
r(wid)
assert rounded_rect.antialiasing_line_points == []
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
rounded_rect = SmoothRoundedRectangle(
pos=(100, 100), size=(3.99, 3.99)
)
r(wid)
assert rounded_rect.antialiasing_line_points == []
def test_smoothellipse(self):
from kivy.uix.widget import Widget
from kivy.graphics import Color, SmoothEllipse
r = self.render
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
ellipse = SmoothEllipse(pos=(100, 100), size=(150, 150))
r(wid)
ellipse_center = [
ellipse.pos[0] + ellipse.size[0] / 2,
ellipse.pos[1] + ellipse.size[1] / 2,
]
filtered_points = self._filtered_points(
ellipse.points + ellipse_center
)
assert (
ellipse.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# test if antialiasing is disabled if the graphic has one of its
# dimensions decreased to less than 4px
ellipse.size = (150, -2)
r(wid)
assert ellipse.antialiasing_line_points == []
ellipse.size = (150, 2)
r(wid)
assert ellipse.antialiasing_line_points == []
# re-enable antialiasing line rendering.
ellipse.size = (150, 150)
r(wid)
assert (
ellipse.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# disabling antialiasing.
ellipse.texture = self._get_texture()
r(wid)
assert ellipse.antialiasing_line_points == []
# re-enable antialiasing.
ellipse.source = ""
r(wid)
assert (
ellipse.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
ellipse = SmoothEllipse(
pos=(100, 100), size=(150, 150), angle_start=90, angle_end=-120
)
r(wid)
ellipse_center = [
ellipse.pos[0] + ellipse.size[0] / 2,
ellipse.pos[1] + ellipse.size[1] / 2,
]
filtered_points = self._filtered_points(
ellipse.points + ellipse_center
)
assert (
ellipse.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# test if antialiasing is disabled if the graphic is initialized with
# at least one of its dimensions less than 4px.
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
ellipse = SmoothEllipse(pos=(100, 100), size=(150, -3))
r(wid)
assert ellipse.antialiasing_line_points == []
wid = Widget()
with wid.canvas:
Color(1, 1, 1, 0.5)
ellipse = SmoothEllipse(pos=(100, 100), size=(3.99, 3.99))
r(wid)
assert ellipse.antialiasing_line_points == []
def test_smoothtriangle(self):
from kivy.uix.widget import Widget
from kivy.graphics import Color, SmoothTriangle
r = self.render
wid = Widget()
with wid.canvas:
Color(1, 0, 0, 0.5)
triangle = SmoothTriangle(
points=[
100, 100,
200, 100,
150, 200,
500, 500, 400, 400 # Irrelevant, just for testing purposes
]
)
r(wid)
filtered_points = self._filtered_points(triangle.points[:6])
assert (
triangle.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
wid = Widget()
with wid.canvas:
Color(0, 0, 1, 0.5)
triangle = SmoothTriangle(
points=[
125, 200,
200, 100,
100, 100,
500, 500, 400, 400 # Irrelevant, just for testing purposes
]
)
r(wid)
filtered_points = self._filtered_points(triangle.points[:6])
assert (
triangle.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# Test disabling antialiasing if the points are very close.
wid = Widget()
with wid.canvas:
Color(0, 1, 0, 0.5)
triangle = SmoothTriangle(
points=[100, 100, 100.5, 100, 100, 100.5]
)
r(wid)
assert triangle.antialiasing_line_points == []
# re-enable antialiasing line rendering.
triangle.points = [125, 200, 200, 100, 100, 100]
r(wid)
assert (
triangle.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# disabling antialiasing.
triangle.texture = self._get_texture()
r(wid)
assert triangle.antialiasing_line_points == []
# re-enable antialiasing.
triangle.source = ""
r(wid)
assert (
triangle.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
def test_smoothquad(self):
from kivy.uix.widget import Widget
from kivy.graphics import Color, SmoothQuad
r = self.render
wid = Widget()
with wid.canvas:
Color(1, 0, 0, 0.5)
quad = SmoothQuad(points=[100, 100, 100, 200, 200, 200, 200, 100])
r(wid)
filtered_points = self._filtered_points(quad.points)
assert (
quad.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
wid = Widget()
with wid.canvas:
Color(1, 0, 0, 0.5)
quad = SmoothQuad(points=[200, 100, 200, 200, 100, 200, 100, 100])
r(wid)
filtered_points = self._filtered_points(quad.points)
assert (
quad.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# Test disabling antialiasing if the points are very close.
wid = Widget()
with wid.canvas:
Color(0, 1, 0, 0.5)
quad = SmoothQuad(
points=[200, 100, 200, 100.8, 100, 100.8, 100, 100]
)
r(wid)
assert quad.antialiasing_line_points == []
# re-enable antialiasing line rendering.
quad.points = [200, 100, 200, 200, 100, 200, 100, 100]
r(wid)
assert (
quad.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
# disabling antialiasing.
quad.texture = self._get_texture()
r(wid)
assert quad.antialiasing_line_points == []
# re-enable antialiasing.
quad.source = ""
r(wid)
assert (
quad.antialiasing_line_points
== filtered_points + filtered_points[:2]
)
class FBOInstructionTestCase(GraphicUnitTest):
def test_fbo_pixels(self):
from kivy.graphics import Fbo, ClearColor, ClearBuffers, Ellipse
fbo = Fbo(size=(512, 512))
with fbo:
ClearColor(0, 0, 0, 1)
ClearBuffers()
Ellipse(pos=(100, 100), size=(100, 100))
fbo.draw()
data = fbo.pixels
fbo.texture.save('results.png')
class TransformationsTestCase(GraphicUnitTest):
def test_identity_creation(self):
from kivy.graphics import LoadIdentity
mat = LoadIdentity()
self.assertTrue(mat.stack)
def check_transform_works(self, transform_type):
# Normal args
transform = transform_type(0, 1, 2)
self.assertEqual(transform.x, 0)
self.assertEqual(transform.y, 1)
self.assertEqual(transform.z, 2)
# Key word args
transform = transform_type(x=0, y=1)
self.assertEqual(transform.x, 0)
self.assertEqual(transform.y, 1)
transform = transform_type(x=0, y=1, z=2)
self.assertEqual(transform.x, 0)
self.assertEqual(transform.y, 1)
self.assertEqual(transform.z, 2)
def test_translate_creation(self):
from kivy.graphics import Translate
self.check_transform_works(Translate)
def test_scale_creation(self):
from kivy.graphics import Scale
self.check_transform_works(Scale)
class CallbackInstructionTest(GraphicUnitTest):
def test_from_kv(self):
from textwrap import dedent
from kivy.lang import Builder
root = Builder.load_string(dedent("""\
Widget:
canvas:
Callback:
callback: lambda __: setattr(self, 'callback_test', 'TEST')
"""))
r = self.render
r(root)
self.assertTrue(root.callback_test == 'TEST')
@pytest.fixture
def widget_verify_thread(request):
from kivy.uix.widget import Widget
from kivy.config import Config
original = Config.get('graphics', 'verify_gl_main_thread')
Config.set('graphics', 'verify_gl_main_thread', request.param)
widget = Widget()
yield widget, request.param
Config.set('graphics', 'verify_gl_main_thread', original)
@requires_graphics
@pytest.mark.parametrize('widget_verify_thread', ['0', '1'], indirect=True)
def test_graphics_main_thread(widget_verify_thread):
from kivy.graphics import Color
widget, verify_thread = widget_verify_thread
with widget.canvas:
color = Color()
color.rgb = .1, .2, .3
@requires_graphics
@pytest.mark.parametrize('widget_verify_thread', ['0', '1'], indirect=True)
def test_create_graphics_second_thread(widget_verify_thread):
from kivy.graphics import Color
widget, verify_thread = widget_verify_thread
exception = None
def callback():
nonlocal exception
try:
with widget.canvas:
if verify_thread == '1':
with pytest.raises(TypeError):
Color()
else:
Color()
except BaseException as e:
exception = e, sys.exc_info()[2]
raise
thread = Thread(target=callback)
thread.start()
thread.join()
if exception is not None:
raise exception[0].with_traceback(exception[1])
@requires_graphics
@pytest.mark.parametrize('widget_verify_thread', ['0', '1'], indirect=True)
def test_change_graphics_second_thread(widget_verify_thread):
from kivy.graphics import Color
widget, verify_thread = widget_verify_thread
with widget.canvas:
color = Color()
exception = None
def callback():
nonlocal exception
try:
if verify_thread == '1':
with pytest.raises(TypeError):
color.rgb = .1, .2, .3
else:
color.rgb = .1, .2, .3
except BaseException as e:
exception = e, sys.exc_info()[2]
raise
thread = Thread(target=callback)
thread.start()
thread.join()
if exception is not None:
raise exception[0].with_traceback(exception[1])