Source code for unit.canvas.drawing.utils

# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Timeline is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Timeline.  If not, see <http://www.gnu.org/licenses/>.


from random import random

from timelinelib.calendar.gregorian.timetype import GregorianTimeType
from timelinelib.calendar.num.timetype.timetype import NumTimeType
from timelinelib.canvas.data.timeperiod import TimePeriod
from timelinelib.canvas.drawing.utils import darken_color
from timelinelib.canvas.drawing.utils import lighten_color
from timelinelib.canvas.drawing.utils import Metrics
from timelinelib.test.cases.unit import UnitTestCase
from timelinelib.test.utils import human_time_to_gregorian


WIDTH = 200
HEIGHT = 100
START_TIME = human_time_to_gregorian("1 Jan 9988 00:00")
END_TIME = human_time_to_gregorian("1 Jan 9988 00:01")
START_NUM_TIME = 0
END_NUM_TIME = 1


[docs]class MetricsTestCase(UnitTestCase):
[docs] def setUp(self): self.given_a_screen()
[docs] def given_a_gregorian_scene_period(self, start_time=START_TIME, end_time=END_TIME): self.time_type = GregorianTimeType() self.time_period = TimePeriod(start_time, end_time) self.metrics = Metrics(self.screen_size, self.time_type, self.time_period, 50)
[docs] def given_a_numeric_scene_period(self, start_time=START_NUM_TIME, end_time=END_NUM_TIME): self.time_type = NumTimeType() self.time_period = TimePeriod(start_time, end_time) self.metrics = Metrics(self.screen_size, self.time_type, self.time_period, 50)
[docs] def given_a_screen(self, width=WIDTH, height=HEIGHT): self.screen_size = (width, height)
[docs]class describe_gregorian_overflow_error(MetricsTestCase):
[docs] def test_x_is_zero_at_period_start(self): self.given_a_gregorian_scene_period() self.assertEqual(0, self.metrics.calc_x(START_TIME))
[docs] def test_x_is_width_at_period_end(self): self.given_a_gregorian_scene_period() self.assertEqual(WIDTH, self.metrics.calc_x(END_TIME))
[docs] def test_x_can_be_negative(self): self.given_a_gregorian_scene_period() time = human_time_to_gregorian("1 Jan -4700") self.assertTrue(self.metrics.calc_x(time) < 0)
[docs]class describe_numeric_overflow_error(MetricsTestCase):
[docs] def test_x_is_zero_at_period_start(self): self.given_a_numeric_scene_period() self.assertEqual(0, self.metrics.calc_x(START_NUM_TIME))
[docs] def test_x_is_width_at_period_end(self): self.given_a_numeric_scene_period() self.assertEqual(WIDTH, self.metrics.calc_x(END_NUM_TIME))
[docs] def test_x_can_be_negative(self): self.given_a_numeric_scene_period() time = -10000 self.assertTrue(self.metrics.calc_x(time) < 0)
[docs] def test_negative_overflow_is_handled(self): self.given_a_numeric_scene_period() time = -1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 self.assertEqual(-1, self.metrics.calc_x(time))
[docs] def test_positive_overflow_is_handled(self): self.given_a_numeric_scene_period() time = 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 self.assertEqual(WIDTH + 1, self.metrics.calc_x(time))
[docs]class describe_drawing_utils(UnitTestCase):
[docs] def test_darken_color_good_factor(self): randColor = self.random_color() randFactor = random() newColor = darken_color(randColor, randFactor) for x in newColor: self.assertTrue(x >= 0 and x <= 255)
[docs] def test_darken_color_bad_factor(self): lowFactor = random() * 256 - 256 # -256 < factor < 0 highFactor = 1 + random() * 255 # 1 < factor < 256 randColor = self.random_color() self.assertEqual(randColor, darken_color(randColor, lowFactor)) self.assertEqual(randColor, darken_color(randColor, highFactor))
[docs] def test_lighten_color_good_factor(self): randColor = self.random_color() randFactor = 1 + random() * 254 # 1 < factor < 255 newColor = lighten_color(randColor, randFactor) for x in newColor: self.assertTrue(x >= 0 and x <= 255)
[docs] def test_lighten_color_bad_factor(self): lowFactor = random() * 257 - 256 # -256 < factor < 1 highFactor = 255 + random() # 255 < factor < 256 randColor = self.random_color() self.assertEqual(randColor, lighten_color(randColor, lowFactor)) self.assertEqual(randColor, lighten_color(randColor, highFactor))
[docs] def random_color(self): return tuple([int(random() * 256) for _ in (1, 2, 3)])