Skip to content

Commit

Permalink
Merge 70edcee into cfc3a76
Browse files Browse the repository at this point in the history
  • Loading branch information
itziakos committed Dec 12, 2014
2 parents cfc3a76 + 70edcee commit 71f7aa1
Show file tree
Hide file tree
Showing 17 changed files with 451 additions and 6 deletions.
11 changes: 9 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ python:
- '2.7_with_system_site_packages'
- 2.6
before_install:
# For Python 2.7, install PyQt4
- sudo apt-get update
# For Python 2.7, install PyQt4 and cairo
- if [[ $TRAVIS_PYTHON_VERSION == '2.7_with_system_site_packages' ]]; then source .travis_before_install; fi
# PyQt can't be installed on 2.6; run the tests without Qt
# PyQt and cairo can't be installed on 2.6; run the tests without Qt
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then source .travis_before_install_noqt; fi
- sudo apt-get install swig
# Simlinks for PIL compilation
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libfreetype.so /usr/lib/
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libjpeg.so /usr/lib/
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libpng.so /usr/lib/
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libz.so /usr/lib/
install:
# nose is already installed
- pip install cython
- pip install --upgrade numpy
- pip install -r dev_requirements.txt
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install -r requirements-2.6.txt; fi
- pip install coveralls
- python setup.py develop
script:
Expand Down
8 changes: 8 additions & 0 deletions .travis_before_install
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ python -c 'import PyQt4'
python -c 'import PyQt4.QtCore'
python -c 'import PyQt4.QtGui'

wget -nv http://cairographics.org/releases/py2cairo-1.10.0.tar.bz2
tar -xf py2cairo-1.10.0.tar.bz2
pushd py2cairo-1.10.0
./waf configure
./waf build
sudo ./waf install
popd

export ETS_TOOLKIT=qt4
2 changes: 1 addition & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Enhancements
------------

* Added a base class for drag and drop tools, example and test support.

* PR #160: Basic testing for kiva backends.


Enable 4.4.0 (May 1, 2014)
Expand Down
4 changes: 4 additions & 0 deletions dev_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
coverage
PIL
pyparsing
PyPDF2
pyglet
pygarrayimage
reportlab
-e git+http://github.com/enthought/traits.git#egg=traits
-e git+http://github.com/enthought/traitsui.git#egg=traitsui
-e git+http://github.com/nucleic/kiwi.git#egg=kiwisolver
8 changes: 6 additions & 2 deletions kiva/graphics_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,12 @@ def __init__(self):
line_cap = CAP_ROUND
line_join = JOIN_MITER
line_dash = (0, array([0])) # This will draw a solid line
self.line_state = LineState(line_color, line_width, line_cap,
line_join, line_dash)

# FIXME: This is a very wierd class. The following code is here to
# make the basecore2d and the PS, SVG context managers happy
super(GraphicsState, self).__init__(
line_color, line_width, line_cap, line_join, line_dash)
self.line_state = self

# All other default values.
self.ctm = affine.affine_identity()
Expand Down
5 changes: 5 additions & 0 deletions kiva/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,11 @@ def get_text_extent(self, textstring):
# Painting paths (drawing and filling contours)
# ----------------------------------------------------------------

def clear(self):
"""
"""
warnings.warn("clear() is ignored for the pdf backend")

def stroke_path(self):
"""
"""
Expand Down
2 changes: 1 addition & 1 deletion kiva/qpainter.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ def fill_path(self):
def eof_fill_path(self):
"""
"""
self.path.setFillRule(QtCore.Qt.OddEvenFill)
self.path.path.setFillRule(QtCore.Qt.OddEvenFill)
self.gc.fillPath(self.path.path, self.gc.brush())
self.begin_path()

Expand Down
Empty file added kiva/tests/__init__.py
Empty file.
179 changes: 179 additions & 0 deletions kiva/tests/drawing_tester.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import contextlib
import os
import shutil
import tempfile

import numpy
from PIL import Image

from kiva.fonttools import Font
from kiva.constants import MODERN


class DrawingTester(object):
""" Basic drawing tests for graphics contexts.
"""

def setUp(self):
self.directory = tempfile.mkdtemp()
self.filename = os.path.join(self.directory, 'rendered')
self.gc = self.create_graphics_context(300, 300)
self.gc.clear()
self.gc.set_stroke_color((1.0, 0.0, 0.0))
self.gc.set_fill_color((1.0, 0.0, 0.0))
self.gc.set_line_width(5)

def tearDown(self):
del self.gc
shutil.rmtree(self.directory)

def test_line(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.move_to(107, 204)
self.gc.line_to(107, 104)
self.gc.stroke_path()

def test_rectangle(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.move_to(107, 104)
self.gc.line_to(107, 184)
self.gc.line_to(187, 184)
self.gc.line_to(187, 104)
self.gc.line_to(107, 104)
self.gc.stroke_path()

def test_rect(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.rect(0, 0, 200, 200)
self.gc.stroke_path()

def test_circle(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.arc(150, 150, 100, 0.0, 2 * numpy.pi)
self.gc.stroke_path()

def test_quarter_circle(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.arc(150, 150, 100, 0.0, numpy.pi / 2)
self.gc.stroke_path()

def test_text(self):
with self.draw_and_check():
font = Font(family=MODERN)
font.size = 24
self.gc.set_font(font)
self.gc.set_text_position(23, 67)
self.gc.show_text("hello kiva")

def test_circle_fill(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.arc(150, 150, 100, 0.0, 2 * numpy.pi)
self.gc.fill_path()

def test_star_fill(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.move_to(100, 100)
self.gc.line_to(150, 200)
self.gc.line_to(200, 100)
self.gc.line_to(100, 150)
self.gc.line_to(200, 150)
self.gc.line_to(100, 100)
self.gc.fill_path()

def test_star_eof_fill(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.move_to(100, 100)
self.gc.line_to(150, 200)
self.gc.line_to(200, 100)
self.gc.line_to(100, 150)
self.gc.line_to(200, 150)
self.gc.line_to(100, 100)
self.gc.eof_fill_path()

def test_circle_clip(self):
with self.draw_and_check():
self.gc.clip_to_rect(150, 150, 100, 100)
self.gc.begin_path()
self.gc.arc(150, 150, 100, 0.0, 2 * numpy.pi)
self.gc.fill_path()

def test_text_clip(self):
with self.draw_and_check():
self.gc.clip_to_rect(23, 77, 100, 23)
font = Font(family=MODERN)
font.size = 24
self.gc.set_font(font)
self.gc.set_text_position(23, 67)
self.gc.show_text("hello kiva")

def test_star_clip(self):
with self.draw_and_check():
self.gc.begin_path()
self.gc.move_to(100, 100)
self.gc.line_to(150, 200)
self.gc.line_to(200, 100)
self.gc.line_to(100, 150)
self.gc.line_to(200, 150)
self.gc.line_to(100, 100)
self.gc.close_path()
self.gc.clip()

self.gc.begin_path()
self.gc.arc(150, 150, 100, 0.0, 2 * numpy.pi)
self.gc.fill_path()

#### Required methods ####################################################

@contextlib.contextmanager
def draw_and_check(self):
""" A context manager to check the result.
"""
raise NotImplementedError()

def create_graphics_context(self, width, length):
""" Create the desired graphics context
"""
raise NotImplementedError()


class DrawingImageTester(DrawingTester):
""" Basic drawing tests for graphics contexts of gui toolkits.
"""

@contextlib.contextmanager
def draw_and_check(self):
yield
filename = "{0}.png".format(self.filename)
self.gc.save(filename)
self.assertImageSavedWithContent(filename)

def assertImageSavedWithContent(self, filename):
""" Load the image and check that there is some content in it.
"""
image = numpy.array(Image.open(filename))
# default is expected to be a totally white image

self.assertEqual(image.shape[:2], (300, 300))
if image.shape[2] == 3:
check = numpy.sum(image == [255, 0, 0], axis=2) == 3
elif image.shape[2] == 4:
check = numpy.sum(image == [255, 0, 0, 255], axis=2) == 4
else:
self.fail(
'Pixel size is not 3 or 4, but {0}'.format(image.shape[2]))
if check.any():
return
self.fail('The image looks empty, no red pixels where drawn')
13 changes: 13 additions & 0 deletions kiva/tests/test_agg_drawing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from kiva.tests.drawing_tester import DrawingImageTester
from kiva.image import GraphicsContext
from traits.testing.unittest_tools import unittest


class TestAggDrawing(DrawingImageTester, unittest.TestCase):

def create_graphics_context(self, width, height):
return GraphicsContext((width, height))


if __name__ == "__main__":
unittest.main()
21 changes: 21 additions & 0 deletions kiva/tests/test_cairo_drawing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from kiva.tests.drawing_tester import DrawingImageTester
from traits.testing.unittest_tools import unittest

try:
import cairo # noqa
except ImportError:
CAIRO_NOT_AVAILABLE = True
else:
CAIRO_NOT_AVAILABLE = False


@unittest.skipIf(CAIRO_NOT_AVAILABLE, "Cannot import cairo")
class TestCairoDrawing(DrawingImageTester, unittest.TestCase):

def create_graphics_context(self, width, height):
from kiva.cairo import GraphicsContext
return GraphicsContext((width, height))


if __name__ == "__main__":
unittest.main()
57 changes: 57 additions & 0 deletions kiva/tests/test_gl_drawing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import contextlib

try:
import pyglet
except ImportError:
PYGLET_NOT_AVAILABLE = True
else:
PYGLET_NOT_AVAILABLE = False


from kiva.tests.drawing_tester import DrawingImageTester
from traits.testing.unittest_tools import unittest


@unittest.skipIf(PYGLET_NOT_AVAILABLE, "Cannot import pyglet")
class TestGLDrawing(DrawingImageTester, unittest.TestCase):

def tearDown(self):
if hasattr(self, 'window') and self.window is not None:
self.window.close()
del self.window
DrawingImageTester.tearDown(self)

def create_graphics_context(self, width, height):
from kiva.gl import GraphicsContext
self.window = pyglet.window.Window(width=width, height=height)
gc = GraphicsContext((width, height))
gc.gl_init()
return gc

@unittest.skip("gl graphics context does not support star_clip (#164)")
def test_star_clip(self):
# FIXME: overriding test since it segfaults
DrawingImageTester.test_star_clip(self)

@unittest.expectedFailure
def test_text_clip(self):
# gl graphics context does not clip text properly (#165).
DrawingImageTester.test_text_clip(self)

@contextlib.contextmanager
def draw_and_check(self):
from pyglet.image.codecs.png import PNGImageEncoder

self.window.clear()
self.window.switch_to()
self.window.dispatch_events()
yield
self.window.dispatch_events()
filename = "{0}.png".format(self.filename)
buffer = pyglet.image.get_buffer_manager()
buffer.get_color_buffer().save(filename, encoder=PNGImageEncoder())
self.assertImageSavedWithContent(filename)


if __name__ == "__main__":
unittest.main()

0 comments on commit 71f7aa1

Please sign in to comment.