# coding=utf-8 # # Copyright 2022 Martin Owens # # This program 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. # # This program 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 this program. If not, see # """ Test pixmap and image handling from various sources. """ import os import sys import time import pytest from inkex.tester import TestCase from inkex.utils import DependencyError try: from inkex.gui.tester import MainLoopProtection from inkex.gui.pixmap import ( PixmapLoadError, PixmapFilter, OverlayFilter, PadFilter, SizeFilter, SIZE_ASPECT, SIZE_ASPECT_GROW, SIZE_ASPECT_CROP, SIZE_STRETCH, ) from inkex.gui import PixmapManager except DependencyError: PixmapFilter = object PixmapManager = None class NullFilter(PixmapFilter): required = ["underpants"] @pytest.mark.skipif(PixmapManager is None, reason="PyGObject is required") class GtkPixmapsTest(TestCase): """Tests all the pixmaps functionality""" def construct_manager(self, **kwargs): """Create a gtk app based on some inputs""" return type( "_PixMan", (PixmapManager,), { "pixmap_dir": self.datadir(), "missing_image": kwargs.pop("missing_image", None), "default_image": kwargs.pop("default_image", None), **kwargs, }, ) def test_filter(self): """Test building filters and errors""" null_filter = NullFilter(underpants=True) self.assertRaises(NotImplementedError, null_filter.filter, "not") self.assertRaises(ValueError, OverlayFilter().filter, None) def test_manager_filter_overlay(self): """Test overlay filter in use""" pixmaps = self.construct_manager(filters=[OverlayFilter])("svg") self.assertTrue(pixmaps.get("colors.svg", overlay="application-default-icon")) def test_manger_filter_size(self): """Test resizing a file pixmap""" pixmaps = self.construct_manager(filters=[SizeFilter])("svg", size=150) ret = pixmaps.get("colors.svg") self.assertEqual(ret.get_width(), 150) self.assertEqual(ret.get_height(), 50) self.assertRaises(PixmapLoadError, pixmaps.load_from_name, "no-file.svg") self.assertRaises( PixmapLoadError, pixmaps.load_from_name, os.path.join(self.datadir(), "ui", "window-test.ui"), ) def test_missing_image(self): pixmaps = PixmapManager("svg", filters=[SizeFilter(size=25)]) img_a = pixmaps.get("NeverExisted.svg") img_b = pixmaps.get(PixmapManager.missing_image) self.assertEqual(img_a.get_width(), 25) self.assertPixbuf(img_a, img_b) def test_overlay_filter(self): """Test overlay filter""" pixmaps = self.construct_manager()("svg") start = pixmaps.get("gradient_with_mixed_offsets.svg") # 1. Simple overlay ret = OverlayFilter().filter(start, manager=pixmaps, overlay="colors.svg") comp = pixmaps.get("img/color_overlay_a.png") self.assertPixbuf(ret, comp) # 2. Overlay at bottom ret = OverlayFilter(position=1).filter( start, manager=pixmaps, overlay="colors.svg" ) comp = pixmaps.get("img/color_overlay_b.png") self.assertPixbuf(ret, comp) def test_pad_filter(self): """Test padding filter""" pixmaps = self.construct_manager()("svg") start = pixmaps.get("colors.svg") # 1. Add no padding ret = PadFilter(size=(300, 100)).filter(start) self.assertPixbuf(ret, start) # 2a. Add padding at top-left ret = PadFilter(size=300, padding=0.0).filter(start) comp = pixmaps.get("img/color_pad_a.png") self.assertPixbuf(ret, comp) # 12b. Add padding at top-left ret = PadFilter(size=300, padding=1.0).filter(start) comp = pixmaps.get("img/color_pad_b.png") self.assertPixbuf(ret, comp) # 12c. Add padding at top-left ret = PadFilter(size=300, padding=0.5).filter(start) comp = pixmaps.get("img/color_pad_c.png") self.assertPixbuf(ret, comp) # 3. Take image and pad to 1px x 150px ret = PadFilter(size=(1, 150)).filter(start) self.assertEqual((ret.get_width(), ret.get_height()), (300, 150)) def test_size_filter(self): """Test the size pixbuf filter""" pixmaps = self.construct_manager()("svg") start = pixmaps.get("colors.svg") self.assertEqual((start.get_width(), start.get_height()), (300, 100)) ret = SizeFilter().filter(start) self.assertEqual((ret.get_width(), ret.get_height()), (300, 100)) ret = SizeFilter(size=600, resize_mode=SIZE_ASPECT).filter(start) self.assertEqual((ret.get_width(), ret.get_height()), (300, 100)) self.assertEqual((start.get_width(), start.get_height()), (300, 100)) ret = SizeFilter(size=60, resize_mode=SIZE_ASPECT).filter(start) self.assertEqual((ret.get_width(), ret.get_height()), (60, 20)) self.assertEqual((start.get_width(), start.get_height()), (300, 100)) ret = SizeFilter(size=600, resize_mode=SIZE_ASPECT_GROW).filter(start) self.assertEqual((ret.get_width(), ret.get_height()), (600, 200)) self.assertEqual((start.get_width(), start.get_height()), (300, 100)) ret = SizeFilter(size=60, resize_mode=SIZE_ASPECT_CROP).filter(start) self.assertEqual((ret.get_width(), ret.get_height()), (180, 60)) self.assertEqual((start.get_width(), start.get_height()), (300, 100)) ret = SizeFilter(size=600, resize_mode=SIZE_STRETCH).filter(start) self.assertEqual((ret.get_width(), ret.get_height()), (600, 600)) self.assertEqual((start.get_width(), start.get_height()), (300, 100)) def test_load_file(self): """Test loading a filename""" pixmaps = self.construct_manager()("svg") self.assertTrue(pixmaps.get("colors.svg")) self.assertFalse(pixmaps.get("colors-no-file.svg")) def test_load_name(self): """Test loading from a Gtk named theme icon""" pixmaps = self.construct_manager()() self.assertTrue(pixmaps.get("image-missing")) def test_load_data_svg(self): """Test loading a data svg""" pixmaps = self.construct_manager()(size=None, load_size=(128, 128)) with open(os.path.join(self.datadir(), "svg", "colors.svg"), "r") as fhl: self.assertTrue(pixmaps.get(fhl.read())) self.assertRaises(PixmapLoadError, pixmaps.load_from_data, " {pcent}%" )