diff options
| author | Michael Soegtrop <MSoegtrop@yahoo.de> | 2017-06-05 13:13:40 +0000 |
|---|---|---|
| committer | Michael Soegtrop <MSoegtrop@yahoo.de> | 2017-06-05 13:13:40 +0000 |
| commit | ab8fc319f2c80aeea54eaab63ceec042a763fc94 (patch) | |
| tree | 8eb2f8d265d3cdb61e81331833ec404f751571d0 /share | |
| parent | Added emboidery and bool LPEs (diff) | |
| parent | Fix regression: restore order in resources (e.g. pattern list) (diff) | |
| download | inkscape-ab8fc319f2c80aeea54eaab63ceec042a763fc94.tar.gz inkscape-ab8fc319f2c80aeea54eaab63ceec042a763fc94.zip | |
updated to trunk
(bzr r14862.2.2)
Diffstat (limited to 'share')
| -rw-r--r-- | share/extensions/CMakeLists.txt | 12 | ||||
| -rw-r--r-- | share/extensions/color_randomize.inx | 7 | ||||
| -rwxr-xr-x[-rw-r--r--] | share/extensions/color_randomize.py | 105 | ||||
| -rwxr-xr-x | share/extensions/coloreffect.py | 34 | ||||
| -rwxr-xr-x | share/extensions/plotter.py | 10 | ||||
| -rw-r--r-- | share/extensions/test/Makefile.am | 1 | ||||
| -rwxr-xr-x | share/extensions/test/color_randomize.test.py | 123 | ||||
| -rwxr-xr-x | share/extensions/test/run-all-extension-tests | 20 | ||||
| -rw-r--r-- | share/ui/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | share/ui/Makefile.am | 1 | ||||
| -rw-r--r-- | share/ui/style.css | 98 |
11 files changed, 335 insertions, 78 deletions
diff --git a/share/extensions/CMakeLists.txt b/share/extensions/CMakeLists.txt index c167a156a..74819309d 100644 --- a/share/extensions/CMakeLists.txt +++ b/share/extensions/CMakeLists.txt @@ -1,3 +1,4 @@ +# Install the set of non-executable data files file(GLOB _FILES "README" "fontfix.conf" @@ -13,13 +14,20 @@ file(GLOB _FILES "svg2xaml.xsl" "xaml2svg.xsl" "inkscape.extension.rng" + "*.inx" + ) + +install(FILES ${_FILES} DESTINATION ${SHARE_INSTALL}/inkscape/extensions) + +# Install the executable scripts +file(GLOB _SCRIPTS "*.py" "*.pl" "*.sh" "*.rb" - "*.inx" ) -install(FILES ${_FILES} DESTINATION ${SHARE_INSTALL}/inkscape/extensions) + +install(PROGRAMS ${_SCRIPTS} DESTINATION ${SHARE_INSTALL}/inkscape/extensions) file(GLOB _FILES "alphabet_soup/*.svg") install(FILES ${_FILES} DESTINATION ${SHARE_INSTALL}/inkscape/extensions/alphabet_soup) diff --git a/share/extensions/color_randomize.inx b/share/extensions/color_randomize.inx index 0c84227ae..c0c0d9ea2 100644 --- a/share/extensions/color_randomize.inx +++ b/share/extensions/color_randomize.inx @@ -7,16 +7,13 @@ <dependency type="executable" location="extensions">simplestyle.py</dependency> <param name="tab" type="notebook"> <page name="Options" _gui-text="Options"> - <param name="hue" type="boolean" _gui-text="Hue">true</param> <param name="hue_range" type="int" appearance="full" min="0" max="100" indent="0" _gui-text="Hue range (%)">100</param> - <param name="saturation" type="boolean" _gui-text="Saturation">true</param> <param name="saturation_range" type="int" appearance="full" min="0" max="100" indent="0" _gui-text="Saturation range (%)">100</param> - <param name="lightness" type="boolean" _gui-text="Lightness">true</param> <param name="lightness_range" type="int" appearance="full" min="0" max="100" indent="0" _gui-text="Lightness range (%)">100</param> - + <param name="opacity_range" type="int" appearance="full" min="0" max="100" indent="0" _gui-text="Opacity range (%)">0</param> </page> <page name="Help" _gui-text="Help"> - <_param name="instructions" type="description" xml:space="preserve">Converts to HSL, randomizes hue and/or saturation and/or lightness and converts it back to RGB. Lower the range values to limit the distance between the original color and the randomized one.</_param> + <_param name="instructions" type="description" xml:space="preserve">Randomizes hue, saturation, lightness and/or opacity (opacity randomization only for objects and groups). Change the range values to limit the distance between the original color and the randomized one.</_param> </page> </param> <effect> diff --git a/share/extensions/color_randomize.py b/share/extensions/color_randomize.py index b8f52cb6b..93abcf174 100644..100755 --- a/share/extensions/color_randomize.py +++ b/share/extensions/color_randomize.py @@ -1,85 +1,84 @@ #!/usr/bin/env python -import coloreffect,random,inkex + +import random + +import coloreffect +import inkex class C(coloreffect.ColorEffect): def __init__(self): coloreffect.ColorEffect.__init__(self) - self.OptionParser.add_option("-x", "--hue", - action="store", type="inkbool", - dest="hue", default=True, - help="Randomize hue") self.OptionParser.add_option("-y", "--hue_range", action="store", type="int", dest="hue_range", default=0, help="Hue range") - self.OptionParser.add_option("-s", "--saturation", - action="store", type="inkbool", - dest="saturation", default=True, - help="Randomize saturation") self.OptionParser.add_option("-t", "--saturation_range", action="store", type="int", dest="saturation_range", default=0, help="Saturation range") - self.OptionParser.add_option("-l", "--lightness", - action="store", type="inkbool", - dest="lightness", default=True, - help="Randomize lightness") self.OptionParser.add_option("-m", "--lightness_range", action="store", type="int", dest="lightness_range", default=0, help="Lightness range") + self.OptionParser.add_option("-o", "--opacity_range", + action="store", type="int", + dest="opacity_range", default=0, + help="Opacity range") self.OptionParser.add_option("--tab", action="store", type="string", dest="tab", help="The selected UI-tab when OK was pressed") + def randomize_hsl(self, limit, current_value): + limit = 255.0 * limit / 100.0 + limit /= 2 + max = int((current_value * 255.0) + limit) + min = int((current_value * 255.0) - limit) + if max > 255: + min = min - (max - 255) + max = 255 + if min < 0: + max = max - min + min = 0 + return random.randrange(min, max) / 255.0 + def colmod(self,r,g,b): hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) - - if(self.options.hue): - limit = 255.0 * (1 + self.options.hue_range) / 100.0 - limit /= 2 - max = int((hsl[0] * 255.0) + limit) - min = int((hsl[0] * 255.0) - limit) - if max > 255: - min = min - (max - 255) - max = 255 - if min < 0: - max = max - min - min = 0 - hsl[0] = random.randrange(min, max) - hsl[0] /= 255.0 - if(self.options.saturation): - limit = 255.0 * (1 + self.options.saturation_range) / 100.0 - limit /= 2 - max = int((hsl[1] * 255.0) + limit) - min = int((hsl[1] * 255.0) - limit) - if max > 255: - min = min - (max - 255) - max = 255 - if min < 0: - max = max - min - min = 0 - hsl[1] = random.randrange(min, max) - hsl[1] /= 255.0 - if(self.options.lightness): - limit = 255.0 * (1 + self.options.lightness_range) / 100.0 + if self.options.hue_range > 0: + hsl[0] = self.randomize_hsl(self.options.hue_range, hsl[0]) + if self.options.saturation_range > 0: + hsl[1] = self.randomize_hsl(self.options.saturation_range, hsl[1]) + if self.options.lightness_range > 0: + hsl[2] = self.randomize_hsl(self.options.lightness_range, hsl[2]) + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + + def opacmod(self, opacity): + if self.options.opacity_range > 0: + # maybe not necessary, but better not change things that shouldn't change + try: + opacity = float(opacity) + except ValueError: + return opacity + + limit = self.options.opacity_range limit /= 2 - max = int((hsl[2] * 255.0) + limit) - min = int((hsl[2] * 255.0) - limit) - if max > 255: - min = min - (max - 255) - max = 255 + max = opacity*100 + limit + min = opacity*100 - limit + if max > 100: + min = min - (max - 100) + max = 100 if min < 0: max = max - min min = 0 - hsl[2] = random.randrange(min, max) - hsl[2] /= 255.0 - rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) - return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + ret = str(random.uniform(min,max)/100) + return ret + return opacity + -c = C() -c.affect() +if __name__ == '__main__': + c = C() + c.affect() # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 diff --git a/share/extensions/coloreffect.py b/share/extensions/coloreffect.py index a6b5cfe41..d33ac41fe 100755 --- a/share/extensions/coloreffect.py +++ b/share/extensions/coloreffect.py @@ -21,8 +21,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import sys, copy, simplestyle, inkex import random -color_props_fill = ('fill', 'stop-color', 'flood-color', 'lighting-color') +color_props_fill = ('fill', 'stop-color', 'flood-color', 'lighting-color') color_props_stroke = ('stroke',) +opacity_props = ('opacity',) #'stop-opacity', 'fill-opacity', 'stroke-opacity' don't work with clones color_props = color_props_fill + color_props_stroke @@ -63,13 +64,14 @@ class ColorEffect(inkex.Effect): # # The processing here is just something simple that should usually work, # without trying too hard to get everything right. - # (Won't work for the pathalogical case that someone escapes a property + # (Won't work for the pathological case that someone escapes a property # name, probably does the wrong thing if colon or semicolon is used inside # a comment or string value.) style = node.get('style') # fixme: this will break for presentation attributes! if style: #inkex.debug('old style:'+style) declarations = style.split(';') + opacity_in_style = False for i,decl in enumerate(declarations): parts = decl.split(':', 2) if len(parts) == 2: @@ -80,16 +82,25 @@ class ColorEffect(inkex.Effect): new_val = self.process_prop(val) if new_val != val: declarations[i] = prop + ':' + new_val + elif prop in opacity_props: + opacity_in_style = True + val = val.strip() + new_val = self.process_prop(val) + if new_val != val: + declarations[i] = prop + ':' + new_val + if not opacity_in_style: + new_val = self.process_prop("1") + declarations.append('opacity' + ':' + new_val) #inkex.debug('new style:'+';'.join(declarations)) node.set('style', ';'.join(declarations)) - def process_prop(self,col): - #debug('got:'+col) + def process_prop(self, col): + #inkex.debug('got:'+col+str(type(col))) if simplestyle.isColor(col): c=simplestyle.parseColor(col) - col='#'+self.colmod(c[0],c[1],c[2]) - #debug('made:'+col) - if col.startswith('url(#'): + col='#'+self.colmod(c[0], c[1], c[2]) + #inkex.debug('made:'+col) + elif col.startswith('url(#'): id = col[len('url(#'):col.find(')')] newid = '%s-%d' % (id, int(random.random() * 1000)) #inkex.debug('ID:' + id ) @@ -97,6 +108,11 @@ class ColorEffect(inkex.Effect): for node in self.document.xpath(path, namespaces=inkex.NSS): self.process_gradient(node, newid) col = 'url(#%s)' % newid + # what remains should be opacity + else: + col = self.opacmod(col) + + #inkex.debug('col:'+str(col)) return col def process_gradient(self, node, newid): @@ -128,6 +144,9 @@ class ColorEffect(inkex.Effect): def colmod(self,r,g,b): pass + + def opacmod(self, opacity): + return opacity def rgb_to_hsl(self,r, g, b): rgb_max = max (max (r, g), b) @@ -188,4 +207,5 @@ class ColorEffect(inkex.Effect): rgb[2] = self.hue_2_rgb (v1, v2, h*6 - 2.0) return rgb + # vi: set autoindent shiftwidth=2 tabstop=8 expandtab softtabstop=2 : diff --git a/share/extensions/plotter.py b/share/extensions/plotter.py index 60858cc6c..1c4a683c1 100755 --- a/share/extensions/plotter.py +++ b/share/extensions/plotter.py @@ -144,10 +144,12 @@ class Plot(inkex.Effect): try: import serial except ImportError, e: - inkex.errormsg(_("pySerial is not installed." - + "\n\n1. Download pySerial here (not the \".exe\"!): http://pypi.python.org/pypi/pyserial" - + "\n2. Extract the \"serial\" subfolder from the zip to the following folder: C:\\[Program files]\\inkscape\\python\\Lib\\" - + "\n3. Restart Inkscape.")) + inkex.errormsg(_("pySerial is not installed. Please follow these steps:") + + "\n\n" + _("1. Download and extract (unzip) this file to your local harddisk:") + + "\n" + " https://pypi.python.org/packages/source/p/pyserial/pyserial-2.7.tar.gz" + + "\n" + _("2. Copy the \"serial\" folder (Can be found inside the just extracted folder)") + + "\n" + _(" into the following Inkscape folder: C:\\<Program files>\\inkscape\\python\\Lib\\") + + "\n" + _("3. Close and restart Inkscape.")) return # init serial framework mySerial = serial.Serial() diff --git a/share/extensions/test/Makefile.am b/share/extensions/test/Makefile.am index 7ff68083d..cd1929a7f 100644 --- a/share/extensions/test/Makefile.am +++ b/share/extensions/test/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DIST = \ addnodes.test.py \ chardataeffect.test.py \ + color_randomize_test.py \ coloreffect.test.py \ create_test_from_template.sh \ dots.test.py \ diff --git a/share/extensions/test/color_randomize.test.py b/share/extensions/test/color_randomize.test.py new file mode 100755 index 000000000..d8549a35a --- /dev/null +++ b/share/extensions/test/color_randomize.test.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +''' +Unit test file for ../color_randomize.py +-- +If you want to help, read the python unittest documentation: +http://docs.python.org/library/unittest.html +''' + +import os +import sys +import unittest + +sys.path.append('..') # this line allows to import the extension code +from color_randomize import * + +def extract_hsl(e,rgb): + r = int(rgb[:2], 16) + g = int(rgb[2:4], 16) + b = int(rgb[4:6], 16) + return e.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + + +class ColorRandomizeBasicTest(unittest.TestCase): + def setUp(self): + self.e=C() + + def test_default_values(self): + """ The default ranges are set to 0, and thus the color and opacity should not change. """ + args = ['svg/empty-SVG.svg'] + self.e.affect(args, False) + col = self.e.colmod(128, 128, 255) + self.assertEqual("8080ff", col) + opac = self.e.opacmod(5) + self.assertEqual(5, opac) + + +class ColorRandomizeColorModificationTest(unittest.TestCase): + def setUp(self): + self.e=C() + + def test_no_change(self): + """ The user selected 0% values, and thus the color should not change. """ + args = ['-y 0', '-t 0', '-m 0', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + col = self.e.colmod(128, 128, 255) + self.assertEqual("8080ff", col) + + def test_random_hue(self): + """ Random hue only. Saturation and lightness not changed. """ + args = ['-y 50','-t 0','-m 0','svg/empty-SVG.svg'] + self.e.affect(args, False) + hsl = extract_hsl(self.e, self.e.colmod(150, 100, 200)) + self.assertEqual([0.47, 0.59], [round(hsl[1], 2), round(hsl[2], 2)]) + + @unittest.skip("Inaccurate convertion") + def test_random_lightness(self): + """ Random lightness only. Hue and saturation not changed. """ + args = ['-y 0', '-t 0', '-m 50', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + hsl = extract_hsl(self.e, self.e.colmod(150, 100, 200)) + # Lightness change also affects hue and saturation... + #self.assertEqual(0.75, round(hsl[0], 2)) + #self.assertEqual(0.48, round(hsl[1], 2)) + + def test_random_saturation(self): + """ Random saturation only. Hue and lightness not changed. """ + args = ['-y 0', '-t 50', '-m 0', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + hsl = extract_hsl(self.e, self.e.colmod(150, 100, 200)) + self.assertEqual([0.75, 0.59], [round(hsl[0], 2), round(hsl[2], 2)]) + + def test_range_limits(self): + """ The maximum hsl values should be between 0 and 100% of their maximum """ + args = ['-y 100', '-t 100', '-m 100', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + hsl = extract_hsl(self.e, self.e.colmod(156, 156, 156)) + self.assertLessEqual([hsl[0], hsl[1], hsl[2]], [1, 1, 1]) + self.assertGreaterEqual([hsl[0], hsl[1], hsl[2]], [0, 0, 0]) + + +class ColorRandomizeOpacityModificationTest(unittest.TestCase): + def setUp(self): + self.e=C() + + def test_no_change(self): + """ The user selected 0% opacity range, and thus the opacity should not change. """ + args = ['-o 0', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + opac = self.e.opacmod(0.15) + self.assertEqual(0.15, opac) + + def test_range_min_limit(self): + """ The opacity value should be greater than 0 """ + args = ['-o 100', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + opac = self.e.opacmod(0) + self.assertGreaterEqual(opac, "0") + + def test_range_max_limit(self): + """ The opacity value should be lesser than 1 """ + args = ['-o 100', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + opac = self.e.opacmod(1) + self.assertLessEqual(opac, "1") + + def test_non_float_opacity(self): + """ Non-float opacity value not changed """ + args = ['-o 100', 'svg/empty-SVG.svg'] + self.e.affect(args, False) + opac = self.e.opacmod("toto") + self.assertLessEqual(opac, "toto") + +if __name__ == '__main__': + #unittest.main() + suite = unittest.TestLoader().loadTestsFromTestCase(ColorRandomizeBasicTest) + unittest.TextTestRunner(verbosity=2).run(suite) + suite = unittest.TestLoader().loadTestsFromTestCase(ColorRandomizeColorModificationTest) + unittest.TextTestRunner(verbosity=2).run(suite) + suite = unittest.TestLoader().loadTestsFromTestCase(ColorRandomizeOpacityModificationTest) + unittest.TextTestRunner(verbosity=2).run(suite) + + +# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 diff --git a/share/extensions/test/run-all-extension-tests b/share/extensions/test/run-all-extension-tests index aa20c8c7b..e7faf672a 100755 --- a/share/extensions/test/run-all-extension-tests +++ b/share/extensions/test/run-all-extension-tests @@ -35,24 +35,32 @@ has_py_coverage=false py_cover_files=$( $MKTEMP ) failed_tests=$( $MKTEMP ) -if coverage.py -e >/dev/null 2>/dev/null; then +if coverage.py erase >/dev/null 2>/dev/null; then has_py_coverage=true cover_py_cmd=coverage.py else - if coverage -e >/dev/null 2>/dev/null; then + if coverage erase >/dev/null 2>/dev/null; then has_py_coverage=true cover_py_cmd=coverage + else + if python-coverage erase >/dev/null 2>/dev/null; then + has_py_coverage=true + cover_py_cmd=python-coverage + fi fi fi +if $has_py_coverage; then + echo -e "\nRunning tests with coverage" +fi #if $has_py_coverage; then # $cover_py_cmd -e #fi function run_py_test() { - echo -e "\n>> Testing $1" + echo -e "\n>>>>>> Testing $1 <<<<<<\n" if $has_py_coverage; then - if ! $cover_py_cmd -x "$1.test.py"; then + if ! $cover_py_cmd run -a "$1.test.py"; then echo "$1" >> $failed_tests fi echo "../$1.py" >> $py_cover_files @@ -77,7 +85,7 @@ else SED_EXTENDED='sed -E' # BSD sed (e.g. on Mac OS X) fi -echo "sed regex command: $SED_EXTENDED" +echo -e "sed regex command: $SED_EXTENDED\n" # --------------------------------------------------------------------- @@ -89,7 +97,7 @@ done if $has_py_coverage; then echo -e "\n>> Coverage Report:" - cat $py_cover_files | xargs $cover_py_cmd -r + cat $py_cover_files | xargs $cover_py_cmd report fi fail=false diff --git a/share/ui/CMakeLists.txt b/share/ui/CMakeLists.txt index 89b9f9b0f..5e9db74cf 100644 --- a/share/ui/CMakeLists.txt +++ b/share/ui/CMakeLists.txt @@ -1,3 +1,3 @@ -file(GLOB _FILES "*.xml" "*.rc") +file(GLOB _FILES "*.xml" "*.rc" "*.css") install(FILES ${_FILES} DESTINATION ${SHARE_INSTALL}/inkscape/ui) diff --git a/share/ui/Makefile.am b/share/ui/Makefile.am index 7195af0cb..1e55ea58f 100644 --- a/share/ui/Makefile.am +++ b/share/ui/Makefile.am @@ -4,6 +4,7 @@ uidir = $(datadir)/inkscape/ui ui_DATA = \ keybindings.rc \ menus-bars.xml \ + style.css \ toolbox.xml \ units.xml diff --git a/share/ui/style.css b/share/ui/style.css new file mode 100644 index 000000000..6729344d2 --- /dev/null +++ b/share/ui/style.css @@ -0,0 +1,98 @@ + +/* GTK3 WIDGET STYLING */ + +/* + * Keep in order of: + * General -> Specific + * Order of appearance in widget tree. + * See GtkInspector + * GTK_DEBUG=interactive ~/path_to_gtk3/bin/inkscape + * + * We need a standardized naming scheme. + * + * As of Gtk 3.20, you cannot use widget names. + */ + +/* Standard theme based colors. Prefer these. + * + * @theme_bg_color + * @theme_fg_color + * @theme_base_color + * @theme_text_color + * @theme_selected_bg_color + * @theme_selected_fg_color + * @theme_tooltip_bg_color + * @theme_tooltip_fg_color + * + */ + + +/* Our own custom shades... better not to use. + * Lightest to darkest based on linear rgb. + */ +@define-color bg_color0 #ffffff; /* White */ +@define-color bg_color05 #f8f8f8; /* Slightly off white */ +@define-color bg_color1 #f0f0f0; +@define-color bg_color2 #e0e0e0; +@define-color bg_color3 #d0d0d0; +@define-color bg_color4 #bbbbbb; /* 50% Gray */ +@define-color bg_color5 #a5a5a5; +@define-color bg_color6 #898989; +@define-color bg_color7 #636363; +@define-color bg_color8 #000000; /* Black */ + +/* 'GtkWidget' for Gtk <= 3.18 */ +/* 'widget' for Gtk <= 3.19.2 */ +GtkWidget, widget { +/* font-size: 12pt; */ +} + +GtkSpinButton { + padding: 0; +} + +spinbutton { + padding: 0; +} + +GtkSpinButton.entry { + padding-left: 2px; +} + +spinbutton.entry { + padding-left: 2px; +} + +SPRuler { + background-color: @theme_bg_color; + color: @theme_fg_color; +} + +ruler-widget { + background-color: @theme_bg_color; + color: @theme_fg_color; +} + +/* The actual canvas (Inkscape's drawing area). */ +SPCanvas { + background-color: white; +} + +combobox window.popup scrolledwindow treeview separator { + -GtkWidget-wide-separators: true; + -GtkWidget-separator-height: 6; +} + +#font_selector_family { + -GtkWidget-wide-separators: true; + -GtkWidget-separator-height: 6; +} + +#TextFontFamilyAction_combobox { + -GtkComboBox-appears-as-list: true; +} + +#LockGuides { + padding: 0; +} + |
