Merge lp:~valavanisalex/ubuntu/utopic/inkscape/fix-1358863 into lp:ubuntu/utopic/inkscape
- Utopic (14.10)
- fix-1358863
- Merge into utopic
Proposed by
Alex Valavanis
Status: | Merged | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 87 | ||||||||||||||||||||||||||||
Proposed branch: | lp:~valavanisalex/ubuntu/utopic/inkscape/fix-1358863 | ||||||||||||||||||||||||||||
Merge into: | lp:ubuntu/utopic/inkscape | ||||||||||||||||||||||||||||
Diff against target: |
83978 lines (+9530/-59871) 289 files modified
.pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.inx (+0/-20) .pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.py (+0/-654) .pc/0002-Drop_PS_and_PDF_support_in_MimeType.patch/inkscape.desktop.in (+0/-14) .pc/0003-Fix_LP_-911146.patch/src/extension/implementation/script.cpp (+0/-1034) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/connector-context.cpp (+0/-2041) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/extension/effect.cpp (+0/-409) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/gradient-drag.cpp (+0/-2216) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/libavoid/vpsc.cpp (+0/-1301) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/libcola/straightener.cpp (+0/-361) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/libcroco/cr-parser.c (+0/-4409) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/libvpsc/block.cpp (+0/-422) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/widgets/desktop-widget.h (+0/-268) .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/widgets/toolbox.cpp (+0/-8503) .pc/0005-Fix_FreeType_include.patch/src/libnrtype/FontFactory.h (+0/-163) .pc/0006-Fix_FTBFS_on_poppler-0.26.patch/configure.ac (+0/-1065) .pc/0006-Fix_FTBFS_on_poppler-0.26.patch/src/extension/internal/pdfinput/pdf-parser.cpp (+0/-3399) .pc/0006_add_unity_quicklist_support.patch/inkscape.desktop.in (+0/-14) .pc/applied-patches (+0/-8) .pc/librevenge.patch/configure.ac (+0/-1070) .pc/librevenge.patch/src/extension/internal/wpg-input.cpp (+0/-145) ChangeLog (+775/-10714) Info.plist (+3/-3) Info.plist.in (+1/-1) Makefile.in (+183/-167) NEWS (+9/-17) aclocal.m4 (+406/-348) build.xml (+1/-1) compile (+68/-31) config.guess (+106/-78) config.h.in (+3/-3) config.sub (+66/-48) configure (+520/-358) configure.ac (+28/-38) debian/changelog (+55/-0) debian/control (+3/-3) debian/patches/0004-Fix_FTBFS_on_gcc-4.8.patch (+10/-139) debian/patches/0005-Fix_FTBFS_due_to_tests.patch (+482/-0) debian/patches/0005-Fix_FreeType_include.patch (+0/-23) debian/patches/0006-Fix_FTBFS_on_poppler-0.26.patch (+0/-150) debian/patches/0006-Update_to_new_libwpg.patch (+111/-0) debian/patches/librevenge.patch (+0/-80) debian/patches/series (+2/-3) debian/rules (+2/-2) depcomp (+296/-193) doc/Makefile.in (+75/-37) inkscape.1 (+51/-42) inkscape.desktop.in (+1/-7) inkscape.el.1 (+74/-65) inkscape.fr.1 (+63/-54) inkscape.ja.1 (+33/-24) inkscape.sk.1 (+58/-49) inkscape.spec (+1/-1) inkscape.zh_TW.1 (+31/-22) install-sh (+7/-7) missing (+159/-275) mkinstalldirs (+2/-2) packaging/macosx/Resources/MenuBar.nib/classes.nib (+0/-4) packaging/macosx/Resources/MenuBar.nib/info.nib (+0/-23) packaging/macosx/Resources/MenuBar.nib/objects.xib (+0/-73) packaging/macosx/Resources/ProgressWindow.nib/classes.nib (+0/-4) packaging/macosx/Resources/ProgressWindow.nib/info.nib (+0/-18) packaging/macosx/Resources/ProgressWindow.nib/objects.xib (+0/-53) packaging/macosx/Resources/bin/getdisplay.sh (+0/-9) packaging/macosx/Resources/bin/inkscape (+0/-158) packaging/macosx/Resources/etc/fonts/fonts.conf (+0/-155) packaging/macosx/Resources/openDoc (+0/-17) packaging/macosx/Resources/script (+0/-54) packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/copy-slider.sh (+0/-7) packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/copy-slider.sh (+0/-7) packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/pre_gtkrc (+0/-547) packaging/macosx/ScriptExec/English.lproj/main.nib/classes.nib (+0/-4) packaging/macosx/ScriptExec/English.lproj/main.nib/info.nib (+0/-19) packaging/macosx/ScriptExec/English.lproj/main.nib/objects.xib (+0/-271) packaging/macosx/ScriptExec/Info.plist (+0/-39) packaging/macosx/ScriptExec/MenuBar.nib/classes.nib (+0/-4) packaging/macosx/ScriptExec/MenuBar.nib/info.nib (+0/-23) packaging/macosx/ScriptExec/MenuBar.nib/objects.xib (+0/-73) packaging/macosx/ScriptExec/ScriptExec.xcode/project.pbxproj (+0/-451) packaging/macosx/ScriptExec/ScriptExec.xcodeproj/project.pbxproj (+0/-351) packaging/macosx/ScriptExec/ScriptExec_Prefix.pch (+0/-5) packaging/macosx/ScriptExec/main.c (+0/-789) packaging/macosx/ScriptExec/openDoc (+0/-4) packaging/macosx/ScriptExec/script (+0/-4) packaging/macosx/ScriptExec/version.plist (+0/-16) packaging/macosx/osx-app.sh (+0/-499) packaging/macosx/osx-build.sh (+0/-410) packaging/macosx/osx-dmg.sh (+0/-178) packaging/win32/AdvUninstLog.nsh (+0/-437) packaging/win32/AdvUninstLog.txt (+0/-121) packaging/win32/MessageBox.txt (+0/-186) packaging/win32/RequireLatestNSIS.nsh (+0/-9) packaging/win32/VersionCompleteXXXX.nsh (+0/-47) packaging/win32/header.svg (+0/-516) packaging/win32/ifexist.nsh (+0/-21) packaging/win32/inkscape.nsi (+0/-1032) packaging/win32/inkscape.nsi.uninstall (+0/-20) packaging/win32/languages/Breton.nsh (+0/-113) packaging/win32/languages/Catalan.nsh (+0/-113) packaging/win32/languages/Czech.nsh (+0/-113) packaging/win32/languages/Dutch.nsh (+0/-113) packaging/win32/languages/English.nsh (+0/-113) packaging/win32/languages/Finnish.nsh (+0/-113) packaging/win32/languages/French.nsh (+0/-113) packaging/win32/languages/Galician.nsh (+0/-113) packaging/win32/languages/German.nsh (+0/-113) packaging/win32/languages/Indonesian.nsh (+0/-113) packaging/win32/languages/Italian.nsh (+0/-113) packaging/win32/languages/Japanese.nsh (+0/-113) packaging/win32/languages/Polish.nsh (+0/-113) packaging/win32/languages/Romanian.nsh (+0/-113) packaging/win32/languages/Russian.nsh (+0/-113) packaging/win32/languages/SimpChinese.nsh (+0/-113) packaging/win32/languages/Slovak.nsh (+0/-113) packaging/win32/languages/Slovenian.nsh (+0/-113) packaging/win32/languages/Spanish.nsh (+0/-113) packaging/win32/languages/TradChinese.nsh (+0/-113) packaging/win32/languages/Ukrainian.nsh (+0/-113) packaging/win32/md5dll.txt (+0/-68) packaging/win32/portable/App/AppInfo/appinfo.ini (+0/-26) packaging/win32/portable/App/AppInfo/installer.ini (+0/-15) packaging/win32/portable/App/readme.txt (+0/-1) packaging/win32/portable/Other/Source/InkscapePortable.ini (+0/-6) packaging/win32/portable/Other/Source/InkscapePortable.nsi (+0/-130) packaging/win32/portable/Other/Source/License.txt (+0/-344) packaging/win32/portable/Other/Source/PortableApps.comInstallerCustom.nsh (+0/-12) packaging/win32/portable/Other/Source/PortableApps.comLauncherLANG_ENGLISH.nsh (+0/-6) packaging/win32/portable/Other/Source/Readme.txt (+0/-67) packaging/win32/portable/Other/Source/ReplaceInFileWithTextReplace.nsh (+0/-64) packaging/win32/portable/help.html (+0/-178) packaging/win32/portable/readme.packaging.txt (+0/-29) packaging/win32/welcomefinish.svg (+0/-3510) po/fi.po (+1866/-2720) po/nl.po (+2/-2) share/Makefile.in (+145/-126) share/clipart/Makefile.am (+0/-1) share/clipart/Makefile.in (+75/-38) share/clipart/inkscape.logo.svg (+0/-9) share/examples/Makefile.in (+75/-37) share/examples/blend_modes.svg (+12/-12) share/examples/lighting_filters.svg (+12/-12) share/extensions/Barcode/Makefile.in (+75/-37) share/extensions/Makefile.in (+147/-128) share/extensions/Poly3DObjects/Makefile.in (+76/-39) share/extensions/alphabet_soup/Makefile.in (+76/-39) share/extensions/dxf_outlines.py (+6/-1) share/extensions/inkex.py (+8/-2) share/extensions/inkscape_help_reportabug.inx (+1/-1) share/extensions/printing-marks.inx (+5/-5) share/extensions/render_barcode_datamatrix.inx (+4/-34) share/extensions/render_barcode_datamatrix.py (+3/-46) share/extensions/scour.py (+6/-3) share/extensions/simplestyle.py (+1/-1) share/extensions/test/Makefile.in (+75/-37) share/extensions/text_braille.py (+1/-1) share/extensions/xaml2svg/Makefile.in (+76/-39) share/extensions/yocto_css.py (+6/-3) share/filters/Makefile.in (+76/-38) share/fonts/Makefile.in (+76/-38) share/gradients/Makefile.in (+76/-38) share/icons/Makefile.in (+146/-127) share/icons/application/16x16/Makefile.in (+76/-38) share/icons/application/22x22/Makefile.in (+76/-38) share/icons/application/24x24/Makefile.in (+76/-38) share/icons/application/256x256/Makefile.in (+76/-38) share/icons/application/32x32/Makefile.in (+76/-38) share/icons/application/48x48/Makefile.in (+76/-38) share/icons/application/Makefile.in (+147/-128) share/icons/inkscape.file.svg (+14/-16) share/icons/inkscape.svg (+14/-16) share/keys/Makefile.in (+76/-38) share/keys/right-handed-illustration.xml (+0/-1) share/keys/xara.xml (+0/-1) share/markers/Makefile.in (+76/-38) share/palettes/Makefile.in (+76/-38) share/palettes/Tango-Palette.gpl (+2/-0) share/patterns/Makefile.in (+76/-38) share/screens/Makefile.in (+76/-38) share/templates/Makefile.in (+75/-37) share/tutorials/Makefile.in (+75/-37) share/ui/Makefile.in (+76/-38) src/2geom/basic-intersection.cpp (+11/-1) src/2geom/interval.h (+1/-1) src/2geom/rect.h (+1/-1) src/2geom/sbasis.h (+24/-6) src/2geom/solve-bezier-parametric.cpp (+22/-5) src/Makefile.am (+1/-5) src/Makefile.in (+574/-817) src/box3d-context.cpp (+1/-1) src/color-profile.cpp (+8/-10) src/cxxtests.cpp (+62/-62) src/dialogs/export.cpp (+1/-1) src/dialogs/spellcheck.cpp (+1/-1) src/display/canvas-grid.cpp (+5/-0) src/display/nr-filter-gaussian.cpp (+2/-2) src/display/sodipodi-ctrl.cpp (+7/-2) src/display/sp-canvas.cpp (+9/-7) src/dom/io/uristream.cpp (+24/-25) src/dom/io/uristream.h (+38/-38) src/dom/svgimpl.cpp (+3/-3) src/dropper-context.cpp (+1/-1) src/extension/effect.cpp (+1/-1) src/extension/implementation/script.cpp (+1/-8) src/extension/init.cpp (+1/-1) src/extension/internal/cairo-renderer.cpp (+1/-1) src/extension/internal/filter/filter-file.cpp (+1/-1) src/extension/internal/filter/filter.cpp (+1/-1) src/extension/internal/pdfinput/svg-builder.cpp (+13/-13) src/extension/internal/wpg-input.cpp (+17/-10) src/extension/system.cpp (+2/-1) src/file.cpp (+1/-1) src/gc-core.h (+1/-1) src/gc.cpp (+13/-5) src/gradient-drag.cpp (+1/-1) src/helper/pixbuf-ops.cpp (+1/-1) src/helper/sp-marshal.cpp (+7/-7) src/helper/sp-marshal.h (+6/-6) src/inkscape-version.cpp (+1/-1) src/inkscape.rc (+5/-5) src/inkview.rc (+5/-5) src/interface.cpp (+11/-9) src/io/inkjar.cpp (+17/-9) src/io/inkjar.h (+4/-2) src/io/inkscapestream.h (+1/-0) src/io/uristream.cpp (+29/-31) src/io/uristream.h (+40/-40) src/io/xsltstream.cpp (+8/-11) src/io/xsltstream.h (+19/-21) src/libavoid/vpsc.cpp (+1/-1) src/libcola/straightener.cpp (+3/-3) src/libcroco/cr-parser.c (+1/-1) src/libcroco/cr-rgb.c (+2/-2) src/libgdl/gdl-dock-object.c (+1/-1) src/libgdl/gdl-dock-object.h (+2/-2) src/libgdl/gdl-tools.h (+1/-1) src/libnrtype/FontFactory.cpp (+1/-1) src/libnrtype/Layout-TNG-OutIter.cpp (+26/-5) src/libvpsc/Makefile_insert (+0/-2) src/libvpsc/block.cpp (+1/-1) src/libvpsc/csolve_VPSC.cpp (+0/-126) src/libvpsc/csolve_VPSC.h (+0/-60) src/live_effects/lpe-bendpath.cpp (+6/-3) src/live_effects/lpe-perp_bisector.h (+2/-2) src/main.cpp (+3/-0) src/pencil-context.cpp (+16/-9) src/preferences.cpp (+3/-0) src/prefix.cpp (+0/-3) src/registrytool.cpp (+1/-1) src/remove-last.h (+3/-2) src/select-context.cpp (+2/-2) src/selection-chemistry.cpp (+1/-1) src/selection.cpp (+2/-0) src/seltrans.cpp (+1/-1) src/sp-conn-end.cpp (+1/-1) src/sp-flowregion.cpp (+2/-2) src/sp-guide.cpp (+4/-4) src/sp-image.cpp (+4/-6) src/sp-item-group.cpp (+2/-0) src/sp-item-rm-unsatisfied-cns.cpp (+2/-2) src/sp-namedview.cpp (+4/-4) src/sp-polygon.cpp (+7/-4) src/splivarot.cpp (+15/-5) src/spray-context.cpp (+22/-32) src/trace/imagemap-gdk.cpp (+8/-6) src/trace/imagemap-gdk.h (+2/-2) src/trace/siox.cpp (+3/-12) src/trace/siox.h (+1/-11) src/trace/trace.cpp (+2/-2) src/tweak-context.cpp (+1/-1) src/ui/dialog/filedialogimpl-gtkmm.cpp (+10/-5) src/ui/dialog/filedialogimpl-win32.cpp (+10/-12) src/ui/dialog/filedialogimpl-win32.h (+12/-0) src/ui/dialog/inkscape-preferences.cpp (+5/-2) src/ui/dialog/layers.cpp (+4/-3) src/ui/dialog/print.cpp (+4/-3) src/ui/tool/multi-path-manipulator.cpp (+13/-3) src/ui/tool/node-tool.cpp (+4/-0) src/ui/tool/node.h (+8/-0) src/ui/tool/path-manipulator.cpp (+5/-1) src/ui/tool/transform-handle-set.cpp (+1/-1) src/ui/widget/registered-widget.h (+0/-3) src/verbs.cpp (+5/-0) src/widgets/desktop-widget.cpp (+12/-14) src/widgets/eek-preview.cpp (+1/-1) src/widgets/ege-paint-def.cpp (+1/-1) src/widgets/sp-color-icc-selector.cpp (+3/-3) src/widgets/toolbox.cpp (+1/-1) src/xml/repr-io.cpp (+75/-15) src/xml/repr-util.cpp (+3/-3) test-driver (+139/-0) |
||||||||||||||||||||||||||||
To merge this branch: | bzr merge lp:~valavanisalex/ubuntu/utopic/inkscape/fix-1358863 | ||||||||||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Holbach (community) | Approve | ||
Review via email: mp+231439@code.launchpad.net |
Commit message
Description of the change
Merge upstream bugfix version 0.48.5 from Debian Unstable/Testing
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed directory '.pc/0001-Fix_Datamatrix_UI_issue.patch' |
2 | === removed directory '.pc/0001-Fix_Datamatrix_UI_issue.patch/share' |
3 | === removed directory '.pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions' |
4 | === removed file '.pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.inx' |
5 | --- .pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.inx 2013-07-02 17:25:52 +0000 |
6 | +++ .pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.inx 1970-01-01 00:00:00 +0000 |
7 | @@ -1,20 +0,0 @@ |
8 | -<?xml version="1.0" encoding="UTF-8"?> |
9 | -<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> |
10 | - <_name>Barcode - Datamatrix</_name> |
11 | - <id>il.datamatrix</id> |
12 | - <dependency type="executable" location="extensions">render_barcode_datamatrix.py</dependency> |
13 | - <dependency type="executable" location="extensions">inkex.py</dependency> |
14 | - <param name="text" type="string" _gui-text="Text">Inkscape</param> |
15 | - <param name="rows" type="int" min="8" max="144" _gui-text="Rows">10</param> |
16 | - <param name="cols" type="int" min="10" max="144" _gui-text="Cols">10</param> |
17 | - <param name="size" type="int" min="1" max="1000" _gui-text="Square Size / px">4</param> |
18 | - <effect> |
19 | - <object-type>all</object-type> |
20 | - <effects-menu> |
21 | - <submenu _name="Render"/> |
22 | - </effects-menu> |
23 | - </effect> |
24 | - <script> |
25 | - <command reldir="extensions" interpreter="python">render_barcode_datamatrix.py</command> |
26 | - </script> |
27 | -</inkscape-extension> |
28 | |
29 | === removed file '.pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.py' |
30 | --- .pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.py 2013-07-02 17:25:52 +0000 |
31 | +++ .pc/0001-Fix_Datamatrix_UI_issue.patch/share/extensions/render_barcode_datamatrix.py 1970-01-01 00:00:00 +0000 |
32 | @@ -1,654 +0,0 @@ |
33 | -#!/usr/bin/env python |
34 | -# -*- coding: UTF-8 -*- |
35 | -''' |
36 | -Copyright (C) 2009 John Beard john.j.beard@gmail.com |
37 | - |
38 | -######DESCRIPTION###### |
39 | - |
40 | -This extension renders a DataMatrix 2D barcode, as specified in |
41 | -BS ISO/IEC 16022:2006. Only ECC200 codes are considered, as these are the only |
42 | -ones recommended for an "open" system. |
43 | - |
44 | -The size of the DataMatrix is variable between 10x10 to 144x144 |
45 | - |
46 | -The absolute size of the DataMatrix modules (the little squares) is also |
47 | -variable. |
48 | - |
49 | -If more data is given than can be contained in one DataMatrix, |
50 | -more than one DataMatrices will be produced. |
51 | - |
52 | -Text is encoded as ASCII (the standard provides for other options, but these are |
53 | -not implemented). Consecutive digits are encoded in a compressed form, halving |
54 | -the space required to store them. |
55 | - |
56 | -The basis processing flow is; |
57 | - * Convert input string to codewords (modified ASCII and compressed digits) |
58 | - * Split codewords into blocks of the right size for Reed-Solomon coding |
59 | - * Interleave the blocks if required |
60 | - * Apply Reed-Solomon coding |
61 | - * De-interleave the blocks if required |
62 | - * Place the codewords into the matrix bit by bit |
63 | - * Render the modules in the matrix as squares |
64 | - |
65 | -######LICENCE####### |
66 | -This program is free software; you can redistribute it and/or modify |
67 | -it under the terms of the GNU General Public License as published by |
68 | -the Free Software Foundation; either version 2 of the License, or |
69 | -(at your option) any later version. |
70 | - |
71 | -This program is distributed in the hope that it will be useful, |
72 | -but WITHOUT ANY WARRANTY; without even the implied warranty of |
73 | -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
74 | -GNU General Public License for more details. |
75 | - |
76 | -You should have received a copy of the GNU General Public License |
77 | -along with this program; if not, write to the Free Software |
78 | -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
79 | - |
80 | -######VERSION HISTORY##### |
81 | - Ver. Date Notes |
82 | - |
83 | - 0.50 2009-10-25 Full functionality, up to 144x144. |
84 | - ASCII and compressed digit encoding only. |
85 | -''' |
86 | - |
87 | -import inkex, simplestyle |
88 | - |
89 | -import gettext |
90 | -_ = gettext.gettext |
91 | - |
92 | -#ENCODING ROUTINES =================================================== |
93 | -# Take an input string and convert it to a sequence (or sequences) |
94 | -# of codewords as specified in ISO/IEC 16022:2006 (section 5.2.3) |
95 | -#===================================================================== |
96 | - |
97 | -#create a 2d list corresponding to the 1's and 0s of the DataMatrix |
98 | -def encode(text, (nrow, ncol) ): |
99 | - #retreive the parameters of this size of DataMatrix |
100 | - data_nrow, data_ncol, reg_row, reg_col, nd, nc, inter = get_parameters( nrow, ncol ) |
101 | - |
102 | - if not ((nrow == 144) and (ncol == 144)): #we have a regular datamatrix |
103 | - size144 = False |
104 | - else: #special handling will be required by get_codewords() |
105 | - size144 = True |
106 | - |
107 | - #generate the codewords including padding and ECC |
108 | - codewords = get_codewords( text, nd, nc, inter, size144 ) |
109 | - |
110 | - # break up into separate arrays if more than one DataMatrix is needed |
111 | - module_arrays = [] |
112 | - for codeword_stream in codewords: #for each datamatrix |
113 | - bit_array = place_bits(codeword_stream, (data_nrow*reg_row, data_ncol*reg_col)) #place the codewords' bits across the array as modules |
114 | - module_arrays.append(add_finder_pattern( bit_array, data_nrow, data_ncol, reg_row, reg_col )) #add finder patterns around the modules |
115 | - |
116 | - return module_arrays |
117 | - |
118 | -#return parameters for the selected datamatrix size |
119 | -# data_nrow number of rows in each data region |
120 | -# data_ncol number of cols in each data region |
121 | -# reg_row number of rows of data regions |
122 | -# reg_col number of cols of data regions |
123 | -# nd number of data codewords per reed-solomon block |
124 | -# nc number of ECC codewords per reed-solomon block |
125 | -# inter number of interleaved Reed-Solomon blocks |
126 | -def get_parameters(nrow, ncol): |
127 | - |
128 | - #SQUARE SYMBOLS |
129 | - if ( nrow == 10 and ncol == 10 ): |
130 | - return 8, 8, 1, 1, 3, 5, 1 |
131 | - elif ( nrow == 12 and ncol == 12 ): |
132 | - return 10, 10, 1, 1, 5, 7, 1 |
133 | - elif ( nrow == 14 and ncol == 14 ): |
134 | - return 12, 12, 1, 1, 8, 10, 1 |
135 | - elif ( nrow == 16 and ncol == 16 ): |
136 | - return 14, 14, 1, 1, 12, 12, 1 |
137 | - elif ( nrow == 18 and ncol == 18 ): |
138 | - return 16, 16, 1, 1, 18, 14, 1 |
139 | - elif ( nrow == 20 and ncol == 20 ): |
140 | - return 18, 18, 1, 1, 22, 18, 1 |
141 | - elif ( nrow == 22 and ncol == 22 ): |
142 | - return 18, 18, 1, 1, 30, 20, 1 |
143 | - elif ( nrow == 24 and ncol == 24 ): |
144 | - return 22, 22, 1, 1, 36, 24, 1 |
145 | - elif ( nrow == 26 and ncol == 26 ): |
146 | - return 24, 24, 1, 1, 44, 28, 1 |
147 | - elif ( nrow == 32 and ncol == 32 ): |
148 | - return 14, 14, 2, 2, 62, 36, 1 |
149 | - elif ( nrow == 36 and ncol == 36 ): |
150 | - return 16, 16, 2, 2, 86, 42, 1 |
151 | - elif ( nrow == 40 and ncol == 40): |
152 | - return 18, 18, 2, 2, 114, 48, 1 |
153 | - elif ( nrow == 44 and ncol == 44): |
154 | - return 20, 20, 2, 2, 144, 56, 1 |
155 | - elif ( nrow == 48 and ncol == 48 ): |
156 | - return 22, 22, 2, 2, 174, 68, 1 |
157 | - |
158 | - elif ( nrow == 52 and ncol == 52 ): |
159 | - return 24, 24, 2, 2, 102, 42, 2 |
160 | - elif ( nrow == 64 and ncol == 64 ): |
161 | - return 16, 16, 4, 4, 140, 56, 2 |
162 | - |
163 | - elif ( nrow == 72 and ncol == 72 ): |
164 | - return 16, 16, 4, 4, 92, 36, 4 |
165 | - elif ( nrow == 80 and ncol == 80 ): |
166 | - return 18, 18, 4, 4, 114, 48, 4 |
167 | - elif ( nrow == 88 and ncol == 88 ): |
168 | - return 20, 20, 4, 4, 144, 56, 4 |
169 | - elif ( nrow == 96 and ncol == 96 ): |
170 | - return 22, 22, 4, 4, 174, 68, 4 |
171 | - |
172 | - elif ( nrow == 104 and ncol == 104 ): |
173 | - return 24, 24, 4, 4, 136, 56, 6 |
174 | - elif ( nrow == 120 and ncol == 120): |
175 | - return 18, 18, 6, 6, 175, 68, 6 |
176 | - |
177 | - elif ( nrow == 132 and ncol == 132): |
178 | - return 20, 20, 6, 6, 163, 62, 8 |
179 | - |
180 | - elif (nrow == 144 and ncol == 144): |
181 | - return 22, 22, 6, 6, 0, 0, 0 #there are two separate sections of the data matrix with |
182 | - #different interleaving and reed-solomon parameters. |
183 | - #this will be handled separately |
184 | - |
185 | - #RECTANGULAR SYMBOLS |
186 | - elif ( nrow == 8 and ncol == 18 ): |
187 | - return 6, 16, 1, 1, 5, 7, 1 |
188 | - elif ( nrow == 8 and ncol == 32 ): |
189 | - return 6, 14, 1, 2, 10, 11, 1 |
190 | - elif ( nrow == 12 and ncol == 26 ): |
191 | - return 10, 24, 1, 1, 16, 14, 1 |
192 | - elif ( nrow == 12 and ncol == 36 ): |
193 | - return 10, 16, 1, 2, 22, 18, 1 |
194 | - elif ( nrow == 16 and ncol == 36 ): |
195 | - return 14, 16, 1, 2, 32, 24, 1 |
196 | - elif ( nrow == 16 and ncol == 48 ): |
197 | - return 14, 22, 1, 2, 49, 28, 1 |
198 | - |
199 | - #RETURN ERROR |
200 | - else: |
201 | - inkex.errormsg(_('Unrecognised DataMatrix size')) |
202 | - |
203 | - return None |
204 | - |
205 | -# CODEWORD STREAM GENERATION ========================================= |
206 | -#take the text input and return the codewords, |
207 | -#including the Reed-Solomon error-correcting codes. |
208 | -#===================================================================== |
209 | - |
210 | -def get_codewords( text, nd, nc, inter, size144 ): |
211 | - #convert the data to the codewords |
212 | - data = encode_to_ascii( text ) |
213 | - |
214 | - if not size144: #render a "normal" datamatrix |
215 | - data_blocks = partition_data(data, nd*inter) #partition into data blocks of length nd*inter -> inter Reed-Solomon block |
216 | - |
217 | - data_blocks = interleave( data_blocks, inter) # interleave consecutive inter blocks if required |
218 | - |
219 | - data_blocks = reed_solomon(data_blocks, nd, nc) #generate and append the Reed-Solomon codewords |
220 | - |
221 | - data_blocks = combine_interleaved(data_blocks, inter, nd, nc, False) #concatenate Reed-Solomon blocks bound for the same datamatrix |
222 | - |
223 | - else: #we have a 144x144 datamatrix |
224 | - data_blocks = partition_data(data, 1558) #partition the data into datamtrix-sized chunks (1558 =156*8 + 155*2 ) |
225 | - |
226 | - for i in range(len(data_blocks)): #for each datamtrix |
227 | - |
228 | - |
229 | - inter = 8 |
230 | - nd = 156 |
231 | - nc = 62 |
232 | - block1 = data_blocks[i][0:156*8] |
233 | - block1 = interleave( [block1], inter) # interleave into 8 blocks |
234 | - block1 = reed_solomon(block1, nd, nc) #generate and append the Reed-Solomon codewords |
235 | - |
236 | - inter = 2 |
237 | - nd = 155 |
238 | - nc = 62 |
239 | - block2 = data_blocks[i][156*8:] |
240 | - block2 = interleave( [block2], inter) # interleave into 2 blocks |
241 | - block2 = reed_solomon(block2, nd, nc) #generate and append the Reed-Solomon codewords |
242 | - |
243 | - blocks = block1 |
244 | - blocks.extend(block2) |
245 | - |
246 | - blocks = combine_interleaved(blocks, 10, nd, nc, True) |
247 | - |
248 | - data_blocks[i] = blocks[0] |
249 | - |
250 | - |
251 | - return data_blocks |
252 | - |
253 | - |
254 | -#Takes a codeword stream and splits up into "inter" blocks. |
255 | -#eg interleave( [1,2,3,4,5,6], 2 ) -> [1,3,5], [2,4,6] |
256 | -def interleave( blocks, inter): |
257 | - |
258 | - if inter == 1: # if we don't have to interleave, just return the blocks |
259 | - return blocks |
260 | - else: |
261 | - result = [] |
262 | - for block in blocks: #for each codeword block in the stream |
263 | - block_length = len(block)/inter #length of each interleaved block |
264 | - inter_blocks = [[0] * block_length for i in xrange(inter)] #the interleaved blocks |
265 | - |
266 | - for i in range(block_length): #for each element in the interleaved blocks |
267 | - for j in range(inter): #for each interleaved block |
268 | - inter_blocks[j][i] = block[ i*inter + j ] |
269 | - |
270 | - result.extend(inter_blocks) #add the interleaved blocks to the output |
271 | - |
272 | - return result |
273 | - |
274 | -#Combine interleaved blocks into the groups for the same datamatrix |
275 | -# |
276 | -#e.g combine_interleaved( [[d1, d3, d5, e1, e3, e5], [d2, d4, d6, e2, e4, e6]], 2, 3, 3 ) |
277 | -# --> [[d1, d2, d3, d4, d5, d6, e1, e2, e3, e4, e5, e6]] |
278 | -def combine_interleaved( blocks, inter, nd, nc, size144): |
279 | - if inter == 1: #the blocks aren't interleaved |
280 | - return blocks |
281 | - else: |
282 | - result = [] |
283 | - for i in range( len(blocks) / inter ): #for each group of "inter" blocks -> one full datamatrix |
284 | - data_codewords = [] #interleaved data blocks |
285 | - |
286 | - if size144: |
287 | - nd_range = 1558 #1558 = 156*8 + 155*2 |
288 | - nc_range = 620 #620 = 62*8 + 62*2 |
289 | - else: |
290 | - nd_range = nd*inter |
291 | - nc_range = nc*inter |
292 | - |
293 | - for j in range(nd_range): #for each codeword in the final list |
294 | - data_codewords.append( blocks[i*inter + j%inter][j/inter] ) |
295 | - |
296 | - for j in range(nc_range): #for each block, add the ecc codewords |
297 | - data_codewords.append( blocks[i*inter + j%inter][nd + j/inter] ) |
298 | - |
299 | - result.append(data_codewords) |
300 | - return result |
301 | - |
302 | -#checks if an ASCII character is a digit from 0 - 9 |
303 | -def is_digit( char ): |
304 | - |
305 | - if ord(char) >= 48 and ord(char) <= 57: |
306 | - return True |
307 | - else: |
308 | - return False |
309 | - |
310 | -def encode_to_ascii( text): |
311 | - |
312 | - ascii = [] |
313 | - i = 0 |
314 | - while i < len(text): |
315 | - #check for double digits |
316 | - if is_digit( text[i] ) and ( i < len(text)-1) and is_digit( text[i+1] ): #if the next char is also a digit |
317 | - |
318 | - codeword = int( text[i] + text[i+1] ) + 130 |
319 | - ascii.append( codeword ) |
320 | - i = i + 2 #move on 2 characters |
321 | - else: #encode as a normal ascii, |
322 | - ascii.append( ord(text[i] ) + 1 ) #codeword is ASCII value + 1 (ISO 16022:2006 5.2.3) |
323 | - i = i + 1 #next character |
324 | - |
325 | - return ascii |
326 | - |
327 | - |
328 | -#partition data into blocks of the appropriate size to suit the |
329 | -#Reed-Solomon block being used. |
330 | -#e.g. partition_data([1,2,3,4,5], 3) -> [[1,2,3],[4,5,PAD]] |
331 | -def partition_data( data , rs_data): |
332 | - |
333 | - PAD_VAL = 129 # PAD codeword (ISO 16022:2006 5.2.3) |
334 | - data_blocks = [] |
335 | - i = 0 |
336 | - while i < len(data): |
337 | - if len(data) >= i+rs_data: #we have a whole block in our data |
338 | - data_blocks.append( data[i:i+rs_data] ) |
339 | - i = i + rs_data |
340 | - else: #pad out with the pad codeword |
341 | - data_block = data[i:len(data)] #add any remaining data |
342 | - pad_pos = len(data) |
343 | - padded = False |
344 | - while len(data_block) < rs_data:#and then pad with randomised pad codewords |
345 | - if not padded: |
346 | - data_block.append( PAD_VAL ) #add a normal pad codeword |
347 | - padded = True |
348 | - else: |
349 | - data_block.append( randomise_pad_253( PAD_VAL, pad_pos) ) |
350 | - pad_pos = pad_pos + 1 |
351 | - data_blocks.append( data_block) |
352 | - break |
353 | - |
354 | - return data_blocks |
355 | - |
356 | -#Pad character randomisation, to prevent regular patterns appearing |
357 | -#in the data matrix |
358 | -def randomise_pad_253(pad_value, pad_position ): |
359 | - pseudo_random_number = ( ( 149 * pad_position ) % 253 )+ 1 |
360 | - randomised = pad_value + pseudo_random_number |
361 | - if ( randomised <= 254 ): |
362 | - return randomised |
363 | - else: |
364 | - return randomised - 254 |
365 | - |
366 | -# REED-SOLOMON ENCODING ROUTINES ===================================== |
367 | - |
368 | -# "prod(x,y,log,alog,gf)" returns the product "x" times "y" |
369 | -def prod(x, y, log, alog, gf): |
370 | - |
371 | - if ( x==0 or y==0): |
372 | - return 0 |
373 | - else: |
374 | - result = alog[ ( log[x] + log[y] ) % (gf - 1) ] |
375 | - return result |
376 | - |
377 | -# generate the log & antilog lists: |
378 | -def gen_log_alog(gf, pp): |
379 | - log = [0]*gf |
380 | - alog = [0]*gf |
381 | - |
382 | - log[0] = 1-gf |
383 | - alog[0] = 1 |
384 | - |
385 | - for i in range(1,gf): |
386 | - alog[i] = alog[i-1] * 2 |
387 | - |
388 | - if (alog[i] >= gf): |
389 | - alog[i] = alog[i] ^ pp |
390 | - |
391 | - log[alog[i]] = i |
392 | - |
393 | - return log, alog |
394 | - |
395 | -# generate the generator polynomial coefficients: |
396 | -def gen_poly_coeffs(nc, log, alog, gf): |
397 | - c = [0] * (nc+1) |
398 | - c[0] = 1 |
399 | - |
400 | - for i in range(1,nc+1): |
401 | - c[i] = c[i-1] |
402 | - |
403 | - j = i-1 |
404 | - while j >= 1: |
405 | - c[j] = c[j-1] ^ prod(c[j],alog[i],log,alog,gf) |
406 | - j = j - 1 |
407 | - |
408 | - c[0] = prod(c[0],alog[i],log,alog,gf) |
409 | - |
410 | - return c |
411 | - |
412 | -# "ReedSolomon(wd,nd,nc)" takes "nd" data codeword values in wd[] |
413 | -# and adds on "nc" check codewords, all within GF(gf) where "gf" is a |
414 | -# power of 2 and "pp" is the value of its prime modulus polynomial */ |
415 | -def reed_solomon(data, nd, nc): |
416 | - #parameters of the polynomial arithmetic |
417 | - gf = 256 #operating on 8-bit codewords -> Galois field = 2^8 = 256 |
418 | - pp = 301 #prime modulus polynomial for ECC-200 is 0b100101101 = 301 (ISO 16022:2006 5.7.1) |
419 | - |
420 | - log, alog = gen_log_alog(gf,pp) |
421 | - c = gen_poly_coeffs(nc, log, alog, gf) |
422 | - |
423 | - for block in data: #for each block of data codewords |
424 | - |
425 | - block.extend( [0]*(nc+1) ) #extend to make space for the error codewords |
426 | - |
427 | - #generate "nc" checkwords in the list block |
428 | - for i in range(0, nd): |
429 | - k = block[nd] ^ block[i] |
430 | - |
431 | - for j in range(0,nc): |
432 | - block[nd+j] = block[nd+j+1] ^ prod(k,c[nc-j-1],log, alog,gf) |
433 | - |
434 | - block.pop() |
435 | - |
436 | - return data |
437 | - |
438 | -#MODULE PLACEMENT ROUTINES=========================================== |
439 | -# These routines take a steam of codewords, and place them into the |
440 | -# DataMatrix in accordance with Annex F of BS ISO/IEC 16022:2006 |
441 | - |
442 | -# bit() returns the bit'th bit of the byte |
443 | -def bit(byte, bit): |
444 | - #the MSB is bit 1, LSB is bit 8 |
445 | - return ( byte >> (8-bit) ) %2 |
446 | - |
447 | -# "module" places a given bit with appropriate wrapping within array |
448 | -def module(array, nrow, ncol, row, col, bit) : |
449 | - if (row < 0) : |
450 | - row = row + nrow |
451 | - col = col + 4 - ((nrow+4)%8) |
452 | - |
453 | - if (col < 0): |
454 | - col = col + ncol |
455 | - row = row + 4 - ((ncol+4)%8) |
456 | - |
457 | - array[row][col] = bit |
458 | - |
459 | -def corner1(array, nrow, ncol, char): |
460 | - module(array, nrow, ncol, nrow-1, 0, bit(char,1)); |
461 | - module(array, nrow, ncol, nrow-1, 1, bit(char,2)); |
462 | - module(array, nrow, ncol, nrow-1, 2, bit(char,3)); |
463 | - module(array, nrow, ncol, 0, ncol-2, bit(char,4)); |
464 | - module(array, nrow, ncol, 0, ncol-1, bit(char,5)); |
465 | - module(array, nrow, ncol, 1, ncol-1, bit(char,6)); |
466 | - module(array, nrow, ncol, 2, ncol-1, bit(char,7)); |
467 | - module(array, nrow, ncol, 3, ncol-1, bit(char,8)); |
468 | - |
469 | -def corner2(array, nrow, ncol, char): |
470 | - module(array, nrow, ncol, nrow-3, 0, bit(char,1)); |
471 | - module(array, nrow, ncol, nrow-2, 0, bit(char,2)); |
472 | - module(array, nrow, ncol, nrow-1, 0, bit(char,3)); |
473 | - module(array, nrow, ncol, 0, ncol-4, bit(char,4)); |
474 | - module(array, nrow, ncol, 0, ncol-3, bit(char,5)); |
475 | - module(array, nrow, ncol, 0, ncol-2, bit(char,6)); |
476 | - module(array, nrow, ncol, 0, ncol-1, bit(char,7)); |
477 | - module(array, nrow, ncol, 1, ncol-1, bit(char,8)); |
478 | - |
479 | -def corner3(array, nrow, ncol, char): |
480 | - module(array, nrow, ncol, nrow-3, 0, bit(char,1)); |
481 | - module(array, nrow, ncol, nrow-2, 0, bit(char,2)); |
482 | - module(array, nrow, ncol, nrow-1, 0, bit(char,3)); |
483 | - module(array, nrow, ncol, 0, ncol-2, bit(char,4)); |
484 | - module(array, nrow, ncol, 0, ncol-1, bit(char,5)); |
485 | - module(array, nrow, ncol, 1, ncol-1, bit(char,6)); |
486 | - module(array, nrow, ncol, 2, ncol-1, bit(char,7)); |
487 | - module(array, nrow, ncol, 3, ncol-1, bit(char,8)); |
488 | - |
489 | -def corner4(array, nrow, ncol, char): |
490 | - module(array, nrow, ncol, nrow-1, 0, bit(char,1)); |
491 | - module(array, nrow, ncol, nrow-1, ncol-1, bit(char,2)); |
492 | - module(array, nrow, ncol, 0, ncol-3, bit(char,3)); |
493 | - module(array, nrow, ncol, 0, ncol-2, bit(char,4)); |
494 | - module(array, nrow, ncol, 0, ncol-1, bit(char,5)); |
495 | - module(array, nrow, ncol, 1, ncol-3, bit(char,6)); |
496 | - module(array, nrow, ncol, 1, ncol-2, bit(char,7)); |
497 | - module(array, nrow, ncol, 1, ncol-1, bit(char,8)); |
498 | - |
499 | -#"utah" places the 8 bits of a utah-shaped symbol character in ECC200 |
500 | -def utah(array, nrow, ncol, row, col, char): |
501 | - module(array, nrow, ncol,row-2, col-2, bit(char,1)) |
502 | - module(array, nrow, ncol,row-2, col-1, bit(char,2)) |
503 | - module(array, nrow, ncol,row-1, col-2, bit(char,3)) |
504 | - module(array, nrow, ncol,row-1, col-1, bit(char,4)) |
505 | - module(array, nrow, ncol,row-1, col, bit(char,5)) |
506 | - module(array, nrow, ncol,row, col-2, bit(char,6)) |
507 | - module(array, nrow, ncol,row, col-1, bit(char,7)) |
508 | - module(array, nrow, ncol,row, col, bit(char,8)) |
509 | - |
510 | -#"place_bits" fills an nrow x ncol array with the bits from the |
511 | -# codewords in data. |
512 | -def place_bits(data, (nrow, ncol)): |
513 | -# First, fill the array[] with invalid entries */ |
514 | - INVALID = 2 |
515 | - array = [[INVALID] * ncol for i in xrange(nrow)] #initialise and fill with -1's (invalid value) |
516 | -# Starting in the correct location for character #1, bit 8,... |
517 | - char = 0 |
518 | - row = 4 |
519 | - col = 0 |
520 | - while True: |
521 | - |
522 | - #first check for one of the special corner cases, then... |
523 | - if ((row == nrow) and (col == 0)): |
524 | - corner1(array, nrow, ncol, data[char]) |
525 | - char = char + 1 |
526 | - if ((row == nrow-2) and (col == 0) and (ncol%4)) : |
527 | - corner2(array, nrow, ncol, data[char]) |
528 | - char = char + 1 |
529 | - if ((row == nrow-2) and (col == 0) and (ncol%8 == 4)): |
530 | - corner3(array, nrow, ncol, data[char]) |
531 | - char = char + 1 |
532 | - if ((row == nrow+4) and (col == 2) and ((ncol%8) == 0)): |
533 | - corner4(array, nrow, ncol, data[char]) |
534 | - char = char + 1 |
535 | - |
536 | - #sweep upward diagonally, inserting successive characters,... |
537 | - while True: |
538 | - if ((row < nrow) and (col >= 0) and (array[row][col] == INVALID)) : |
539 | - utah(array, nrow, ncol,row,col,data[char]) |
540 | - char = char+1 |
541 | - row = row - 2 |
542 | - col = col + 2 |
543 | - |
544 | - if not((row >= 0) and (col < ncol)): |
545 | - break |
546 | - |
547 | - row = row + 1 |
548 | - col = col + 3 |
549 | - |
550 | - # & then sweep downward diagonally, inserting successive characters,... |
551 | - while True: |
552 | - if ((row >= 0) and (col < ncol) and (array[row][col] == INVALID)) : |
553 | - utah(array, nrow, ncol,row,col,data[char]) |
554 | - char = char + 1 |
555 | - row = row + 2 |
556 | - col = col - 2 |
557 | - |
558 | - if not((row < nrow) and (col >= 0)): |
559 | - break |
560 | - |
561 | - row = row + 3 |
562 | - col = col + 1 |
563 | - |
564 | - #... until the entire array is scanned |
565 | - if not((row < nrow) or (col < ncol)): |
566 | - break |
567 | - |
568 | - # Lastly, if the lower righthand corner is untouched, fill in fixed pattern */ |
569 | - if (array[nrow-1][ncol-1] == INVALID): |
570 | - array[nrow-1][ncol-2] = 0 |
571 | - array[nrow-1][ncol-1] = 1 |
572 | - array[nrow-2][ncol-1] = 0 |
573 | - array[nrow-2][ncol-2] = 1 |
574 | - |
575 | - return array #return the array of 1's and 0's |
576 | - |
577 | - |
578 | -def add_finder_pattern( array, data_nrow, data_ncol, reg_row, reg_col ): |
579 | - |
580 | - #get the total size of the datamatrix |
581 | - nrow = (data_nrow+2) * reg_row |
582 | - ncol = (data_ncol+2) * reg_col |
583 | - |
584 | - datamatrix = [[0] * ncol for i in xrange(nrow)] #initialise and fill with 0's |
585 | - |
586 | - for i in range( reg_col ): #for each column of data regions |
587 | - for j in range(nrow): |
588 | - datamatrix[j][i*(data_ncol+2)] = 1 #vertical black bar on left |
589 | - datamatrix[j][i*(data_ncol+2)+data_ncol+1] = (j)%2 # alternating blocks |
590 | - |
591 | - for i in range( reg_row): # for each row of data regions |
592 | - for j in range(ncol): |
593 | - datamatrix[i*(data_nrow+2)+data_nrow+1][j] = 1 #horizontal black bar at bottom |
594 | - datamatrix[i*(data_nrow+2)][j] = (j+1)%2 # alternating blocks |
595 | - |
596 | - for i in range( data_nrow*reg_row ): |
597 | - for j in range( data_ncol* reg_col ): |
598 | - dest_col = j + 1 + 2*(j/(data_ncol)) #offset by 1, plus two for every addition block |
599 | - dest_row = i + 1 + 2*(i/(data_nrow)) |
600 | - |
601 | - datamatrix[dest_row][dest_col] = array[i][j] #transfer from the plain bit array |
602 | - |
603 | - return datamatrix |
604 | - |
605 | -#RENDERING ROUTINES ================================================== |
606 | -# Take the array of 1's and 0's and render as a series of black |
607 | -# squares. A binary 1 is a filled square |
608 | -#===================================================================== |
609 | - |
610 | -#SVG element generation routine |
611 | -def draw_SVG_square((w,h), (x,y), parent): |
612 | - |
613 | - style = { 'stroke' : 'none', |
614 | - 'stroke-width' : '1', |
615 | - 'fill' : '#000000' |
616 | - } |
617 | - |
618 | - attribs = { |
619 | - 'style' :simplestyle.formatStyle(style), |
620 | - 'height' : str(h), |
621 | - 'width' : str(w), |
622 | - 'x' : str(x), |
623 | - 'y' : str(y) |
624 | - } |
625 | - circ = inkex.etree.SubElement(parent, inkex.addNS('rect','svg'), attribs ) |
626 | - |
627 | -#turn a 2D array of 1's and 0's into a set of black squares |
628 | -def render_data_matrix( module_arrays, size, spacing, parent): |
629 | - |
630 | - for i in range(len(module_arrays)): #for each data matrix |
631 | - |
632 | - height = len(module_arrays[i]) |
633 | - width = len(module_arrays[i][0] ) |
634 | - |
635 | - for y in range(height): #loop over all the modules in the datamatrix |
636 | - for x in range(width): |
637 | - |
638 | - if module_arrays[i][y][x] == 1: #A binary 1 is a filled square |
639 | - draw_SVG_square((size,size), (x*size + i*spacing,y*size), parent) |
640 | - elif module_arrays[i][y][x] != 0: #we have an invalid bit value |
641 | - inkex.errormsg(_('Invalid bit value, this is a bug!')) |
642 | - |
643 | -class DataMatrix(inkex.Effect): |
644 | - def __init__(self): |
645 | - inkex.Effect.__init__(self) |
646 | - |
647 | - #PARSE OPTIONS |
648 | - self.OptionParser.add_option("--text", |
649 | - action="store", type="string", |
650 | - dest="TEXT", default='Inkscape') |
651 | - self.OptionParser.add_option("--rows", |
652 | - action="store", type="int", |
653 | - dest="ROWS", default=10) |
654 | - self.OptionParser.add_option("--cols", |
655 | - action="store", type="int", |
656 | - dest="COLS", default=10) |
657 | - self.OptionParser.add_option("--size", |
658 | - action="store", type="int", |
659 | - dest="SIZE", default=4) |
660 | - |
661 | - def effect(self): |
662 | - |
663 | - so = self.options |
664 | - |
665 | - if so.TEXT == '': #abort if converting blank text |
666 | - inkex.errormsg(_('Please enter an input string')) |
667 | - else: |
668 | - |
669 | - #INKSCAPE GROUP TO CONTAIN EVERYTHING |
670 | - |
671 | - centre = self.view_center #Put in in the centre of the current view |
672 | - grp_transform = 'translate' + str( centre ) |
673 | - grp_name = 'DataMatrix' |
674 | - grp_attribs = {inkex.addNS('label','inkscape'):grp_name, |
675 | - 'transform':grp_transform } |
676 | - grp = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs)#the group to put everything in |
677 | - |
678 | - #GENERATE THE DATAMATRIX |
679 | - encoded = encode( so.TEXT, (so.ROWS, so.COLS) ) #get the pattern of squares |
680 | - render_data_matrix( encoded, so.SIZE, so.COLS*so.SIZE*1.5, grp ) # generate the SVG elements |
681 | - |
682 | -if __name__ == '__main__': |
683 | - e = DataMatrix() |
684 | - e.affect() |
685 | - |
686 | -# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99 |
687 | |
688 | === removed directory '.pc/0002-Drop_PS_and_PDF_support_in_MimeType.patch' |
689 | === removed file '.pc/0002-Drop_PS_and_PDF_support_in_MimeType.patch/inkscape.desktop.in' |
690 | --- .pc/0002-Drop_PS_and_PDF_support_in_MimeType.patch/inkscape.desktop.in 2013-07-02 17:25:52 +0000 |
691 | +++ .pc/0002-Drop_PS_and_PDF_support_in_MimeType.patch/inkscape.desktop.in 1970-01-01 00:00:00 +0000 |
692 | @@ -1,14 +0,0 @@ |
693 | -[Desktop Entry] |
694 | -Version=1.0 |
695 | -_Name=Inkscape |
696 | -_GenericName=Vector Graphics Editor |
697 | -_X-GNOME-FullName=Inkscape Vector Graphics Editor |
698 | -_Comment=Create and edit Scalable Vector Graphics images |
699 | -Type=Application |
700 | -Categories=Graphics;VectorGraphics;GTK; |
701 | -MimeType=image/svg+xml;image/svg+xml-compressed;application/vnd.corel-draw;application/pdf;application/postscript;image/x-eps;application/illustrator; |
702 | -Exec=inkscape %F |
703 | -TryExec=inkscape |
704 | -Terminal=false |
705 | -StartupNotify=true |
706 | -Icon=inkscape |
707 | |
708 | === removed directory '.pc/0003-Fix_LP_-911146.patch' |
709 | === removed directory '.pc/0003-Fix_LP_-911146.patch/src' |
710 | === removed directory '.pc/0003-Fix_LP_-911146.patch/src/extension' |
711 | === removed directory '.pc/0003-Fix_LP_-911146.patch/src/extension/implementation' |
712 | === removed file '.pc/0003-Fix_LP_-911146.patch/src/extension/implementation/script.cpp' |
713 | --- .pc/0003-Fix_LP_-911146.patch/src/extension/implementation/script.cpp 2013-07-02 17:25:52 +0000 |
714 | +++ .pc/0003-Fix_LP_-911146.patch/src/extension/implementation/script.cpp 1970-01-01 00:00:00 +0000 |
715 | @@ -1,1034 +0,0 @@ |
716 | -/** \file |
717 | - * Code for handling extensions (i.e.\ scripts). |
718 | - */ |
719 | -/* |
720 | - * Authors: |
721 | - * Bryce Harrington <bryce@osdl.org> |
722 | - * Ted Gould <ted@gould.cx> |
723 | - * Jon A. Cruz <jon@joncruz.org> |
724 | - * |
725 | - * Copyright (C) 2002-2005,2007 Authors |
726 | - * |
727 | - * Released under GNU GPL, read the file 'COPYING' for more information |
728 | - */ |
729 | - |
730 | -#define __INKSCAPE_EXTENSION_IMPLEMENTATION_SCRIPT_C__ |
731 | - |
732 | -#ifdef HAVE_CONFIG_H |
733 | -# include <config.h> |
734 | -#endif |
735 | - |
736 | -#include <unistd.h> |
737 | - |
738 | -#include <errno.h> |
739 | -#include <glib.h> |
740 | -#include <glib/gstdio.h> |
741 | -#include <gtkmm.h> |
742 | - |
743 | -#include "ui/view/view.h" |
744 | -#include "desktop-handles.h" |
745 | -#include "desktop.h" |
746 | -#include "selection.h" |
747 | -#include "sp-namedview.h" |
748 | -#include "io/sys.h" |
749 | -#include "preferences.h" |
750 | -#include "../system.h" |
751 | -#include "extension/effect.h" |
752 | -#include "extension/output.h" |
753 | -#include "extension/input.h" |
754 | -#include "extension/db.h" |
755 | -#include "script.h" |
756 | -#include "dialogs/dialog-events.h" |
757 | -#include "application/application.h" |
758 | -#include "xml/node.h" |
759 | -#include "xml/attribute-record.h" |
760 | - |
761 | -#include "util/glib-list-iterators.h" |
762 | -#include "path-prefix.h" |
763 | - |
764 | - |
765 | -#ifdef WIN32 |
766 | -#include <windows.h> |
767 | -#include <sys/stat.h> |
768 | -#include "registrytool.h" |
769 | -#endif |
770 | - |
771 | - |
772 | - |
773 | -/** This is the command buffer that gets allocated from the stack */ |
774 | -#define BUFSIZE (255) |
775 | - |
776 | - |
777 | - |
778 | -/* Namespaces */ |
779 | -namespace Inkscape { |
780 | -namespace Extension { |
781 | -namespace Implementation { |
782 | - |
783 | -/** \brief Make GTK+ events continue to come through a little bit |
784 | - |
785 | - This just keeps coming the events through so that we'll make the GUI |
786 | - update and look pretty. |
787 | -*/ |
788 | -void Script::pump_events (void) { |
789 | - while ( Gtk::Main::events_pending() ) { |
790 | - Gtk::Main::iteration(); |
791 | - } |
792 | - return; |
793 | -} |
794 | - |
795 | - |
796 | -/** \brief A table of what interpreters to call for a given language |
797 | - |
798 | - This table is used to keep track of all the programs to execute a |
799 | - given script. It also tracks the preference to use to overwrite |
800 | - the given interpreter to a custom one per user. |
801 | -*/ |
802 | -Script::interpreter_t const Script::interpreterTab[] = { |
803 | - {"perl", "perl-interpreter", "perl" }, |
804 | -#ifdef WIN32 |
805 | - {"python", "python-interpreter", "pythonw" }, |
806 | -#else |
807 | - {"python", "python-interpreter", "python" }, |
808 | -#endif |
809 | - {"ruby", "ruby-interpreter", "ruby" }, |
810 | - {"shell", "shell-interpreter", "sh" }, |
811 | - { NULL, NULL, NULL } |
812 | -}; |
813 | - |
814 | - |
815 | - |
816 | -/** \brief Look up an interpreter name, and translate to something that |
817 | - is executable |
818 | - \param interpNameArg The name of the interpreter that we're looking |
819 | - for, should be an entry in interpreterTab |
820 | -*/ |
821 | -std::string Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) |
822 | -{ |
823 | - interpreter_t const *interp = 0; |
824 | - bool foundInterp = false; |
825 | - for (interp = interpreterTab ; interp->identity ; interp++ ){ |
826 | - if (interpNameArg == interp->identity) { |
827 | - foundInterp = true; |
828 | - break; |
829 | - } |
830 | - } |
831 | - |
832 | - // Do we have a supported interpreter type? |
833 | - if (!foundInterp) { |
834 | - return ""; |
835 | - } |
836 | - std::string interpreter_path = Glib::filename_from_utf8(interp->defaultval); |
837 | - |
838 | - // 1. Check preferences for an override. |
839 | - // Note: this must be an absolute path. |
840 | - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
841 | - Glib::ustring prefInterp = prefs->getString("/extensions/" + Glib::ustring(interp->prefstring)); |
842 | - |
843 | - if (!prefInterp.empty()) { |
844 | - interpreter_path = Glib::filename_from_utf8(prefInterp); |
845 | - } |
846 | - |
847 | - // 2. Search the path. |
848 | - // Do this on all systems, for consistency. |
849 | - // PATH is set up to contain the Python and Perl binary directories |
850 | - // on Windows, so no extra code is necessary. |
851 | - if (!Glib::path_is_absolute(interpreter_path)) { |
852 | - interpreter_path = Glib::find_program_in_path(interpreter_path); |
853 | - } |
854 | - return interpreter_path; |
855 | -} |
856 | - |
857 | -/** \brief This function creates a script object and sets up the |
858 | - variables. |
859 | - \return A script object |
860 | - |
861 | - This function just sets the command to NULL. It should get built |
862 | - officially in the load function. This allows for less allocation |
863 | - of memory in the unloaded state. |
864 | -*/ |
865 | -Script::Script() : |
866 | - Implementation() |
867 | -{ |
868 | -} |
869 | - |
870 | -/** |
871 | - * brief Destructor |
872 | - */ |
873 | -Script::~Script() |
874 | -{ |
875 | -} |
876 | - |
877 | - |
878 | - |
879 | -/** |
880 | - \return A string with the complete string with the relative directory expanded |
881 | - \brief This function takes in a Repr that contains a reldir entry |
882 | - and returns that data with the relative directory expanded. |
883 | - Mostly it is here so that relative directories all get used |
884 | - the same way. |
885 | - \param reprin The Inkscape::XML::Node with the reldir in it. |
886 | - |
887 | - Basically this function looks at an attribute of the Repr, and makes |
888 | - a decision based on that. Currently, it is only working with the |
889 | - 'extensions' relative directory, but there will be more of them. |
890 | - One thing to notice is that this function always returns an allocated |
891 | - string. This means that the caller of this function can always |
892 | - free what they are given (and should do it too!). |
893 | -*/ |
894 | -std::string |
895 | -Script::solve_reldir(Inkscape::XML::Node *reprin) { |
896 | - |
897 | - gchar const *s = reprin->attribute("reldir"); |
898 | - |
899 | - // right now the only recognized relative directory is "extensions" |
900 | - if (!s || Glib::ustring(s) != "extensions") { |
901 | - Glib::ustring str = sp_repr_children(reprin)->content(); |
902 | - return str; |
903 | - } |
904 | - |
905 | - Glib::ustring reldir = s; |
906 | - for (unsigned int i=0; |
907 | - i < Inkscape::Extension::Extension::search_path.size(); |
908 | - i++) { |
909 | - |
910 | - gchar * fname = g_build_filename( |
911 | - Inkscape::Extension::Extension::search_path[i], |
912 | - sp_repr_children(reprin)->content(), |
913 | - NULL); |
914 | - Glib::ustring filename = fname; |
915 | - g_free(fname); |
916 | - //printf("Filename: %s\n", filename.c_str()); |
917 | - if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) { |
918 | - return Glib::filename_from_utf8(filename); |
919 | - } |
920 | - } |
921 | - |
922 | - return ""; |
923 | -} |
924 | - |
925 | - |
926 | - |
927 | -/** |
928 | - \return Whether the command given exists, including in the path |
929 | - \brief This function is used to find out if something exists for |
930 | - the check command. It can look in the path if required. |
931 | - \param command The command or file that should be looked for |
932 | - |
933 | - The first thing that this function does is check to see if the |
934 | - incoming file name has a directory delimiter in it. This would |
935 | - mean that it wants to control the directories, and should be |
936 | - used directly. |
937 | - |
938 | - If not, the path is used. Each entry in the path is stepped through, |
939 | - attached to the string, and then tested. If the file is found |
940 | - then a TRUE is returned. If we get all the way through the path |
941 | - then a FALSE is returned, the command could not be found. |
942 | -*/ |
943 | -bool Script::check_existence(const std::string &command) |
944 | -{ |
945 | - // Check the simple case first |
946 | - if (command.empty()) { |
947 | - return false; |
948 | - } |
949 | - |
950 | - //Don't search when it is an absolute path. */ |
951 | - if (Glib::path_is_absolute(command)) { |
952 | - if (Glib::file_test(command, Glib::FILE_TEST_EXISTS)) { |
953 | - return true; |
954 | - } else { |
955 | - return false; |
956 | - } |
957 | - } |
958 | - |
959 | - // First search in the current directory |
960 | - std::string path = G_SEARCHPATH_SEPARATOR_S; |
961 | - path.append(";"); |
962 | - // And then in the PATH environment variable. |
963 | - path.append(Glib::getenv("PATH")); |
964 | - |
965 | - std::string::size_type pos = 0; |
966 | - std::string::size_type pos2 = 0; |
967 | - while ( pos < path.size() ) { |
968 | - |
969 | - std::string localPath; |
970 | - |
971 | - pos2 = path.find(G_SEARCHPATH_SEPARATOR, pos); |
972 | - if (pos2 == path.npos) { |
973 | - localPath = path.substr(pos); |
974 | - pos = path.size(); |
975 | - } else { |
976 | - localPath = path.substr(pos, pos2-pos); |
977 | - pos = pos2+1; |
978 | - } |
979 | - |
980 | - //printf("### %s\n", localPath.c_str()); |
981 | - std::string candidatePath = |
982 | - Glib::build_filename(localPath, command); |
983 | - |
984 | - if (Glib::file_test(candidatePath, |
985 | - Glib::FILE_TEST_EXISTS)) { |
986 | - return true; |
987 | - } |
988 | - |
989 | - } |
990 | - |
991 | - return false; |
992 | -} |
993 | - |
994 | - |
995 | - |
996 | - |
997 | - |
998 | -/** |
999 | - \return none |
1000 | - \brief This function 'loads' an extention, basically it determines |
1001 | - the full command for the extention and stores that. |
1002 | - \param module The extention to be loaded. |
1003 | - |
1004 | - The most difficult part about this function is finding the actual |
1005 | - command through all of the Reprs. Basically it is hidden down a |
1006 | - couple of layers, and so the code has to move down too. When |
1007 | - the command is actually found, it has its relative directory |
1008 | - solved. |
1009 | - |
1010 | - At that point all of the loops are exited, and there is an |
1011 | - if statement to make sure they didn't exit because of not finding |
1012 | - the command. If that's the case, the extention doesn't get loaded |
1013 | - and should error out at a higher level. |
1014 | -*/ |
1015 | - |
1016 | -bool Script::load(Inkscape::Extension::Extension *module) |
1017 | -{ |
1018 | - if (module->loaded()) { |
1019 | - return true; |
1020 | - } |
1021 | - |
1022 | - helper_extension = ""; |
1023 | - |
1024 | - /* This should probably check to find the executable... */ |
1025 | - Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr()); |
1026 | - while (child_repr != NULL) { |
1027 | - if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "script")) { |
1028 | - child_repr = sp_repr_children(child_repr); |
1029 | - while (child_repr != NULL) { |
1030 | - if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "command")) { |
1031 | - const gchar *interpretstr = child_repr->attribute("interpreter"); |
1032 | - if (interpretstr != NULL) { |
1033 | - std::string interpString = resolveInterpreterExecutable(interpretstr); |
1034 | - command.insert(command.end(), interpString); |
1035 | - } |
1036 | - command.insert(command.end(), solve_reldir(child_repr)); |
1037 | - } |
1038 | - if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "helper_extension")) { |
1039 | - helper_extension = sp_repr_children(child_repr)->content(); |
1040 | - } |
1041 | - child_repr = sp_repr_next(child_repr); |
1042 | - } |
1043 | - |
1044 | - break; |
1045 | - } |
1046 | - child_repr = sp_repr_next(child_repr); |
1047 | - } |
1048 | - |
1049 | - //g_return_val_if_fail(command.length() > 0, false); |
1050 | - |
1051 | - return true; |
1052 | -} |
1053 | - |
1054 | - |
1055 | -/** |
1056 | - \return None. |
1057 | - \brief Unload this puppy! |
1058 | - \param module Extension to be unloaded. |
1059 | - |
1060 | - This function just sets the module to unloaded. It free's the |
1061 | - command if it has been allocated. |
1062 | -*/ |
1063 | -void Script::unload(Inkscape::Extension::Extension */*module*/) |
1064 | -{ |
1065 | - command.clear(); |
1066 | - helper_extension = ""; |
1067 | -} |
1068 | - |
1069 | - |
1070 | - |
1071 | - |
1072 | -/** |
1073 | - \return Whether the check passed or not |
1074 | - \brief Check every dependency that was given to make sure we should keep this extension |
1075 | - \param module The Extension in question |
1076 | - |
1077 | -*/ |
1078 | -bool |
1079 | -Script::check(Inkscape::Extension::Extension *module) |
1080 | -{ |
1081 | - int script_count = 0; |
1082 | - Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr()); |
1083 | - while (child_repr != NULL) { |
1084 | - if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "script")) { |
1085 | - script_count++; |
1086 | - child_repr = sp_repr_children(child_repr); |
1087 | - while (child_repr != NULL) { |
1088 | - if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "check")) { |
1089 | - std::string command_text = solve_reldir(child_repr); |
1090 | - if (!command_text.empty()) { |
1091 | - /* I've got the command */ |
1092 | - bool existance = check_existence(command_text); |
1093 | - if (!existance) { |
1094 | - return false; |
1095 | - } |
1096 | - } else { |
1097 | - return false; |
1098 | - } |
1099 | - } |
1100 | - |
1101 | - if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "helper_extension")) { |
1102 | - gchar const *helper = sp_repr_children(child_repr)->content(); |
1103 | - if (Inkscape::Extension::db.get(helper) == NULL) { |
1104 | - return false; |
1105 | - } |
1106 | - } |
1107 | - |
1108 | - child_repr = sp_repr_next(child_repr); |
1109 | - } |
1110 | - |
1111 | - break; |
1112 | - } |
1113 | - child_repr = sp_repr_next(child_repr); |
1114 | - } |
1115 | - |
1116 | - if (script_count == 0) { |
1117 | - return false; |
1118 | - } |
1119 | - |
1120 | - return true; |
1121 | -} |
1122 | - |
1123 | -class ScriptDocCache : public ImplementationDocumentCache { |
1124 | - friend class Script; |
1125 | -protected: |
1126 | - std::string _filename; |
1127 | - int _tempfd; |
1128 | -public: |
1129 | - ScriptDocCache (Inkscape::UI::View::View * view); |
1130 | - ~ScriptDocCache ( ); |
1131 | -}; |
1132 | - |
1133 | -ScriptDocCache::ScriptDocCache (Inkscape::UI::View::View * view) : |
1134 | - ImplementationDocumentCache(view), |
1135 | - _filename(""), |
1136 | - _tempfd(0) |
1137 | -{ |
1138 | - try { |
1139 | - _tempfd = Inkscape::IO::file_open_tmp(_filename, "ink_ext_XXXXXX.svg"); |
1140 | - } catch (...) { |
1141 | - /// \todo Popup dialog here |
1142 | - return; |
1143 | - } |
1144 | - |
1145 | - SPDesktop *desktop = (SPDesktop *) view; |
1146 | - sp_namedview_document_from_window(desktop); |
1147 | - |
1148 | - Inkscape::Extension::save( |
1149 | - Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE), |
1150 | - view->doc(), _filename.c_str(), false, false, false, Inkscape::Extension::FILE_SAVE_METHOD_TEMPORARY); |
1151 | - |
1152 | - return; |
1153 | -} |
1154 | - |
1155 | -ScriptDocCache::~ScriptDocCache ( ) |
1156 | -{ |
1157 | - close(_tempfd); |
1158 | - unlink(_filename.c_str()); |
1159 | -} |
1160 | - |
1161 | -ImplementationDocumentCache *Script::newDocCache( Inkscape::Extension::Extension * /*ext*/, Inkscape::UI::View::View * view ) { |
1162 | - return new ScriptDocCache(view); |
1163 | -} |
1164 | - |
1165 | - |
1166 | -/** |
1167 | - \return A dialog for preferences |
1168 | - \brief A stub funtion right now |
1169 | - \param module Module who's preferences need getting |
1170 | - \param filename Hey, the file you're getting might be important |
1171 | - |
1172 | - This function should really do something, right now it doesn't. |
1173 | -*/ |
1174 | -Gtk::Widget *Script::prefs_input(Inkscape::Extension::Input *module, |
1175 | - const gchar */*filename*/) |
1176 | -{ |
1177 | - return module->autogui(NULL, NULL); |
1178 | -} |
1179 | - |
1180 | - |
1181 | - |
1182 | -/** |
1183 | - \return A dialog for preferences |
1184 | - \brief A stub funtion right now |
1185 | - \param module Module whose preferences need getting |
1186 | - |
1187 | - This function should really do something, right now it doesn't. |
1188 | -*/ |
1189 | -Gtk::Widget *Script::prefs_output(Inkscape::Extension::Output *module) |
1190 | -{ |
1191 | - return module->autogui(NULL, NULL); |
1192 | -} |
1193 | - |
1194 | -/** |
1195 | - \return A new document that has been opened |
1196 | - \brief This function uses a filename that is put in, and calls |
1197 | - the extension's command to create an SVG file which is |
1198 | - returned. |
1199 | - \param module Extension to use. |
1200 | - \param filename File to open. |
1201 | - |
1202 | - First things first, this function needs a temporary file name. To |
1203 | - create on of those the function g_file_open_tmp is used with |
1204 | - the header of ink_ext_. |
1205 | - |
1206 | - The extension is then executed using the 'execute' function |
1207 | - with the filname coming in, and the temporary filename. After |
1208 | - That executing, the SVG should be in the temporary file. |
1209 | - |
1210 | - Finally, the temporary file is opened using the SVG input module and |
1211 | - a document is returned. That document has its filename set to |
1212 | - the incoming filename (so that it's not the temporary filename). |
1213 | - That document is then returned from this function. |
1214 | -*/ |
1215 | -SPDocument *Script::open(Inkscape::Extension::Input *module, |
1216 | - const gchar *filenameArg) |
1217 | -{ |
1218 | - std::list<std::string> params; |
1219 | - module->paramListString(params); |
1220 | - |
1221 | - std::string tempfilename_out; |
1222 | - int tempfd_out = 0; |
1223 | - try { |
1224 | - tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX.svg"); |
1225 | - } catch (...) { |
1226 | - /// \todo Popup dialog here |
1227 | - return NULL; |
1228 | - } |
1229 | - |
1230 | - std::string lfilename = Glib::filename_from_utf8(filenameArg); |
1231 | - |
1232 | - file_listener fileout; |
1233 | - int data_read = execute(command, params, lfilename, fileout); |
1234 | - fileout.toFile(tempfilename_out); |
1235 | - |
1236 | - SPDocument * mydoc = NULL; |
1237 | - if (data_read > 10) { |
1238 | - if (helper_extension.size()==0) { |
1239 | - mydoc = Inkscape::Extension::open( |
1240 | - Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), |
1241 | - tempfilename_out.c_str()); |
1242 | - } else { |
1243 | - mydoc = Inkscape::Extension::open( |
1244 | - Inkscape::Extension::db.get(helper_extension.c_str()), |
1245 | - tempfilename_out.c_str()); |
1246 | - } |
1247 | - } // data_read |
1248 | - |
1249 | - if (mydoc != NULL) { |
1250 | - g_free(mydoc->base); |
1251 | - mydoc->base = NULL; |
1252 | - sp_document_change_uri_and_hrefs(mydoc, filenameArg); |
1253 | - } |
1254 | - |
1255 | - // make sure we don't leak file descriptors from g_file_open_tmp |
1256 | - close(tempfd_out); |
1257 | - |
1258 | - unlink(tempfilename_out.c_str()); |
1259 | - |
1260 | - return mydoc; |
1261 | -} // open |
1262 | - |
1263 | - |
1264 | - |
1265 | -/** |
1266 | - \return none |
1267 | - \brief This function uses an extention to save a document. It first |
1268 | - creates an SVG file of the document, and then runs it through |
1269 | - the script. |
1270 | - \param module Extention to be used |
1271 | - \param doc Document to be saved |
1272 | - \param filename The name to save the final file as |
1273 | - \return false in case of any failure writing the file, otherwise true |
1274 | - |
1275 | - Well, at some point people need to save - it is really what makes |
1276 | - the entire application useful. And, it is possible that someone |
1277 | - would want to use an extetion for this, so we need a function to |
1278 | - do that eh? |
1279 | - |
1280 | - First things first, the document is saved to a temporary file that |
1281 | - is an SVG file. To get the temporary filename g_file_open_tmp is used with |
1282 | - ink_ext_ as a prefix. Don't worry, this file gets deleted at the |
1283 | - end of the function. |
1284 | - |
1285 | - After we have the SVG file, then extention_execute is called with |
1286 | - the temporary file name and the final output filename. This should |
1287 | - put the output of the script into the final output file. We then |
1288 | - delete the temporary file. |
1289 | -*/ |
1290 | -void Script::save(Inkscape::Extension::Output *module, |
1291 | - SPDocument *doc, |
1292 | - const gchar *filenameArg) |
1293 | -{ |
1294 | - std::list<std::string> params; |
1295 | - module->paramListString(params); |
1296 | - |
1297 | - std::string tempfilename_in; |
1298 | - int tempfd_in = 0; |
1299 | - try { |
1300 | - tempfd_in = Inkscape::IO::file_open_tmp(tempfilename_in, "ink_ext_XXXXXX.svg"); |
1301 | - } catch (...) { |
1302 | - /// \todo Popup dialog here |
1303 | - throw Inkscape::Extension::Output::save_failed(); |
1304 | - } |
1305 | - |
1306 | - if (helper_extension.size() == 0) { |
1307 | - Inkscape::Extension::save( |
1308 | - Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE), |
1309 | - doc, tempfilename_in.c_str(), false, false, false, |
1310 | - Inkscape::Extension::FILE_SAVE_METHOD_TEMPORARY); |
1311 | - } else { |
1312 | - Inkscape::Extension::save( |
1313 | - Inkscape::Extension::db.get(helper_extension.c_str()), |
1314 | - doc, tempfilename_in.c_str(), false, false, false, |
1315 | - Inkscape::Extension::FILE_SAVE_METHOD_TEMPORARY); |
1316 | - } |
1317 | - |
1318 | - |
1319 | - file_listener fileout; |
1320 | - execute(command, params, tempfilename_in, fileout); |
1321 | - |
1322 | - std::string lfilename = Glib::filename_from_utf8(filenameArg); |
1323 | - bool success = fileout.toFile(lfilename); |
1324 | - |
1325 | - // make sure we don't leak file descriptors from g_file_open_tmp |
1326 | - close(tempfd_in); |
1327 | - // FIXME: convert to utf8 (from "filename encoding") and unlink_utf8name |
1328 | - unlink(tempfilename_in.c_str()); |
1329 | - |
1330 | - if (success == false) { |
1331 | - throw Inkscape::Extension::Output::save_failed(); |
1332 | - } |
1333 | - |
1334 | - return; |
1335 | -} |
1336 | - |
1337 | - |
1338 | - |
1339 | -/** |
1340 | - \return none |
1341 | - \brief This function uses an extention as a effect on a document. |
1342 | - \param module Extention to effect with. |
1343 | - \param doc Document to run through the effect. |
1344 | - |
1345 | - This function is a little bit trickier than the previous two. It |
1346 | - needs two temporary files to get it's work done. Both of these |
1347 | - files have random names created for them using the g_file_open_temp function |
1348 | - with the ink_ext_ prefix in the temporary directory. Like the other |
1349 | - functions, the temporary files are deleted at the end. |
1350 | - |
1351 | - To save/load the two temporary documents (both are SVG) the internal |
1352 | - modules for SVG load and save are used. They are both used through |
1353 | - the module system function by passing their keys into the functions. |
1354 | - |
1355 | - The command itself is built a little bit differently than in other |
1356 | - functions because the effect support selections. So on the command |
1357 | - line a list of all the ids that are selected is included. Currently, |
1358 | - this only works for a single selected object, but there will be more. |
1359 | - The command string is filled with the data, and then after the execution |
1360 | - it is freed. |
1361 | - |
1362 | - The execute function is used at the core of this function |
1363 | - to execute the Script on the two SVG documents (actually only one |
1364 | - exists at the time, the other is created by that script). At that |
1365 | - point both should be full, and the second one is loaded. |
1366 | -*/ |
1367 | -void Script::effect(Inkscape::Extension::Effect *module, |
1368 | - Inkscape::UI::View::View *doc, |
1369 | - ImplementationDocumentCache * docCache) |
1370 | -{ |
1371 | - if (docCache == NULL) { |
1372 | - docCache = newDocCache(module, doc); |
1373 | - } |
1374 | - ScriptDocCache * dc = dynamic_cast<ScriptDocCache *>(docCache); |
1375 | - if (dc == NULL) { |
1376 | - printf("TOO BAD TO LIVE!!!"); |
1377 | - exit(1); |
1378 | - } |
1379 | - |
1380 | - SPDesktop *desktop = (SPDesktop *)doc; |
1381 | - sp_namedview_document_from_window(desktop); |
1382 | - |
1383 | - std::list<std::string> params; |
1384 | - module->paramListString(params); |
1385 | - |
1386 | - if (module->no_doc) { |
1387 | - // this is a no-doc extension, e.g. a Help menu command; |
1388 | - // just run the command without any files, ignoring errors |
1389 | - |
1390 | - Glib::ustring empty; |
1391 | - file_listener outfile; |
1392 | - execute(command, params, empty, outfile); |
1393 | - |
1394 | - return; |
1395 | - } |
1396 | - |
1397 | - std::string tempfilename_out; |
1398 | - int tempfd_out = 0; |
1399 | - try { |
1400 | - tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX.svg"); |
1401 | - } catch (...) { |
1402 | - /// \todo Popup dialog here |
1403 | - return; |
1404 | - } |
1405 | - |
1406 | - if (desktop != NULL) { |
1407 | - Inkscape::Util::GSListConstIterator<SPItem *> selected = |
1408 | - sp_desktop_selection(desktop)->itemList(); |
1409 | - while ( selected != NULL ) { |
1410 | - Glib::ustring selected_id; |
1411 | - selected_id += "--id="; |
1412 | - selected_id += (*selected)->getId(); |
1413 | - params.insert(params.begin(), selected_id); |
1414 | - ++selected; |
1415 | - } |
1416 | - } |
1417 | - |
1418 | - file_listener fileout; |
1419 | - int data_read = execute(command, params, dc->_filename, fileout); |
1420 | - fileout.toFile(tempfilename_out); |
1421 | - |
1422 | - pump_events(); |
1423 | - |
1424 | - SPDocument * mydoc = NULL; |
1425 | - if (data_read > 10) { |
1426 | - mydoc = Inkscape::Extension::open( |
1427 | - Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), |
1428 | - tempfilename_out.c_str()); |
1429 | - } // data_read |
1430 | - |
1431 | - pump_events(); |
1432 | - |
1433 | - // make sure we don't leak file descriptors from g_file_open_tmp |
1434 | - close(tempfd_out); |
1435 | - |
1436 | - g_unlink(tempfilename_out.c_str()); |
1437 | - |
1438 | - /* Do something with mydoc.... */ |
1439 | - if (mydoc) { |
1440 | - doc->doc()->emitReconstructionStart(); |
1441 | - copy_doc(doc->doc()->rroot, mydoc->rroot); |
1442 | - doc->doc()->emitReconstructionFinish(); |
1443 | - SPObject *layer = NULL; |
1444 | - |
1445 | - // Getting the named view from the document generated by the extension |
1446 | - SPNamedView *nv = sp_document_namedview(mydoc, NULL); |
1447 | - |
1448 | - //Check if it has a default layer set up |
1449 | - if ( nv != NULL){ |
1450 | - if( nv->default_layer_id != 0 ) { |
1451 | - SPDocument *document = desktop->doc(); |
1452 | - //If so, get that layer |
1453 | - layer = document->getObjectById(g_quark_to_string(nv->default_layer_id)); |
1454 | - } |
1455 | - } |
1456 | - |
1457 | - sp_namedview_update_layers_from_document(desktop); |
1458 | - //If that layer exists, |
1459 | - if (layer) { |
1460 | - //set the current layer |
1461 | - desktop->setCurrentLayer(layer); |
1462 | - } |
1463 | - mydoc->release(); |
1464 | - } |
1465 | - |
1466 | - return; |
1467 | -} |
1468 | - |
1469 | - |
1470 | - |
1471 | -/** |
1472 | - \brief A function to take all the svg elements from one document |
1473 | - and put them in another. |
1474 | - \param oldroot The root node of the document to be replaced |
1475 | - \param newroot The root node of the document to replace it with |
1476 | - |
1477 | - This function first deletes all of the data in the old document. It |
1478 | - does this by creating a list of what needs to be deleted, and then |
1479 | - goes through the list. This two pass approach removes issues with |
1480 | - the list being change while parsing through it. Lots of nasty bugs. |
1481 | - |
1482 | - Then, it goes through the new document, duplicating all of the |
1483 | - elements and putting them into the old document. The copy |
1484 | - is then complete. |
1485 | -*/ |
1486 | -void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) |
1487 | -{ |
1488 | - std::vector<Inkscape::XML::Node *> delete_list; |
1489 | - Inkscape::XML::Node * oldroot_namedview = NULL; |
1490 | - |
1491 | - for (Inkscape::XML::Node * child = oldroot->firstChild(); |
1492 | - child != NULL; |
1493 | - child = child->next()) { |
1494 | - if (!strcmp("sodipodi:namedview", child->name())) { |
1495 | - oldroot_namedview = child; |
1496 | - for (Inkscape::XML::Node * oldroot_namedview_child = child->firstChild(); |
1497 | - oldroot_namedview_child != NULL; |
1498 | - oldroot_namedview_child = oldroot_namedview_child->next()) { |
1499 | - delete_list.push_back(oldroot_namedview_child); |
1500 | - } |
1501 | - } else { |
1502 | - delete_list.push_back(child); |
1503 | - } |
1504 | - } |
1505 | - for (unsigned int i = 0; i < delete_list.size(); i++) { |
1506 | - sp_repr_unparent(delete_list[i]); |
1507 | - } |
1508 | - |
1509 | - for (Inkscape::XML::Node * child = newroot->firstChild(); |
1510 | - child != NULL; |
1511 | - child = child->next()) { |
1512 | - if (!strcmp("sodipodi:namedview", child->name())) { |
1513 | - if (oldroot_namedview != NULL) { |
1514 | - for (Inkscape::XML::Node * newroot_namedview_child = child->firstChild(); |
1515 | - newroot_namedview_child != NULL; |
1516 | - newroot_namedview_child = newroot_namedview_child->next()) { |
1517 | - oldroot_namedview->appendChild(newroot_namedview_child->duplicate(oldroot->document())); |
1518 | - } |
1519 | - } |
1520 | - } else { |
1521 | - oldroot->appendChild(child->duplicate(oldroot->document())); |
1522 | - } |
1523 | - } |
1524 | - |
1525 | - { |
1526 | - using Inkscape::Util::List; |
1527 | - using Inkscape::XML::AttributeRecord; |
1528 | - std::vector<gchar const *> attribs; |
1529 | - |
1530 | - // Make a list of all attributes of the old root node. |
1531 | - for (List<AttributeRecord const> iter = oldroot->attributeList(); iter; ++iter) { |
1532 | - attribs.push_back(g_quark_to_string(iter->key)); |
1533 | - } |
1534 | - |
1535 | - // Delete the attributes of the old root nodes. |
1536 | - for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); it++) { |
1537 | - oldroot->setAttribute(*it, NULL); |
1538 | - } |
1539 | - |
1540 | - // Set the new attributes. |
1541 | - for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) { |
1542 | - gchar const *name = g_quark_to_string(iter->key); |
1543 | - oldroot->setAttribute(name, newroot->attribute(name)); |
1544 | - } |
1545 | - } |
1546 | - |
1547 | - /** \todo Restore correct layer */ |
1548 | - /** \todo Restore correct selection */ |
1549 | -} |
1550 | - |
1551 | -/** \brief This function checks the stderr file, and if it has data, |
1552 | - shows it in a warning dialog to the user |
1553 | - \param filename Filename of the stderr file |
1554 | -*/ |
1555 | -void Script::checkStderr (const Glib::ustring &data, |
1556 | - Gtk::MessageType type, |
1557 | - const Glib::ustring &message) |
1558 | -{ |
1559 | - Gtk::MessageDialog warning(message, false, type, Gtk::BUTTONS_OK, true); |
1560 | - warning.set_resizable(true); |
1561 | - GtkWidget *dlg = GTK_WIDGET(warning.gobj()); |
1562 | - sp_transientize(dlg); |
1563 | - |
1564 | - Gtk::VBox * vbox = warning.get_vbox(); |
1565 | - |
1566 | - /* Gtk::TextView * textview = new Gtk::TextView(Gtk::TextBuffer::create()); */ |
1567 | - Gtk::TextView * textview = new Gtk::TextView(); |
1568 | - textview->set_editable(false); |
1569 | - textview->set_wrap_mode(Gtk::WRAP_WORD); |
1570 | - textview->show(); |
1571 | - |
1572 | - // Remove the last character |
1573 | - char *errormsg = (char*) data.c_str(); |
1574 | - while (*errormsg != '\0') errormsg++; |
1575 | - errormsg -= 1; |
1576 | - *errormsg = '\0'; |
1577 | - |
1578 | - textview->get_buffer()->set_text(_(data.c_str())); |
1579 | - |
1580 | - Gtk::ScrolledWindow * scrollwindow = new Gtk::ScrolledWindow(); |
1581 | - scrollwindow->add(*textview); |
1582 | - scrollwindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); |
1583 | - scrollwindow->set_shadow_type(Gtk::SHADOW_IN); |
1584 | - scrollwindow->show(); |
1585 | - scrollwindow->set_size_request(0, 60); |
1586 | - |
1587 | - vbox->pack_start(*scrollwindow, true, true, 5 /* fix these */); |
1588 | - |
1589 | - warning.run(); |
1590 | - |
1591 | - return; |
1592 | -} |
1593 | - |
1594 | -bool Script::cancelProcessing (void) { |
1595 | - _canceled = true; |
1596 | - _main_loop->quit(); |
1597 | - Glib::spawn_close_pid(_pid); |
1598 | - |
1599 | - return true; |
1600 | -} |
1601 | - |
1602 | - |
1603 | -/** \brief This is the core of the extension file as it actually does |
1604 | - the execution of the extension. |
1605 | - \param in_command The command to be executed |
1606 | - \param filein Filename coming in |
1607 | - \param fileout Filename of the out file |
1608 | - \return Number of bytes that were read into the output file. |
1609 | - |
1610 | - The first thing that this function does is build the command to be |
1611 | - executed. This consists of the first string (in_command) and then |
1612 | - the filename for input (filein). This file is put on the command |
1613 | - line. |
1614 | - |
1615 | - The next thing is that this function does is open a pipe to the |
1616 | - command and get the file handle in the ppipe variable. It then |
1617 | - opens the output file with the output file handle. Both of these |
1618 | - operations are checked extensively for errors. |
1619 | - |
1620 | - After both are opened, then the data is copied from the output |
1621 | - of the pipe into the file out using fread and fwrite. These two |
1622 | - functions are used because of their primitive nature they make |
1623 | - no assumptions about the data. A buffer is used in the transfer, |
1624 | - but the output of fread is stored so the exact number of bytes |
1625 | - is handled gracefully. |
1626 | - |
1627 | - At the very end (after the data has been copied) both of the files |
1628 | - are closed, and we return to what we were doing. |
1629 | -*/ |
1630 | -int Script::execute (const std::list<std::string> &in_command, |
1631 | - const std::list<std::string> &in_params, |
1632 | - const Glib::ustring &filein, |
1633 | - file_listener &fileout) |
1634 | -{ |
1635 | - g_return_val_if_fail(!in_command.empty(), 0); |
1636 | - // printf("Executing\n"); |
1637 | - |
1638 | - std::vector<std::string> argv; |
1639 | - |
1640 | - bool interpreted = (in_command.size() == 2); |
1641 | - std::string program = in_command.front(); |
1642 | - std::string script = interpreted ? in_command.back() : ""; |
1643 | - std::string working_directory = ""; |
1644 | - |
1645 | - // Use Glib::find_program_in_path instead of the equivalent |
1646 | - // Glib::spawn_* functionality, because _wspawnp is broken on Windows: |
1647 | - // it doesn't work when PATH contains Unicode directories |
1648 | - if (!Glib::path_is_absolute(program)) { |
1649 | - program = Glib::find_program_in_path(program); |
1650 | - } |
1651 | - argv.push_back(program); |
1652 | - |
1653 | - if (interpreted) { |
1654 | - // On Windows, Python garbles Unicode command line parameters |
1655 | - // in an useless way. This means extensions fail when Inkscape |
1656 | - // is run from an Unicode directory. |
1657 | - // As a workaround, we set the working directory to the one |
1658 | - // containing the script. |
1659 | - working_directory = Glib::path_get_dirname(script); |
1660 | - script = Glib::path_get_basename(script); |
1661 | - #ifdef G_OS_WIN32 |
1662 | - // ANNOYING: glibmm does not wrap g_win32_locale_filename_from_utf8 |
1663 | - gchar *workdir_s = g_win32_locale_filename_from_utf8(working_directory.data()); |
1664 | - working_directory = workdir_s; |
1665 | - g_free(workdir_s); |
1666 | - #endif |
1667 | - |
1668 | - argv.push_back(script); |
1669 | - } |
1670 | - |
1671 | - // assemble the rest of argv |
1672 | - std::copy(in_params.begin(), in_params.end(), std::back_inserter(argv)); |
1673 | - if (!filein.empty()) { |
1674 | - argv.push_back(filein); |
1675 | - } |
1676 | - |
1677 | - int stdout_pipe, stderr_pipe; |
1678 | - |
1679 | - try { |
1680 | - Glib::spawn_async_with_pipes(working_directory, // working directory |
1681 | - argv, // arg v |
1682 | - static_cast<Glib::SpawnFlags>(0), // no flags |
1683 | - sigc::slot<void>(), |
1684 | - &_pid, // Pid |
1685 | - NULL, // STDIN |
1686 | - &stdout_pipe, // STDOUT |
1687 | - &stderr_pipe); // STDERR |
1688 | - } catch (Glib::Error e) { |
1689 | - printf("Can't Spawn!!! spawn returns: %s\n", e.what().data()); |
1690 | - return 0; |
1691 | - } |
1692 | - |
1693 | - _main_loop = Glib::MainLoop::create(false); |
1694 | - |
1695 | - file_listener fileerr; |
1696 | - fileout.init(stdout_pipe, _main_loop); |
1697 | - fileerr.init(stderr_pipe, _main_loop); |
1698 | - |
1699 | - _canceled = false; |
1700 | - _main_loop->run(); |
1701 | - |
1702 | - // Ensure all the data is out of the pipe |
1703 | - while (!fileout.isDead()) { |
1704 | - fileout.read(Glib::IO_IN); |
1705 | - } |
1706 | - while (!fileerr.isDead()) { |
1707 | - fileerr.read(Glib::IO_IN); |
1708 | - } |
1709 | - |
1710 | - if (_canceled) { |
1711 | - // std::cout << "Script Canceled" << std::endl; |
1712 | - return 0; |
1713 | - } |
1714 | - |
1715 | - Glib::ustring stderr_data = fileerr.string(); |
1716 | - if (stderr_data.length() != 0 && |
1717 | - Inkscape::NSApplication::Application::getUseGui() |
1718 | - ) { |
1719 | - checkStderr(stderr_data, Gtk::MESSAGE_INFO, |
1720 | - _("Inkscape has received additional data from the script executed. " |
1721 | - "The script did not return an error, but this may indicate the results will not be as expected.")); |
1722 | - } |
1723 | - |
1724 | - Glib::ustring stdout_data = fileout.string(); |
1725 | - if (stdout_data.length() == 0) { |
1726 | - return 0; |
1727 | - } |
1728 | - |
1729 | - // std::cout << "Finishing Execution." << std::endl; |
1730 | - return stdout_data.length(); |
1731 | -} |
1732 | - |
1733 | - |
1734 | - |
1735 | - |
1736 | -} // namespace Implementation |
1737 | -} // namespace Extension |
1738 | -} // namespace Inkscape |
1739 | - |
1740 | -/* |
1741 | - Local Variables: |
1742 | - mode:c++ |
1743 | - c-file-style:"stroustrup" |
1744 | - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
1745 | - indent-tabs-mode:nil |
1746 | - fill-column:99 |
1747 | - End: |
1748 | -*/ |
1749 | -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : |
1750 | |
1751 | === removed directory '.pc/0004-Fix_FTBFS_on_gcc-4.8.patch' |
1752 | === removed directory '.pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src' |
1753 | === removed file '.pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/connector-context.cpp' |
1754 | --- .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/connector-context.cpp 2013-07-02 17:25:52 +0000 |
1755 | +++ .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/connector-context.cpp 1970-01-01 00:00:00 +0000 |
1756 | @@ -1,2041 +0,0 @@ |
1757 | -/* |
1758 | - * Connector creation tool |
1759 | - * |
1760 | - * Authors: |
1761 | - * Michael Wybrow <mjwybrow@users.sourceforge.net> |
1762 | - * |
1763 | - * Copyright (C) 2005-2008 Michael Wybrow |
1764 | - * Copyright (C) 2009 Monash University |
1765 | - * |
1766 | - * Released under GNU GPL, read the file 'COPYING' for more information |
1767 | - * |
1768 | - * TODO: |
1769 | - * o Show a visual indicator for objects with the 'avoid' property set. |
1770 | - * o Allow user to change a object between a path and connector through |
1771 | - * the interface. |
1772 | - * o Create an interface for setting markers (arrow heads). |
1773 | - * o Better distinguish between paths and connectors to prevent problems |
1774 | - * in the node tool and paths accidentally being turned into connectors |
1775 | - * in the connector tool. Perhaps have a way to convert between. |
1776 | - * o Only call libavoid's updateEndPoint as required. Currently we do it |
1777 | - * for both endpoints, even if only one is moving. |
1778 | - * o Allow user-placeable connection points. |
1779 | - * o Deal sanely with connectors with both endpoints attached to the |
1780 | - * same connection point, and drawing of connectors attaching |
1781 | - * overlapping shapes (currently tries to adjust connector to be |
1782 | - * outside both bounding boxes). |
1783 | - * o Fix many special cases related to connectors updating, |
1784 | - * e.g., copying a couple of shapes and a connector that are |
1785 | - * attached to each other. |
1786 | - * e.g., detach connector when it is moved or transformed in |
1787 | - * one of the other contexts. |
1788 | - * o Cope with shapes whose ids change when they have attached |
1789 | - * connectors. |
1790 | - * o During dragging motion, gobble up to and use the final motion event. |
1791 | - * Gobbling away all duplicates after the current can occasionally result |
1792 | - * in the path lagging behind the mouse cursor if it is no longer being |
1793 | - * dragged. |
1794 | - * o Fix up libavoid's representation after undo actions. It doesn't see |
1795 | - * any transform signals and hence doesn't know shapes have moved back to |
1796 | - * there earlier positions. |
1797 | - * o Decide whether drawing/editing mode should be an Inkscape preference |
1798 | - * or the connector tool should always start in drawing mode. |
1799 | - * o Correct the problem with switching to the select tool when pressing |
1800 | - * space bar (there are moments when it refuses to do so). |
1801 | - * |
1802 | - * ---------------------------------------------------------------------------- |
1803 | - * |
1804 | - * mjwybrow's observations on acracan's Summer of Code connector work: |
1805 | - * |
1806 | - * - GUI comments: |
1807 | - * |
1808 | - * - Buttons for adding and removing user-specified connection |
1809 | - * points should probably have "+" and "-" symbols on them so they |
1810 | - * are consistent with the similar buttons for the node tool. |
1811 | - * - Controls on the connector tool be should be reordered logically, |
1812 | - * possibly as follows: |
1813 | - * |
1814 | - * *Connector*: [Polyline-radio-button] [Orthgonal-radio-button] |
1815 | - * [Curvature-control] | *Shape*: [Avoid-button] [Dont-avoid-button] |
1816 | - * [Spacing-control] | *Connection pts*: [Edit-mode] [Add-pt] [Rm-pt] |
1817 | - * |
1818 | - * I think that the network layout controls be moved to the |
1819 | - * Align and Distribute dialog (there is already the layout button |
1820 | - * there, but no options are exposed). |
1821 | - * |
1822 | - * I think that the style change between polyline and orthogonal |
1823 | - * would be much clearer with two buttons (radio behaviour -- just |
1824 | - * one is true). |
1825 | - * |
1826 | - * The other tools show a label change from "New:" to "Change:" |
1827 | - * depending on whether an object is selected. We could consider |
1828 | - * this but there may not be space. |
1829 | - * |
1830 | - * The Add-pt and Rm-pt buttons should be greyed out (inactive) if |
1831 | - * we are not in connection point editing mode. And probably also |
1832 | - * if there is no shape selected, i.e. at the times they have no |
1833 | - * effect when clicked. |
1834 | - * |
1835 | - * Likewise for the avoid/ignore shapes buttons. These should be |
1836 | - * inactive when a shape is not selected in the connector context. |
1837 | - * |
1838 | - * - When creating/editing connection points: |
1839 | - * |
1840 | - * - Strange things can happen if you have connectors selected, or |
1841 | - * try rerouting connectors by dragging their endpoints when in |
1842 | - * connection point editing mode. |
1843 | - * |
1844 | - * - Possibly the selected shape's connection points should always |
1845 | - * be shown (i.e., have knots) when in editing mode. |
1846 | - * |
1847 | - * - It is a little strange to be able to place connection points |
1848 | - * competely outside shapes. Especially when you later can't draw |
1849 | - * connectors to them since the knots are only visible when you |
1850 | - * are over the shape. I think that you should only be able to |
1851 | - * place connection points inside or on the boundary of the shape |
1852 | - * itself. |
1853 | - * |
1854 | - * - The intended ability to place a new point at the current cursor |
1855 | - * position by pressing RETURN does not seem to work. |
1856 | - * |
1857 | - * - The Status bar tooltip should change to reflect editing mode |
1858 | - * and tell the user about RETURN and how to use the tool. |
1859 | - * |
1860 | - * - Connection points general: |
1861 | - * |
1862 | - * - Connection points that were inside the shape can end up outside |
1863 | - * after a rotation is applied to the shape in the select tool. |
1864 | - * It doesn't seem like the correct transform is being applied to |
1865 | - * these, or it is being applied at the wrong time. I'd expect |
1866 | - * connection points to rotate with the shape, and stay at the |
1867 | - * same position "on the shape" |
1868 | - * |
1869 | - * - I was able to make the connectors attached to a shape fall off |
1870 | - * the shape after scaling it. Not sure the exact cause, but may |
1871 | - * require more investigation/debugging. |
1872 | - * |
1873 | - * - The user-defined connection points should be either absolute |
1874 | - * (as the current ones are) or defined as a percentage of the |
1875 | - * shape. These would be based on a toggle setting on the |
1876 | - * toolbar, and they would be placed in exactly the same way by |
1877 | - * the user. The only difference would be that they would be |
1878 | - * store as percentage positions in the SVG connection-points |
1879 | - * property and that they would update/move automatically if the |
1880 | - * object was resized or scaled. |
1881 | - * |
1882 | - * - Thinking more, I think you always want to store and think about |
1883 | - * the positions of connection points to be pre-transform, but |
1884 | - * obviously the shape transform is applied to them. That way, |
1885 | - * they will rotate and scale automatically with the shape, when |
1886 | - * the shape transform is altered. The Percentage version would |
1887 | - * compute their position from the pre-transform dimensions and |
1888 | - * then have the transform applied to them, for example. |
1889 | - * |
1890 | - * - The connection points in the test_connection_points.svg file |
1891 | - * seem to follow the shape when it is moved, but connection |
1892 | - * points I add to new shapes, do not follow the shape, either |
1893 | - * when the shape is just moved or transformed. There is |
1894 | - * something wrong here. What exactly should the behaviour be |
1895 | - * currently? |
1896 | - * |
1897 | - * - I see that connection points are specified at absolute canvas |
1898 | - * positions. I really think that they should be specified in |
1899 | - * shape coordinated relative to the shapes. There may be |
1900 | - * transforms applied to layers and the canvas which would make |
1901 | - * specifying them quite difficult. I'd expect a position of 0, 0 |
1902 | - * to be on the shape in question or very close to it, for example. |
1903 | - * |
1904 | - */ |
1905 | - |
1906 | - |
1907 | - |
1908 | -#include <gdk/gdkkeysyms.h> |
1909 | -#include <string> |
1910 | -#include <cstring> |
1911 | - |
1912 | -#include "connector-context.h" |
1913 | -#include "pixmaps/cursor-connector.xpm" |
1914 | -#include "pixmaps/cursor-node.xpm" |
1915 | -//#include "pixmaps/cursor-node-m.xpm" |
1916 | -//#include "pixmaps/cursor-node-d.xpm" |
1917 | -#include "xml/node-event-vector.h" |
1918 | -#include "xml/repr.h" |
1919 | -#include "svg/svg.h" |
1920 | -#include "desktop.h" |
1921 | -#include "desktop-style.h" |
1922 | -#include "desktop-handles.h" |
1923 | -#include "document.h" |
1924 | -#include "message-context.h" |
1925 | -#include "message-stack.h" |
1926 | -#include "selection.h" |
1927 | -#include "inkscape.h" |
1928 | -#include "preferences.h" |
1929 | -#include "sp-path.h" |
1930 | -#include "display/canvas-bpath.h" |
1931 | -#include "display/sodipodi-ctrl.h" |
1932 | -#include <glibmm/i18n.h> |
1933 | -#include <glibmm/stringutils.h> |
1934 | -#include "snap.h" |
1935 | -#include "knot.h" |
1936 | -#include "sp-conn-end.h" |
1937 | -#include "sp-conn-end-pair.h" |
1938 | -#include "conn-avoid-ref.h" |
1939 | -#include "libavoid/vertices.h" |
1940 | -#include "libavoid/router.h" |
1941 | -#include "context-fns.h" |
1942 | -#include "sp-namedview.h" |
1943 | -#include "sp-text.h" |
1944 | -#include "sp-flowtext.h" |
1945 | -#include "display/curve.h" |
1946 | - |
1947 | -static void sp_connector_context_class_init(SPConnectorContextClass *klass); |
1948 | -static void sp_connector_context_init(SPConnectorContext *conn_context); |
1949 | -static void sp_connector_context_dispose(GObject *object); |
1950 | - |
1951 | -static void sp_connector_context_setup(SPEventContext *ec); |
1952 | -static void sp_connector_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val); |
1953 | -static void sp_connector_context_finish(SPEventContext *ec); |
1954 | -static gint sp_connector_context_root_handler(SPEventContext *ec, GdkEvent *event); |
1955 | -static gint sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event); |
1956 | - |
1957 | -// Stuff borrowed from DrawContext |
1958 | -static void spcc_connector_set_initial_point(SPConnectorContext *cc, Geom::Point const p); |
1959 | -static void spcc_connector_set_subsequent_point(SPConnectorContext *cc, Geom::Point const p); |
1960 | -static void spcc_connector_finish_segment(SPConnectorContext *cc, Geom::Point p); |
1961 | -static void spcc_reset_colors(SPConnectorContext *cc); |
1962 | -static void spcc_connector_finish(SPConnectorContext *cc); |
1963 | -static void spcc_concat_colors_and_flush(SPConnectorContext *cc); |
1964 | -static void spcc_flush_white(SPConnectorContext *cc, SPCurve *gc); |
1965 | - |
1966 | -// Context event handlers |
1967 | -static gint connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const &bevent); |
1968 | -static gint connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion const &mevent); |
1969 | -static gint connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton const &revent); |
1970 | -static gint connector_handle_key_press(SPConnectorContext *const cc, guint const keyval); |
1971 | - |
1972 | -static void cc_active_shape_add_knot(SPDesktop* desktop, SPItem* item, ConnectionPointMap &cphandles, ConnectionPoint& cp); |
1973 | -static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item); |
1974 | -static void cc_clear_active_shape(SPConnectorContext *cc); |
1975 | -static void cc_set_active_conn(SPConnectorContext *cc, SPItem *item); |
1976 | -static void cc_clear_active_conn(SPConnectorContext *cc); |
1977 | -static bool conn_pt_handle_test(SPConnectorContext *cc, Geom::Point& p, gchar **href, gchar **cpid); |
1978 | -static void cc_select_handle(SPKnot* knot); |
1979 | -static void cc_deselect_handle(SPKnot* knot); |
1980 | -static bool cc_item_is_shape(SPItem *item); |
1981 | -static void cc_selection_changed(Inkscape::Selection *selection, gpointer data); |
1982 | -static void cc_connector_rerouting_finish(SPConnectorContext *const cc, |
1983 | - Geom::Point *const p); |
1984 | - |
1985 | -static void shape_event_attr_deleted(Inkscape::XML::Node *repr, |
1986 | - Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data); |
1987 | -static void shape_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, |
1988 | - gchar const *old_value, gchar const *new_value, bool is_interactive, |
1989 | - gpointer data); |
1990 | - |
1991 | - |
1992 | -static char* cc_knot_tips[] = { _("<b>Connection point</b>: click or drag to create a new connector"), |
1993 | - _("<b>Connection point</b>: click to select, drag to move") }; |
1994 | - |
1995 | -/*static Geom::Point connector_drag_origin_w(0, 0); |
1996 | -static bool connector_within_tolerance = false;*/ |
1997 | -static SPEventContextClass *parent_class; |
1998 | - |
1999 | - |
2000 | -static Inkscape::XML::NodeEventVector shape_repr_events = { |
2001 | - NULL, /* child_added */ |
2002 | - NULL, /* child_added */ |
2003 | - shape_event_attr_changed, |
2004 | - NULL, /* content_changed */ |
2005 | - NULL /* order_changed */ |
2006 | -}; |
2007 | - |
2008 | -static Inkscape::XML::NodeEventVector layer_repr_events = { |
2009 | - NULL, /* child_added */ |
2010 | - shape_event_attr_deleted, |
2011 | - NULL, /* child_added */ |
2012 | - NULL, /* content_changed */ |
2013 | - NULL /* order_changed */ |
2014 | -}; |
2015 | - |
2016 | - |
2017 | -GType |
2018 | -sp_connector_context_get_type(void) |
2019 | -{ |
2020 | - static GType type = 0; |
2021 | - if (!type) { |
2022 | - GTypeInfo info = { |
2023 | - sizeof(SPConnectorContextClass), |
2024 | - NULL, NULL, |
2025 | - (GClassInitFunc) sp_connector_context_class_init, |
2026 | - NULL, NULL, |
2027 | - sizeof(SPConnectorContext), |
2028 | - 4, |
2029 | - (GInstanceInitFunc) sp_connector_context_init, |
2030 | - NULL, /* value_table */ |
2031 | - }; |
2032 | - type = g_type_register_static(SP_TYPE_EVENT_CONTEXT, "SPConnectorContext", &info, (GTypeFlags)0); |
2033 | - } |
2034 | - return type; |
2035 | -} |
2036 | - |
2037 | -static void |
2038 | -sp_connector_context_class_init(SPConnectorContextClass *klass) |
2039 | -{ |
2040 | - GObjectClass *object_class; |
2041 | - SPEventContextClass *event_context_class; |
2042 | - |
2043 | - object_class = (GObjectClass *) klass; |
2044 | - event_context_class = (SPEventContextClass *) klass; |
2045 | - |
2046 | - parent_class = (SPEventContextClass*)g_type_class_peek_parent(klass); |
2047 | - |
2048 | - object_class->dispose = sp_connector_context_dispose; |
2049 | - |
2050 | - event_context_class->setup = sp_connector_context_setup; |
2051 | - event_context_class->set = sp_connector_context_set; |
2052 | - event_context_class->finish = sp_connector_context_finish; |
2053 | - event_context_class->root_handler = sp_connector_context_root_handler; |
2054 | - event_context_class->item_handler = sp_connector_context_item_handler; |
2055 | -} |
2056 | - |
2057 | - |
2058 | -static void |
2059 | -sp_connector_context_init(SPConnectorContext *cc) |
2060 | -{ |
2061 | - SPEventContext *ec = SP_EVENT_CONTEXT(cc); |
2062 | - |
2063 | - ec->cursor_shape = cursor_connector_xpm; |
2064 | - ec->hot_x = 1; |
2065 | - ec->hot_y = 1; |
2066 | - ec->xp = 0; |
2067 | - ec->yp = 0; |
2068 | - |
2069 | - cc->mode = SP_CONNECTOR_CONTEXT_DRAWING_MODE; |
2070 | - cc->knot_tip = 0; |
2071 | - |
2072 | - cc->red_color = 0xff00007f; |
2073 | - |
2074 | - cc->newconn = NULL; |
2075 | - cc->newConnRef = NULL; |
2076 | - cc->curvature = 0.0; |
2077 | - |
2078 | - cc->sel_changed_connection = sigc::connection(); |
2079 | - |
2080 | - cc->active_shape = NULL; |
2081 | - cc->active_shape_repr = NULL; |
2082 | - cc->active_shape_layer_repr = NULL; |
2083 | - |
2084 | - cc->active_conn = NULL; |
2085 | - cc->active_conn_repr = NULL; |
2086 | - |
2087 | - cc->active_handle = NULL; |
2088 | - |
2089 | - cc->selected_handle = NULL; |
2090 | - |
2091 | - cc->clickeditem = NULL; |
2092 | - cc->clickedhandle = NULL; |
2093 | - |
2094 | - new (&cc->connpthandles) ConnectionPointMap(); |
2095 | - |
2096 | - for (int i = 0; i < 2; ++i) { |
2097 | - cc->endpt_handle[i] = NULL; |
2098 | - cc->endpt_handler_id[i] = 0; |
2099 | - } |
2100 | - cc->shref = NULL; |
2101 | - cc->scpid = NULL; |
2102 | - cc->ehref = NULL; |
2103 | - cc->ecpid = NULL; |
2104 | - cc->npoints = 0; |
2105 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2106 | -} |
2107 | - |
2108 | - |
2109 | -static void |
2110 | -sp_connector_context_dispose(GObject *object) |
2111 | -{ |
2112 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(object); |
2113 | - |
2114 | - cc->sel_changed_connection.disconnect(); |
2115 | - |
2116 | - if (!cc->connpthandles.empty()) { |
2117 | - for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); |
2118 | - it != cc->connpthandles.end(); ++it) { |
2119 | - g_object_unref(it->first); |
2120 | - } |
2121 | - cc->connpthandles.clear(); |
2122 | - } |
2123 | - cc->connpthandles.~ConnectionPointMap(); |
2124 | - for (int i = 0; i < 2; ++i) { |
2125 | - if (cc->endpt_handle[1]) { |
2126 | - g_object_unref(cc->endpt_handle[i]); |
2127 | - cc->endpt_handle[i] = NULL; |
2128 | - } |
2129 | - } |
2130 | - if (cc->shref) { |
2131 | - g_free(cc->shref); |
2132 | - cc->shref = NULL; |
2133 | - } |
2134 | - if (cc->scpid) { |
2135 | - g_free(cc->scpid); |
2136 | - cc->scpid = NULL; |
2137 | - } |
2138 | - if (cc->ehref) { |
2139 | - g_free(cc->shref); |
2140 | - cc->shref = NULL; |
2141 | - } |
2142 | - if (cc->ecpid) { |
2143 | - g_free(cc->scpid); |
2144 | - cc->scpid = NULL; |
2145 | - } |
2146 | - g_assert( cc->newConnRef == NULL ); |
2147 | - |
2148 | - G_OBJECT_CLASS(parent_class)->dispose(object); |
2149 | -} |
2150 | - |
2151 | - |
2152 | -static void |
2153 | -sp_connector_context_setup(SPEventContext *ec) |
2154 | -{ |
2155 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(ec); |
2156 | - SPDesktop *dt = ec->desktop; |
2157 | - |
2158 | - if (((SPEventContextClass *) parent_class)->setup) { |
2159 | - ((SPEventContextClass *) parent_class)->setup(ec); |
2160 | - } |
2161 | - |
2162 | - cc->selection = sp_desktop_selection(dt); |
2163 | - |
2164 | - cc->sel_changed_connection.disconnect(); |
2165 | - cc->sel_changed_connection = cc->selection->connectChanged( |
2166 | - sigc::bind(sigc::ptr_fun(&cc_selection_changed), |
2167 | - (gpointer) cc)); |
2168 | - |
2169 | - /* Create red bpath */ |
2170 | - cc->red_bpath = sp_canvas_bpath_new(sp_desktop_sketch(ec->desktop), NULL); |
2171 | - sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cc->red_bpath), cc->red_color, |
2172 | - 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); |
2173 | - sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(cc->red_bpath), 0x00000000, |
2174 | - SP_WIND_RULE_NONZERO); |
2175 | - /* Create red curve */ |
2176 | - cc->red_curve = new SPCurve(); |
2177 | - |
2178 | - /* Create green curve */ |
2179 | - cc->green_curve = new SPCurve(); |
2180 | - |
2181 | - // Notice the initial selection. |
2182 | - cc_selection_changed(cc->selection, (gpointer) cc); |
2183 | - |
2184 | - cc->within_tolerance = false; |
2185 | - |
2186 | - sp_event_context_read(ec, "curvature"); |
2187 | - sp_event_context_read(ec, "orthogonal"); |
2188 | - sp_event_context_read(ec, "mode"); |
2189 | - cc->knot_tip = cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE ? cc_knot_tips[0] : cc_knot_tips[1]; |
2190 | - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
2191 | - if (prefs->getBool("/tools/connector/selcue", 0)) { |
2192 | - ec->enableSelectionCue(); |
2193 | - } |
2194 | - |
2195 | - // Make sure we see all enter events for canvas items, |
2196 | - // even if a mouse button is depressed. |
2197 | - dt->canvas->gen_all_enter_events = true; |
2198 | -} |
2199 | - |
2200 | - |
2201 | -static void |
2202 | -sp_connector_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val) |
2203 | -{ |
2204 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(ec); |
2205 | - |
2206 | - /* fixme: Proper error handling for non-numeric data. Use a locale-independent function like |
2207 | - * g_ascii_strtod (or a thin wrapper that does the right thing for invalid values inf/nan). */ |
2208 | - Glib::ustring name = val->getEntryName(); |
2209 | - if ( name == "curvature" ) { |
2210 | - cc->curvature = val->getDoubleLimited(); // prevents NaN and +/-Inf from messing up |
2211 | - } |
2212 | - else if ( name == "orthogonal" ) { |
2213 | - cc->isOrthogonal = val->getBool(); |
2214 | - } |
2215 | - else if ( name == "mode") |
2216 | - { |
2217 | - sp_connector_context_switch_mode(ec, val->getBool() ? SP_CONNECTOR_CONTEXT_EDITING_MODE : SP_CONNECTOR_CONTEXT_DRAWING_MODE); |
2218 | - } |
2219 | -} |
2220 | - |
2221 | -void sp_connector_context_switch_mode(SPEventContext* ec, unsigned int newMode) |
2222 | -{ |
2223 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(ec); |
2224 | - |
2225 | - cc->mode = newMode; |
2226 | - if ( cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE ) |
2227 | - { |
2228 | - ec->cursor_shape = cursor_connector_xpm; |
2229 | - cc->knot_tip = cc_knot_tips[0]; |
2230 | - if (cc->selected_handle) |
2231 | - cc_deselect_handle( cc->selected_handle ); |
2232 | - cc->selected_handle = NULL; |
2233 | - // Show all default connection points |
2234 | - |
2235 | - } |
2236 | - else if ( cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE ) |
2237 | - { |
2238 | - ec->cursor_shape = cursor_node_xpm; |
2239 | - cc->knot_tip = cc_knot_tips[1]; |
2240 | -/* if (cc->active_shape) |
2241 | - { |
2242 | - cc->selection->set( SP_OBJECT( cc->active_shape ) ); |
2243 | - } |
2244 | - else |
2245 | - { |
2246 | - SPItem* item = cc->selection->singleItem(); |
2247 | - if ( item ) |
2248 | - { |
2249 | - cc_set_active_shape(cc, item); |
2250 | - cc->selection->set( SP_OBJECT( item ) ); |
2251 | - } |
2252 | - }*/ |
2253 | - } |
2254 | - sp_event_context_update_cursor(ec); |
2255 | - |
2256 | -} |
2257 | - |
2258 | - |
2259 | -static void |
2260 | -sp_connector_context_finish(SPEventContext *ec) |
2261 | -{ |
2262 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(ec); |
2263 | - |
2264 | - spcc_connector_finish(cc); |
2265 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2266 | - |
2267 | - if (((SPEventContextClass *) parent_class)->finish) { |
2268 | - ((SPEventContextClass *) parent_class)->finish(ec); |
2269 | - } |
2270 | - |
2271 | - if (cc->selection) { |
2272 | - cc->selection = NULL; |
2273 | - } |
2274 | - cc_clear_active_shape(cc); |
2275 | - cc_clear_active_conn(cc); |
2276 | - |
2277 | - // Restore the default event generating behaviour. |
2278 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(ec); |
2279 | - desktop->canvas->gen_all_enter_events = false; |
2280 | -} |
2281 | - |
2282 | - |
2283 | -//----------------------------------------------------------------------------- |
2284 | - |
2285 | - |
2286 | -static void |
2287 | -cc_clear_active_shape(SPConnectorContext *cc) |
2288 | -{ |
2289 | - if (cc->active_shape == NULL) { |
2290 | - return; |
2291 | - } |
2292 | - g_assert( cc->active_shape_repr ); |
2293 | - g_assert( cc->active_shape_layer_repr ); |
2294 | - |
2295 | - cc->active_shape = NULL; |
2296 | - |
2297 | - if (cc->active_shape_repr) { |
2298 | - sp_repr_remove_listener_by_data(cc->active_shape_repr, cc); |
2299 | - Inkscape::GC::release(cc->active_shape_repr); |
2300 | - cc->active_shape_repr = NULL; |
2301 | - |
2302 | - sp_repr_remove_listener_by_data(cc->active_shape_layer_repr, cc); |
2303 | - Inkscape::GC::release(cc->active_shape_layer_repr); |
2304 | - cc->active_shape_layer_repr = NULL; |
2305 | - } |
2306 | - |
2307 | - // Hide the connection points if they exist. |
2308 | - if (cc->connpthandles.size()) { |
2309 | - for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); |
2310 | - it != cc->connpthandles.end(); ++it) { |
2311 | - sp_knot_hide(it->first); |
2312 | - } |
2313 | - } |
2314 | -} |
2315 | - |
2316 | - |
2317 | -static void |
2318 | -cc_clear_active_conn(SPConnectorContext *cc) |
2319 | -{ |
2320 | - if (cc->active_conn == NULL) { |
2321 | - return; |
2322 | - } |
2323 | - g_assert( cc->active_conn_repr ); |
2324 | - |
2325 | - cc->active_conn = NULL; |
2326 | - |
2327 | - if (cc->active_conn_repr) { |
2328 | - sp_repr_remove_listener_by_data(cc->active_conn_repr, cc); |
2329 | - Inkscape::GC::release(cc->active_conn_repr); |
2330 | - cc->active_conn_repr = NULL; |
2331 | - } |
2332 | - |
2333 | - // Hide the endpoint handles. |
2334 | - for (int i = 0; i < 2; ++i) { |
2335 | - if (cc->endpt_handle[i]) { |
2336 | - sp_knot_hide(cc->endpt_handle[i]); |
2337 | - } |
2338 | - } |
2339 | -} |
2340 | - |
2341 | - |
2342 | -static bool |
2343 | -conn_pt_handle_test(SPConnectorContext *cc, Geom::Point& p, gchar **href, gchar **cpid) |
2344 | -{ |
2345 | - // TODO: this will need to change when there are more connection |
2346 | - // points available for each shape. |
2347 | - |
2348 | - if (cc->active_handle && (cc->connpthandles.find(cc->active_handle) != cc->connpthandles.end())) |
2349 | - { |
2350 | - p = cc->active_handle->pos; |
2351 | - const ConnectionPoint& cp = cc->connpthandles[cc->active_handle]; |
2352 | - *href = g_strdup_printf("#%s", cc->active_shape->getId()); |
2353 | - *cpid = g_strdup_printf("%c%d", cp.type == ConnPointDefault ? 'd' : 'u' , cp.id); |
2354 | - return true; |
2355 | - } |
2356 | - *href = NULL; |
2357 | - *cpid = NULL; |
2358 | - return false; |
2359 | -} |
2360 | - |
2361 | -static void |
2362 | -cc_select_handle(SPKnot* knot) |
2363 | -{ |
2364 | - knot->setShape(SP_KNOT_SHAPE_SQUARE); |
2365 | - knot->setSize(10); |
2366 | - knot->setAnchor(GTK_ANCHOR_CENTER); |
2367 | - knot->setFill(0x0000ffff, 0x0000ffff, 0x0000ffff); |
2368 | - sp_knot_update_ctrl(knot); |
2369 | -} |
2370 | - |
2371 | -static void |
2372 | -cc_deselect_handle(SPKnot* knot) |
2373 | -{ |
2374 | - knot->setShape(SP_KNOT_SHAPE_SQUARE); |
2375 | - knot->setSize(8); |
2376 | - knot->setAnchor(GTK_ANCHOR_CENTER); |
2377 | - knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff); |
2378 | - sp_knot_update_ctrl(knot); |
2379 | -} |
2380 | - |
2381 | -static gint |
2382 | -sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event) |
2383 | -{ |
2384 | - gint ret = FALSE; |
2385 | - |
2386 | - SPDesktop *desktop = event_context->desktop; |
2387 | - |
2388 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(event_context); |
2389 | - |
2390 | - Geom::Point p(event->button.x, event->button.y); |
2391 | - |
2392 | - switch (event->type) { |
2393 | - case GDK_BUTTON_RELEASE: |
2394 | - if (event->button.button == 1 && !event_context->space_panning) { |
2395 | - if ((cc->state == SP_CONNECTOR_CONTEXT_DRAGGING) && |
2396 | - (event_context->within_tolerance)) |
2397 | - { |
2398 | - spcc_reset_colors(cc); |
2399 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2400 | - } |
2401 | - if (cc->state != SP_CONNECTOR_CONTEXT_IDLE) { |
2402 | - // Doing something else like rerouting. |
2403 | - break; |
2404 | - } |
2405 | - // find out clicked item, honoring Alt |
2406 | - SPItem *item = sp_event_context_find_item(desktop, |
2407 | - p, event->button.state & GDK_MOD1_MASK, FALSE); |
2408 | - |
2409 | - if (event->button.state & GDK_SHIFT_MASK) { |
2410 | - cc->selection->toggle(item); |
2411 | - } else { |
2412 | - cc->selection->set(item); |
2413 | - if ( cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE && cc->selected_handle ) |
2414 | - { |
2415 | - cc_deselect_handle( cc->selected_handle ); |
2416 | - cc->selected_handle = NULL; |
2417 | - } |
2418 | - /* When selecting a new item, |
2419 | - do not allow showing connection points |
2420 | - on connectors. (yet?) |
2421 | - */ |
2422 | - if ( item != cc->active_shape && !cc_item_is_connector( item ) ) |
2423 | - cc_set_active_shape( cc, item ); |
2424 | - } |
2425 | - ret = TRUE; |
2426 | - |
2427 | - } |
2428 | - break; |
2429 | - case GDK_ENTER_NOTIFY: |
2430 | - { |
2431 | - if (cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE || (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE && !cc->selected_handle)) |
2432 | - { |
2433 | - if (cc_item_is_shape(item)) { |
2434 | - |
2435 | - // I don't really understand what the above does, |
2436 | - // so I commented it. |
2437 | - // This is a shape, so show connection point(s). |
2438 | - /* if (!(cc->active_shape) |
2439 | - // Don't show handle for another handle. |
2440 | - // || (cc->connpthandles.find((SPKnot*) item) != cc->connpthandles.end()) |
2441 | - ) |
2442 | - { |
2443 | - cc_set_active_shape(cc, item); |
2444 | - }*/ |
2445 | - cc_set_active_shape(cc, item); |
2446 | - } |
2447 | - ret = TRUE; |
2448 | - } |
2449 | - break; |
2450 | - } |
2451 | - default: |
2452 | - break; |
2453 | - } |
2454 | - |
2455 | - return ret; |
2456 | -} |
2457 | - |
2458 | - |
2459 | -gint |
2460 | -sp_connector_context_root_handler(SPEventContext *ec, GdkEvent *event) |
2461 | -{ |
2462 | - SPConnectorContext *const cc = SP_CONNECTOR_CONTEXT(ec); |
2463 | - |
2464 | - gint ret = FALSE; |
2465 | - |
2466 | - switch (event->type) { |
2467 | - case GDK_BUTTON_PRESS: |
2468 | - ret = connector_handle_button_press(cc, event->button); |
2469 | - break; |
2470 | - |
2471 | - case GDK_MOTION_NOTIFY: |
2472 | - ret = connector_handle_motion_notify(cc, event->motion); |
2473 | - break; |
2474 | - |
2475 | - case GDK_BUTTON_RELEASE: |
2476 | - ret = connector_handle_button_release(cc, event->button); |
2477 | - break; |
2478 | - case GDK_KEY_PRESS: |
2479 | - ret = connector_handle_key_press(cc, get_group0_keyval (&event->key)); |
2480 | - break; |
2481 | - |
2482 | - default: |
2483 | - break; |
2484 | - } |
2485 | - |
2486 | - if (!ret) { |
2487 | - gint (*const parent_root_handler)(SPEventContext *, GdkEvent *) |
2488 | - = ((SPEventContextClass *) parent_class)->root_handler; |
2489 | - if (parent_root_handler) { |
2490 | - ret = parent_root_handler(ec, event); |
2491 | - } |
2492 | - } |
2493 | - |
2494 | - return ret; |
2495 | -} |
2496 | - |
2497 | - |
2498 | -static gint |
2499 | -connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const &bevent) |
2500 | -{ |
2501 | - Geom::Point const event_w(bevent.x, bevent.y); |
2502 | - /* Find desktop coordinates */ |
2503 | - Geom::Point p = cc->desktop->w2d(event_w); |
2504 | - SPEventContext *event_context = SP_EVENT_CONTEXT(cc); |
2505 | - |
2506 | - gint ret = FALSE; |
2507 | - if ( cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE ) |
2508 | - { |
2509 | - if ( bevent.button == 1 && !event_context->space_panning ) { |
2510 | - |
2511 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
2512 | - |
2513 | - if (Inkscape::have_viable_layer(desktop, cc->_message_context) == false) { |
2514 | - return TRUE; |
2515 | - } |
2516 | - |
2517 | - Geom::Point const event_w(bevent.x, |
2518 | - bevent.y); |
2519 | -// connector_drag_origin_w = event_w; |
2520 | - cc->xp = bevent.x; |
2521 | - cc->yp = bevent.y; |
2522 | - cc->within_tolerance = true; |
2523 | - |
2524 | - Geom::Point const event_dt = cc->desktop->w2d(event_w); |
2525 | - |
2526 | - SnapManager &m = cc->desktop->namedview->snap_manager; |
2527 | - m.setup(cc->desktop); |
2528 | - |
2529 | - switch (cc->state) { |
2530 | - case SP_CONNECTOR_CONTEXT_STOP: |
2531 | - /* This is allowed, if we just canceled curve */ |
2532 | - case SP_CONNECTOR_CONTEXT_IDLE: |
2533 | - { |
2534 | - if ( cc->npoints == 0 ) { |
2535 | - cc_clear_active_conn(cc); |
2536 | - |
2537 | - SP_EVENT_CONTEXT_DESKTOP(cc)->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new connector")); |
2538 | - |
2539 | - /* Set start anchor */ |
2540 | - /* Create green anchor */ |
2541 | - Geom::Point p = event_dt; |
2542 | - |
2543 | - // Test whether we clicked on a connection point |
2544 | - bool found = conn_pt_handle_test(cc, p, &cc->shref, &cc->scpid); |
2545 | - |
2546 | - if (!found) { |
2547 | - // This is the first point, so just snap it to the grid |
2548 | - // as there's no other points to go off. |
2549 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2550 | - } |
2551 | - spcc_connector_set_initial_point(cc, p); |
2552 | - |
2553 | - } |
2554 | - cc->state = SP_CONNECTOR_CONTEXT_DRAGGING; |
2555 | - ret = TRUE; |
2556 | - break; |
2557 | - } |
2558 | - case SP_CONNECTOR_CONTEXT_DRAGGING: |
2559 | - { |
2560 | - // This is the second click of a connector creation. |
2561 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2562 | - |
2563 | - spcc_connector_set_subsequent_point(cc, p); |
2564 | - spcc_connector_finish_segment(cc, p); |
2565 | - // Test whether we clicked on a connection point |
2566 | - /*bool found = */conn_pt_handle_test(cc, p, &cc->ehref, &cc->ecpid); |
2567 | - if (cc->npoints != 0) { |
2568 | - spcc_connector_finish(cc); |
2569 | - } |
2570 | - cc_set_active_conn(cc, cc->newconn); |
2571 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2572 | - ret = TRUE; |
2573 | - break; |
2574 | - } |
2575 | - case SP_CONNECTOR_CONTEXT_CLOSE: |
2576 | - { |
2577 | - g_warning("Button down in CLOSE state"); |
2578 | - break; |
2579 | - } |
2580 | - default: |
2581 | - break; |
2582 | - } |
2583 | - } else if (bevent.button == 3) { |
2584 | - if (cc->state == SP_CONNECTOR_CONTEXT_REROUTING) { |
2585 | - // A context menu is going to be triggered here, |
2586 | - // so end the rerouting operation. |
2587 | - cc_connector_rerouting_finish(cc, &p); |
2588 | - |
2589 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2590 | - |
2591 | - // Don't set ret to TRUE, so we drop through to the |
2592 | - // parent handler which will open the context menu. |
2593 | - } |
2594 | - else if (cc->npoints != 0) { |
2595 | - spcc_connector_finish(cc); |
2596 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2597 | - ret = TRUE; |
2598 | - } |
2599 | - } |
2600 | - } |
2601 | - else if ( cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE ) |
2602 | - { |
2603 | - if ( bevent.button == 1 && !event_context->space_panning ) |
2604 | - { |
2605 | - // Initialize variables in case of dragging |
2606 | - |
2607 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
2608 | - |
2609 | - if (Inkscape::have_viable_layer(desktop, cc->_message_context) == false) { |
2610 | - return TRUE; |
2611 | - } |
2612 | - |
2613 | - cc->xp = bevent.x; |
2614 | - cc->yp = bevent.y; |
2615 | - cc->within_tolerance = true; |
2616 | - |
2617 | - ConnectionPointMap::iterator const& active_knot_it = cc->connpthandles.find( cc->active_handle ); |
2618 | - |
2619 | - switch (cc->state) |
2620 | - { |
2621 | - case SP_CONNECTOR_CONTEXT_IDLE: |
2622 | - if ( active_knot_it != cc->connpthandles.end() ) |
2623 | - { |
2624 | - // We do not allow selecting and, thereby, moving default knots |
2625 | - if ( active_knot_it->second.type != ConnPointDefault) |
2626 | - { |
2627 | - if (cc->selected_handle != cc->active_handle) |
2628 | - { |
2629 | - if ( cc->selected_handle ) |
2630 | - cc_deselect_handle( cc->selected_handle ); |
2631 | - cc->selected_handle = cc->active_handle; |
2632 | - cc_select_handle( cc->selected_handle ); |
2633 | - } |
2634 | - } |
2635 | - else |
2636 | - // Just ignore the default connection point |
2637 | - return FALSE; |
2638 | - } |
2639 | - else |
2640 | - if ( cc->selected_handle ) |
2641 | - { |
2642 | - cc_deselect_handle( cc->selected_handle ); |
2643 | - cc->selected_handle = NULL; |
2644 | - } |
2645 | - |
2646 | - if ( cc->selected_handle ) |
2647 | - { |
2648 | - cc->state = SP_CONNECTOR_CONTEXT_DRAGGING; |
2649 | - cc->selection->set( SP_OBJECT( cc->active_shape ) ); |
2650 | - } |
2651 | - |
2652 | - ret = TRUE; |
2653 | - break; |
2654 | - // Dragging valid because of the way we create |
2655 | - // new connection points. |
2656 | - case SP_CONNECTOR_CONTEXT_DRAGGING: |
2657 | - // Do nothing. |
2658 | - ret = TRUE; |
2659 | - break; |
2660 | - } |
2661 | - } |
2662 | - } |
2663 | - return ret; |
2664 | -} |
2665 | - |
2666 | - |
2667 | -static gint |
2668 | -connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion const &mevent) |
2669 | -{ |
2670 | - gint ret = FALSE; |
2671 | - SPEventContext *event_context = SP_EVENT_CONTEXT(cc); |
2672 | - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
2673 | - |
2674 | - if (event_context->space_panning || mevent.state & GDK_BUTTON2_MASK || mevent.state & GDK_BUTTON3_MASK) { |
2675 | - // allow middle-button scrolling |
2676 | - return FALSE; |
2677 | - } |
2678 | - |
2679 | - Geom::Point const event_w(mevent.x, mevent.y); |
2680 | - |
2681 | - if (cc->within_tolerance) { |
2682 | - cc->tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); |
2683 | - if ( ( abs( (gint) mevent.x - cc->xp ) < cc->tolerance ) && |
2684 | - ( abs( (gint) mevent.y - cc->yp ) < cc->tolerance ) ) { |
2685 | - return FALSE; // Do not drag if we're within tolerance from origin. |
2686 | - } |
2687 | - } |
2688 | - // Once the user has moved farther than tolerance from the original location |
2689 | - // (indicating they intend to move the object, not click), then always process |
2690 | - // the motion notify coordinates as given (no snapping back to origin) |
2691 | - cc->within_tolerance = false; |
2692 | - |
2693 | - SPDesktop *const dt = cc->desktop; |
2694 | - |
2695 | - /* Find desktop coordinates */ |
2696 | - Geom::Point p = dt->w2d(event_w); |
2697 | - |
2698 | - if ( cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE ) |
2699 | - { |
2700 | - SnapManager &m = dt->namedview->snap_manager; |
2701 | - m.setup(dt); |
2702 | - |
2703 | - switch (cc->state) { |
2704 | - case SP_CONNECTOR_CONTEXT_DRAGGING: |
2705 | - { |
2706 | - gobble_motion_events(mevent.state); |
2707 | - // This is movement during a connector creation. |
2708 | - if ( cc->npoints > 0 ) { |
2709 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2710 | - cc->selection->clear(); |
2711 | - spcc_connector_set_subsequent_point(cc, p); |
2712 | - ret = TRUE; |
2713 | - } |
2714 | - break; |
2715 | - } |
2716 | - case SP_CONNECTOR_CONTEXT_REROUTING: |
2717 | - { |
2718 | - gobble_motion_events(GDK_BUTTON1_MASK); |
2719 | - g_assert( SP_IS_PATH(cc->clickeditem)); |
2720 | - |
2721 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2722 | - |
2723 | - // Update the hidden path |
2724 | - Geom::Matrix i2d = sp_item_i2d_affine(cc->clickeditem); |
2725 | - Geom::Matrix d2i = i2d.inverse(); |
2726 | - SPPath *path = SP_PATH(cc->clickeditem); |
2727 | - SPCurve *curve = path->original_curve ? path->original_curve : path->curve; |
2728 | - if (cc->clickedhandle == cc->endpt_handle[0]) { |
2729 | - Geom::Point o = cc->endpt_handle[1]->pos; |
2730 | - curve->stretch_endpoints(p * d2i, o * d2i); |
2731 | - } |
2732 | - else { |
2733 | - Geom::Point o = cc->endpt_handle[0]->pos; |
2734 | - curve->stretch_endpoints(o * d2i, p * d2i); |
2735 | - } |
2736 | - sp_conn_reroute_path_immediate(path); |
2737 | - |
2738 | - // Copy this to the temporary visible path |
2739 | - cc->red_curve = path->original_curve ? |
2740 | - path->original_curve->copy() : path->curve->copy(); |
2741 | - cc->red_curve->transform(i2d); |
2742 | - |
2743 | - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), cc->red_curve); |
2744 | - ret = TRUE; |
2745 | - break; |
2746 | - } |
2747 | - case SP_CONNECTOR_CONTEXT_STOP: |
2748 | - /* This is perfectly valid */ |
2749 | - break; |
2750 | - default: |
2751 | - if (!sp_event_context_knot_mouseover(cc)) { |
2752 | - m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE)); |
2753 | - } |
2754 | - break; |
2755 | - } |
2756 | - } |
2757 | - else if ( cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE ) |
2758 | - { |
2759 | - switch ( cc->state ) |
2760 | - { |
2761 | - case SP_CONNECTOR_CONTEXT_DRAGGING: |
2762 | - sp_knot_set_position(cc->selected_handle, p, 0); |
2763 | - ret = TRUE; |
2764 | - break; |
2765 | - case SP_CONNECTOR_CONTEXT_NEWCONNPOINT: |
2766 | - sp_knot_set_position(cc->selected_handle, p, 0); |
2767 | - ret = TRUE; |
2768 | - break; |
2769 | - } |
2770 | - } |
2771 | - |
2772 | - return ret; |
2773 | -} |
2774 | - |
2775 | - |
2776 | -static gint |
2777 | -connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton const &revent) |
2778 | -{ |
2779 | - gint ret = FALSE; |
2780 | - SPEventContext *event_context = SP_EVENT_CONTEXT(cc); |
2781 | - if ( revent.button == 1 && !event_context->space_panning ) { |
2782 | - |
2783 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
2784 | - SPDocument *doc = sp_desktop_document(desktop); |
2785 | - |
2786 | - SnapManager &m = desktop->namedview->snap_manager; |
2787 | - m.setup(desktop); |
2788 | - |
2789 | - Geom::Point const event_w(revent.x, revent.y); |
2790 | - |
2791 | - /* Find desktop coordinates */ |
2792 | - Geom::Point p = cc->desktop->w2d(event_w); |
2793 | - if ( cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE ) |
2794 | - { |
2795 | - switch (cc->state) { |
2796 | - //case SP_CONNECTOR_CONTEXT_POINT: |
2797 | - case SP_CONNECTOR_CONTEXT_DRAGGING: |
2798 | - { |
2799 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2800 | - |
2801 | - if (cc->within_tolerance) |
2802 | - { |
2803 | - spcc_connector_finish_segment(cc, p); |
2804 | - return TRUE; |
2805 | - } |
2806 | - // Connector has been created via a drag, end it now. |
2807 | - spcc_connector_set_subsequent_point(cc, p); |
2808 | - spcc_connector_finish_segment(cc, p); |
2809 | - // Test whether we clicked on a connection point |
2810 | - /*bool found = */conn_pt_handle_test(cc, p, &cc->ehref, &cc->ecpid); |
2811 | - if (cc->npoints != 0) { |
2812 | - spcc_connector_finish(cc); |
2813 | - } |
2814 | - cc_set_active_conn(cc, cc->newconn); |
2815 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2816 | - break; |
2817 | - } |
2818 | - case SP_CONNECTOR_CONTEXT_REROUTING: |
2819 | - { |
2820 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2821 | - cc_connector_rerouting_finish(cc, &p); |
2822 | - |
2823 | - sp_document_ensure_up_to_date(doc); |
2824 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2825 | - return TRUE; |
2826 | - break; |
2827 | - } |
2828 | - case SP_CONNECTOR_CONTEXT_STOP: |
2829 | - /* This is allowed, if we just cancelled curve */ |
2830 | - break; |
2831 | - default: |
2832 | - break; |
2833 | - } |
2834 | - ret = TRUE; |
2835 | - } |
2836 | - else if ( cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE ) |
2837 | - { |
2838 | - switch ( cc->state ) |
2839 | - { |
2840 | - case SP_CONNECTOR_CONTEXT_DRAGGING: |
2841 | - |
2842 | - if (!cc->within_tolerance) |
2843 | - { |
2844 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2845 | - sp_knot_set_position(cc->selected_handle, p, 0); |
2846 | - ConnectionPoint& cp = cc->connpthandles[cc->selected_handle]; |
2847 | - cp.pos = p * sp_item_dt2i_affine(cc->active_shape); |
2848 | - cc->active_shape->avoidRef->updateConnectionPoint(cp); |
2849 | - } |
2850 | - |
2851 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2852 | - ret = TRUE; |
2853 | - break; |
2854 | - |
2855 | - |
2856 | - case SP_CONNECTOR_CONTEXT_NEWCONNPOINT: |
2857 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2858 | - |
2859 | - sp_knot_set_position(cc->selected_handle, p, 0); |
2860 | - |
2861 | - ConnectionPoint cp; |
2862 | - cp.type = ConnPointUserDefined; |
2863 | - cp.pos = p * sp_item_dt2i_affine(cc->active_shape); |
2864 | - cp.dir = Avoid::ConnDirAll; |
2865 | - g_object_unref(cc->selected_handle); |
2866 | - cc->active_shape->avoidRef->addConnectionPoint(cp); |
2867 | - sp_document_ensure_up_to_date(doc); |
2868 | - for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end(); ++it) |
2869 | - if (it->second.type == ConnPointUserDefined && it->second.id == cp.id) |
2870 | - { |
2871 | - cc->selected_handle = it->first; |
2872 | - break; |
2873 | - } |
2874 | - cc_select_handle( cc->selected_handle ); |
2875 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2876 | - ret = TRUE; |
2877 | - break; |
2878 | - } |
2879 | - } |
2880 | - } |
2881 | - |
2882 | - |
2883 | - return ret; |
2884 | -} |
2885 | - |
2886 | - |
2887 | -static gint |
2888 | -connector_handle_key_press(SPConnectorContext *const cc, guint const keyval) |
2889 | -{ |
2890 | - gint ret = FALSE; |
2891 | - /* fixme: */ |
2892 | - if ( cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE ) |
2893 | - { |
2894 | - switch (keyval) { |
2895 | - case GDK_Return: |
2896 | - case GDK_KP_Enter: |
2897 | - if (cc->npoints != 0) { |
2898 | - spcc_connector_finish(cc); |
2899 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2900 | - ret = TRUE; |
2901 | - } |
2902 | - break; |
2903 | - case GDK_Escape: |
2904 | - if (cc->state == SP_CONNECTOR_CONTEXT_REROUTING) { |
2905 | - |
2906 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
2907 | - SPDocument *doc = sp_desktop_document(desktop); |
2908 | - |
2909 | - cc_connector_rerouting_finish(cc, NULL); |
2910 | - |
2911 | - sp_document_undo(doc); |
2912 | - |
2913 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2914 | - desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE, |
2915 | - _("Connector endpoint drag cancelled.")); |
2916 | - ret = TRUE; |
2917 | - } |
2918 | - else if (cc->npoints != 0) { |
2919 | - // if drawing, cancel, otherwise pass it up for deselecting |
2920 | - cc->state = SP_CONNECTOR_CONTEXT_STOP; |
2921 | - spcc_reset_colors(cc); |
2922 | - ret = TRUE; |
2923 | - } |
2924 | - break; |
2925 | - default: |
2926 | - break; |
2927 | - } |
2928 | - } |
2929 | - else if ( cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE ) |
2930 | - { |
2931 | - switch ( cc->state ) |
2932 | - { |
2933 | - case SP_CONNECTOR_CONTEXT_DRAGGING: |
2934 | - if ( keyval == GDK_Escape ) |
2935 | - { |
2936 | - // Cancel connection point dragging |
2937 | - |
2938 | - // Obtain original position |
2939 | - ConnectionPoint const& cp = cc->connpthandles[cc->selected_handle]; |
2940 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
2941 | - const Geom::Matrix& i2doc = sp_item_i2doc_affine(cc->active_shape); |
2942 | - sp_knot_set_position(cc->selected_handle, cp.pos * i2doc * desktop->doc2dt(), 0); |
2943 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2944 | - desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE, |
2945 | - _("Connection point drag cancelled.")); |
2946 | - ret = TRUE; |
2947 | - } |
2948 | - else if ( keyval == GDK_Return || keyval == GDK_KP_Enter ) |
2949 | - { |
2950 | - // Put connection point at current position |
2951 | - |
2952 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
2953 | - SnapManager &m = desktop->namedview->snap_manager; |
2954 | - m.setup(desktop); |
2955 | - Geom::Point p = cc->selected_handle->pos; |
2956 | -// SPEventContext* event_context = SP_EVENT_CONTEXT( cc ); |
2957 | - |
2958 | - if (!cc->within_tolerance) |
2959 | - { |
2960 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2961 | - sp_knot_set_position(cc->selected_handle, p, 0); |
2962 | - ConnectionPoint& cp = cc->connpthandles[cc->selected_handle]; |
2963 | - cp.pos = p * sp_item_dt2i_affine(cc->active_shape); |
2964 | - cc->active_shape->avoidRef->updateConnectionPoint(cp); |
2965 | - } |
2966 | - |
2967 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2968 | - ret = TRUE; |
2969 | - } |
2970 | - break; |
2971 | - case SP_CONNECTOR_CONTEXT_NEWCONNPOINT: |
2972 | - if ( keyval == GDK_Escape ) |
2973 | - { |
2974 | - // Just destroy the knot |
2975 | - g_object_unref( cc->selected_handle ); |
2976 | - cc->selected_handle = NULL; |
2977 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
2978 | - ret = TRUE; |
2979 | - } |
2980 | - else if ( keyval == GDK_Return || keyval == GDK_KP_Enter ) |
2981 | - { |
2982 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
2983 | - SPDocument *doc = sp_desktop_document(desktop); |
2984 | - SnapManager &m = desktop->namedview->snap_manager; |
2985 | - m.setup(desktop); |
2986 | - Geom::Point p = cc->selected_handle->pos; |
2987 | - |
2988 | - m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE); |
2989 | - |
2990 | - sp_knot_set_position(cc->selected_handle, p, 0); |
2991 | - |
2992 | - ConnectionPoint cp; |
2993 | - cp.type = ConnPointUserDefined; |
2994 | - cp.pos = p * sp_item_dt2i_affine(cc->active_shape); |
2995 | - cp.dir = Avoid::ConnDirAll; |
2996 | - g_object_unref(cc->selected_handle); |
2997 | - cc->active_shape->avoidRef->addConnectionPoint(cp); |
2998 | - sp_document_ensure_up_to_date(doc); |
2999 | - for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end(); ++it) |
3000 | - if (it->second.type == ConnPointUserDefined && it->second.id == cp.id) |
3001 | - { |
3002 | - cc->selected_handle = it->first; |
3003 | - break; |
3004 | - } |
3005 | - cc_select_handle( cc->selected_handle ); |
3006 | - cc->state = SP_CONNECTOR_CONTEXT_IDLE; |
3007 | - ret = TRUE; |
3008 | - } |
3009 | - |
3010 | - break; |
3011 | - case SP_CONNECTOR_CONTEXT_IDLE: |
3012 | - if ( keyval == GDK_Delete && cc->selected_handle ) |
3013 | - { |
3014 | - cc->active_shape->avoidRef->deleteConnectionPoint(cc->connpthandles[cc->selected_handle]); |
3015 | - cc->selected_handle = NULL; |
3016 | - ret = TRUE; |
3017 | - } |
3018 | - |
3019 | - break; |
3020 | - } |
3021 | - } |
3022 | - |
3023 | - return ret; |
3024 | -} |
3025 | - |
3026 | - |
3027 | -static void |
3028 | -cc_connector_rerouting_finish(SPConnectorContext *const cc, Geom::Point *const p) |
3029 | -{ |
3030 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
3031 | - SPDocument *doc = sp_desktop_document(desktop); |
3032 | - |
3033 | - // Clear the temporary path: |
3034 | - cc->red_curve->reset(); |
3035 | - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL); |
3036 | - |
3037 | - if (p != NULL) |
3038 | - { |
3039 | - // Test whether we clicked on a connection point |
3040 | - gchar *shape_label, *cpid; |
3041 | - bool found = conn_pt_handle_test(cc, *p, &shape_label, &cpid); |
3042 | - |
3043 | - if (found) { |
3044 | - if (cc->clickedhandle == cc->endpt_handle[0]) { |
3045 | - sp_object_setAttribute(cc->clickeditem, |
3046 | - "inkscape:connection-start", shape_label, false); |
3047 | - sp_object_setAttribute(cc->clickeditem, |
3048 | - "inkscape:connection-start-point", cpid, false); |
3049 | - } |
3050 | - else { |
3051 | - sp_object_setAttribute(cc->clickeditem, |
3052 | - "inkscape:connection-end", shape_label, false); |
3053 | - sp_object_setAttribute(cc->clickeditem, |
3054 | - "inkscape:connection-end-point", cpid, false); |
3055 | - } |
3056 | - g_free(shape_label); |
3057 | - } |
3058 | - } |
3059 | - cc->clickeditem->setHidden(false); |
3060 | - sp_conn_reroute_path_immediate(SP_PATH(cc->clickeditem)); |
3061 | - cc->clickeditem->updateRepr(); |
3062 | - sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR, |
3063 | - _("Reroute connector")); |
3064 | - cc_set_active_conn(cc, cc->clickeditem); |
3065 | -} |
3066 | - |
3067 | - |
3068 | -static void |
3069 | -spcc_reset_colors(SPConnectorContext *cc) |
3070 | -{ |
3071 | - /* Red */ |
3072 | - cc->red_curve->reset(); |
3073 | - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL); |
3074 | - |
3075 | - cc->green_curve->reset(); |
3076 | - cc->npoints = 0; |
3077 | -} |
3078 | - |
3079 | - |
3080 | -static void |
3081 | -spcc_connector_set_initial_point(SPConnectorContext *const cc, Geom::Point const p) |
3082 | -{ |
3083 | - g_assert( cc->npoints == 0 ); |
3084 | - |
3085 | - cc->p[0] = p; |
3086 | - cc->p[1] = p; |
3087 | - cc->npoints = 2; |
3088 | - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL); |
3089 | -} |
3090 | - |
3091 | - |
3092 | -static void |
3093 | -spcc_connector_set_subsequent_point(SPConnectorContext *const cc, Geom::Point const p) |
3094 | -{ |
3095 | - g_assert( cc->npoints != 0 ); |
3096 | - |
3097 | - SPDesktop *dt = cc->desktop; |
3098 | - Geom::Point o = dt->dt2doc(cc->p[0]); |
3099 | - Geom::Point d = dt->dt2doc(p); |
3100 | - Avoid::Point src(o[Geom::X], o[Geom::Y]); |
3101 | - Avoid::Point dst(d[Geom::X], d[Geom::Y]); |
3102 | - |
3103 | - if (!cc->newConnRef) { |
3104 | - Avoid::Router *router = sp_desktop_document(dt)->router; |
3105 | - cc->newConnRef = new Avoid::ConnRef(router); |
3106 | - cc->newConnRef->setEndpoint(Avoid::VertID::src, src); |
3107 | - if (cc->isOrthogonal) |
3108 | - cc->newConnRef->setRoutingType(Avoid::ConnType_Orthogonal); |
3109 | - else |
3110 | - cc->newConnRef->setRoutingType(Avoid::ConnType_PolyLine); |
3111 | - } |
3112 | - // Set new endpoint. |
3113 | - cc->newConnRef->setEndpoint(Avoid::VertID::tar, dst); |
3114 | - // Immediately generate new routes for connector. |
3115 | - cc->newConnRef->makePathInvalid(); |
3116 | - cc->newConnRef->router()->processTransaction(); |
3117 | - // Recreate curve from libavoid route. |
3118 | - recreateCurve( cc->red_curve, cc->newConnRef, cc->curvature ); |
3119 | - cc->red_curve->transform(dt->doc2dt()); |
3120 | - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), cc->red_curve); |
3121 | -} |
3122 | - |
3123 | - |
3124 | -/** |
3125 | - * Concats red, blue and green. |
3126 | - * If any anchors are defined, process these, optionally removing curves from white list |
3127 | - * Invoke _flush_white to write result back to object. |
3128 | - */ |
3129 | -static void |
3130 | -spcc_concat_colors_and_flush(SPConnectorContext *cc) |
3131 | -{ |
3132 | - SPCurve *c = cc->green_curve; |
3133 | - cc->green_curve = new SPCurve(); |
3134 | - |
3135 | - cc->red_curve->reset(); |
3136 | - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL); |
3137 | - |
3138 | - if (c->is_empty()) { |
3139 | - c->unref(); |
3140 | - return; |
3141 | - } |
3142 | - |
3143 | - spcc_flush_white(cc, c); |
3144 | - |
3145 | - c->unref(); |
3146 | -} |
3147 | - |
3148 | - |
3149 | -/* |
3150 | - * Flushes white curve(s) and additional curve into object |
3151 | - * |
3152 | - * No cleaning of colored curves - this has to be done by caller |
3153 | - * No rereading of white data, so if you cannot rely on ::modified, do it in caller |
3154 | - * |
3155 | - */ |
3156 | - |
3157 | -static void |
3158 | -spcc_flush_white(SPConnectorContext *cc, SPCurve *gc) |
3159 | -{ |
3160 | - SPCurve *c; |
3161 | - |
3162 | - if (gc) { |
3163 | - c = gc; |
3164 | - c->ref(); |
3165 | - } else { |
3166 | - return; |
3167 | - } |
3168 | - |
3169 | - /* Now we have to go back to item coordinates at last */ |
3170 | - c->transform(SP_EVENT_CONTEXT_DESKTOP(cc)->dt2doc()); |
3171 | - |
3172 | - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); |
3173 | - SPDocument *doc = sp_desktop_document(desktop); |
3174 | - Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); |
3175 | - |
3176 | - if ( c && !c->is_empty() ) { |
3177 | - /* We actually have something to write */ |
3178 | - |
3179 | - Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); |
3180 | - /* Set style */ |
3181 | - sp_desktop_apply_style_tool(desktop, repr, "/tools/connector", false); |
3182 | - |
3183 | - gchar *str = sp_svg_write_path( c->get_pathvector() ); |
3184 | - g_assert( str != NULL ); |
3185 | - repr->setAttribute("d", str); |
3186 | - g_free(str); |
3187 | - |
3188 | - /* Attach repr */ |
3189 | - cc->newconn = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); |
3190 | - cc->newconn->transform = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse(); |
3191 | - |
3192 | - bool connection = false; |
3193 | - sp_object_setAttribute(cc->newconn, "inkscape:connector-type", |
3194 | - cc->isOrthogonal ? "orthogonal" : "polyline", false); |
3195 | - sp_object_setAttribute(cc->newconn, "inkscape:connector-curvature", |
3196 | - Glib::Ascii::dtostr(cc->curvature).c_str(), false); |
3197 | - if (cc->shref) |
3198 | - { |
3199 | - sp_object_setAttribute(cc->newconn, "inkscape:connection-start", |
3200 | - cc->shref, false); |
3201 | - if (cc->scpid) |
3202 | - sp_object_setAttribute(cc->newconn, "inkscape:connection-start-point", |
3203 | - cc->scpid, false); |
3204 | - connection = true; |
3205 | - } |
3206 | - |
3207 | - if (cc->ehref) |
3208 | - { |
3209 | - sp_object_setAttribute(cc->newconn, "inkscape:connection-end", |
3210 | - cc->ehref, false); |
3211 | - if (cc->ecpid) |
3212 | - sp_object_setAttribute(cc->newconn, "inkscape:connection-end-point", |
3213 | - cc->ecpid, false); |
3214 | - connection = true; |
3215 | - } |
3216 | - // Process pending updates. |
3217 | - cc->newconn->updateRepr(); |
3218 | - sp_document_ensure_up_to_date(doc); |
3219 | - |
3220 | - if (connection) { |
3221 | - // Adjust endpoints to shape edge. |
3222 | - sp_conn_reroute_path_immediate(SP_PATH(cc->newconn)); |
3223 | - cc->newconn->updateRepr(); |
3224 | - } |
3225 | - |
3226 | - // Only set the selection after we are finished with creating the attributes of |
3227 | - // the connector. Otherwise, the selection change may alter the defaults for |
3228 | - // values like curvature in the connector context, preventing subsequent lookup |
3229 | - // of their original values. |
3230 | - cc->selection->set(repr); |
3231 | - Inkscape::GC::release(repr); |
3232 | - } |
3233 | - |
3234 | - c->unref(); |
3235 | - |
3236 | - sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR, _("Create connector")); |
3237 | -} |
3238 | - |
3239 | - |
3240 | -static void |
3241 | -spcc_connector_finish_segment(SPConnectorContext *const cc, Geom::Point const /*p*/) |
3242 | -{ |
3243 | - if (!cc->red_curve->is_empty()) { |
3244 | - cc->green_curve->append_continuous(cc->red_curve, 0.0625); |
3245 | - |
3246 | - cc->p[0] = cc->p[3]; |
3247 | - cc->p[1] = cc->p[4]; |
3248 | - cc->npoints = 2; |
3249 | - |
3250 | - cc->red_curve->reset(); |
3251 | - } |
3252 | -} |
3253 | - |
3254 | - |
3255 | -static void |
3256 | -spcc_connector_finish(SPConnectorContext *const cc) |
3257 | -{ |
3258 | - SPDesktop *const desktop = cc->desktop; |
3259 | - desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Finishing connector")); |
3260 | - |
3261 | - cc->red_curve->reset(); |
3262 | - spcc_concat_colors_and_flush(cc); |
3263 | - |
3264 | - cc->npoints = 0; |
3265 | - |
3266 | - if (cc->newConnRef) { |
3267 | - cc->newConnRef->removeFromGraph(); |
3268 | - delete cc->newConnRef; |
3269 | - cc->newConnRef = NULL; |
3270 | - } |
3271 | -} |
3272 | - |
3273 | - |
3274 | -static gboolean |
3275 | -cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot) |
3276 | -{ |
3277 | - g_assert (knot != NULL); |
3278 | - |
3279 | - g_object_ref(knot); |
3280 | - |
3281 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT( |
3282 | - knot->desktop->event_context); |
3283 | - |
3284 | - gboolean consumed = FALSE; |
3285 | - |
3286 | - gchar* knot_tip = knot->tip ? knot->tip : cc->knot_tip; |
3287 | - switch (event->type) { |
3288 | - case GDK_ENTER_NOTIFY: |
3289 | - sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, TRUE); |
3290 | - |
3291 | - cc->active_handle = knot; |
3292 | - if (knot_tip) |
3293 | - { |
3294 | - knot->desktop->event_context->defaultMessageContext()->set( |
3295 | - Inkscape::NORMAL_MESSAGE, knot_tip); |
3296 | - } |
3297 | - |
3298 | - consumed = TRUE; |
3299 | - break; |
3300 | - case GDK_LEAVE_NOTIFY: |
3301 | - sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, FALSE); |
3302 | - |
3303 | - cc->active_handle = NULL; |
3304 | - |
3305 | - if (knot_tip) { |
3306 | - knot->desktop->event_context->defaultMessageContext()->clear(); |
3307 | - } |
3308 | - |
3309 | - consumed = TRUE; |
3310 | - break; |
3311 | - default: |
3312 | - break; |
3313 | - } |
3314 | - |
3315 | - g_object_unref(knot); |
3316 | - |
3317 | - return consumed; |
3318 | -} |
3319 | - |
3320 | - |
3321 | -static gboolean |
3322 | -endpt_handler(SPKnot */*knot*/, GdkEvent *event, SPConnectorContext *cc) |
3323 | -{ |
3324 | - g_assert( SP_IS_CONNECTOR_CONTEXT(cc) ); |
3325 | - |
3326 | - gboolean consumed = FALSE; |
3327 | - |
3328 | - switch (event->type) { |
3329 | - case GDK_BUTTON_PRESS: |
3330 | - g_assert( (cc->active_handle == cc->endpt_handle[0]) || |
3331 | - (cc->active_handle == cc->endpt_handle[1]) ); |
3332 | - if (cc->state == SP_CONNECTOR_CONTEXT_IDLE) { |
3333 | - cc->clickeditem = cc->active_conn; |
3334 | - cc->clickedhandle = cc->active_handle; |
3335 | - cc_clear_active_conn(cc); |
3336 | - cc->state = SP_CONNECTOR_CONTEXT_REROUTING; |
3337 | - |
3338 | - // Disconnect from attached shape |
3339 | - unsigned ind = (cc->active_handle == cc->endpt_handle[0]) ? 0 : 1; |
3340 | - sp_conn_end_detach(cc->clickeditem, ind); |
3341 | - |
3342 | - Geom::Point origin; |
3343 | - if (cc->clickedhandle == cc->endpt_handle[0]) { |
3344 | - origin = cc->endpt_handle[1]->pos; |
3345 | - } |
3346 | - else { |
3347 | - origin = cc->endpt_handle[0]->pos; |
3348 | - } |
3349 | - |
3350 | - // Show the red path for dragging. |
3351 | - cc->red_curve = SP_PATH(cc->clickeditem)->original_curve ? SP_PATH(cc->clickeditem)->original_curve->copy() : SP_PATH(cc->clickeditem)->curve->copy(); |
3352 | - Geom::Matrix i2d = sp_item_i2d_affine(cc->clickeditem); |
3353 | - cc->red_curve->transform(i2d); |
3354 | - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), cc->red_curve); |
3355 | - |
3356 | - cc->clickeditem->setHidden(true); |
3357 | - |
3358 | - // The rest of the interaction rerouting the connector is |
3359 | - // handled by the context root handler. |
3360 | - consumed = TRUE; |
3361 | - } |
3362 | - break; |
3363 | - default: |
3364 | - break; |
3365 | - } |
3366 | - |
3367 | - return consumed; |
3368 | -} |
3369 | - |
3370 | -static void cc_active_shape_add_knot(SPDesktop* desktop, SPItem* item, ConnectionPointMap &cphandles, ConnectionPoint& cp) |
3371 | -{ |
3372 | - SPKnot *knot = sp_knot_new(desktop, 0); |
3373 | - |
3374 | - knot->setShape(SP_KNOT_SHAPE_SQUARE); |
3375 | - knot->setSize(8); |
3376 | - knot->setAnchor(GTK_ANCHOR_CENTER); |
3377 | - knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff); |
3378 | - sp_knot_update_ctrl(knot); |
3379 | - |
3380 | - // We don't want to use the standard knot handler. |
3381 | - g_signal_handler_disconnect(G_OBJECT(knot->item), |
3382 | - knot->_event_handler_id); |
3383 | - knot->_event_handler_id = 0; |
3384 | - |
3385 | - gtk_signal_connect(GTK_OBJECT(knot->item), "event", |
3386 | - GTK_SIGNAL_FUNC(cc_generic_knot_handler), knot); |
3387 | - sp_knot_set_position(knot, item->avoidRef->getConnectionPointPos(cp.type, cp.id) * desktop->doc2dt(), 0); |
3388 | - sp_knot_show(knot); |
3389 | - cphandles[knot] = cp; |
3390 | -} |
3391 | - |
3392 | -static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item) |
3393 | -{ |
3394 | - g_assert(item != NULL ); |
3395 | - |
3396 | - std::map<int, ConnectionPoint>* connpts = &item->avoidRef->connection_points; |
3397 | - |
3398 | - if (cc->active_shape != item) |
3399 | - { |
3400 | - // The active shape has changed |
3401 | - // Rebuild everything |
3402 | - cc->active_shape = item; |
3403 | - // Remove existing active shape listeners |
3404 | - if (cc->active_shape_repr) { |
3405 | - sp_repr_remove_listener_by_data(cc->active_shape_repr, cc); |
3406 | - Inkscape::GC::release(cc->active_shape_repr); |
3407 | - |
3408 | - sp_repr_remove_listener_by_data(cc->active_shape_layer_repr, cc); |
3409 | - Inkscape::GC::release(cc->active_shape_layer_repr); |
3410 | - } |
3411 | - |
3412 | - // Listen in case the active shape changes |
3413 | - cc->active_shape_repr = SP_OBJECT_REPR(item); |
3414 | - if (cc->active_shape_repr) { |
3415 | - Inkscape::GC::anchor(cc->active_shape_repr); |
3416 | - sp_repr_add_listener(cc->active_shape_repr, &shape_repr_events, cc); |
3417 | - |
3418 | - cc->active_shape_layer_repr = cc->active_shape_repr->parent(); |
3419 | - Inkscape::GC::anchor(cc->active_shape_layer_repr); |
3420 | - sp_repr_add_listener(cc->active_shape_layer_repr, &layer_repr_events, cc); |
3421 | - } |
3422 | - |
3423 | - |
3424 | - // Set the connection points. |
3425 | - if ( cc->connpthandles.size() ) |
3426 | - // destroy the old list |
3427 | - while (! cc->connpthandles.empty() ) |
3428 | - { |
3429 | - g_object_unref(cc->connpthandles.begin()->first); |
3430 | - cc->connpthandles.erase(cc->connpthandles.begin()); |
3431 | - } |
3432 | - // build the new one |
3433 | - if ( connpts->size() ) |
3434 | - for (std::map<int, ConnectionPoint>::iterator it = connpts->begin(); it != connpts->end(); ++it) |
3435 | - cc_active_shape_add_knot(cc->desktop, item, cc->connpthandles, it->second); |
3436 | - |
3437 | - // Also add default connection points |
3438 | - // For now, only centre default connection point will |
3439 | - // be available |
3440 | - ConnectionPoint centre; |
3441 | - centre.type = ConnPointDefault; |
3442 | - centre.id = ConnPointPosCC; |
3443 | - cc_active_shape_add_knot(cc->desktop, item, cc->connpthandles, centre); |
3444 | - } |
3445 | - else |
3446 | - { |
3447 | - // The active shape didn't change |
3448 | - // Update only the connection point knots |
3449 | - |
3450 | - // Ensure the item's connection_points map |
3451 | - // has been updated |
3452 | - sp_document_ensure_up_to_date(SP_OBJECT_DOCUMENT(item)); |
3453 | - |
3454 | - std::set<int> seen; |
3455 | - for ( ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end() ;) |
3456 | - { |
3457 | - bool removed = false; |
3458 | - if ( it->second.type == ConnPointUserDefined ) |
3459 | - { |
3460 | - std::map<int, ConnectionPoint>::iterator p = connpts->find(it->second.id); |
3461 | - if (p != connpts->end()) |
3462 | - { |
3463 | - if ( it->second != p->second ) |
3464 | - // Connection point position has changed |
3465 | - // Update knot position |
3466 | - sp_knot_set_position(it->first, |
3467 | - item->avoidRef->getConnectionPointPos(it->second.type, it->second.id) * cc->desktop->doc2dt(), 0); |
3468 | - seen.insert(it->second.id); |
3469 | - sp_knot_show(it->first); |
3470 | - } |
3471 | - else |
3472 | - { |
3473 | - // This connection point does no longer exist, |
3474 | - // remove the knot |
3475 | - ConnectionPointMap::iterator curr = it; |
3476 | - ++it; |
3477 | - g_object_unref( curr->first ); |
3478 | - cc->connpthandles.erase(curr); |
3479 | - removed = true; |
3480 | - } |
3481 | - } |
3482 | - else |
3483 | - { |
3484 | - // It's a default connection point |
3485 | - // Just make sure it's position is correct |
3486 | - sp_knot_set_position(it->first, |
3487 | - item->avoidRef->getConnectionPointPos(it->second.type, it->second.id) * cc->desktop->doc2dt(), 0); |
3488 | - sp_knot_show(it->first); |
3489 | - |
3490 | - } |
3491 | - if ( !removed ) |
3492 | - ++it; |
3493 | - } |
3494 | - // Add knots for new connection points. |
3495 | - if (connpts->size()) |
3496 | - for ( std::map<int, ConnectionPoint>::iterator it = connpts->begin(); it != connpts->end(); ++it ) |
3497 | - if ( seen.find(it->first) == seen.end() ) |
3498 | - // A new connection point has been added |
3499 | - // to the shape. Add a knot for it. |
3500 | - cc_active_shape_add_knot(cc->desktop, item, cc->connpthandles, it->second); |
3501 | - } |
3502 | -} |
3503 | - |
3504 | - |
3505 | -static void |
3506 | -cc_set_active_conn(SPConnectorContext *cc, SPItem *item) |
3507 | -{ |
3508 | - g_assert( SP_IS_PATH(item) ); |
3509 | - |
3510 | - SPCurve *curve = SP_PATH(item)->original_curve ? SP_PATH(item)->original_curve : SP_PATH(item)->curve; |
3511 | - Geom::Matrix i2d = sp_item_i2d_affine(item); |
3512 | - |
3513 | - if (cc->active_conn == item) |
3514 | - { |
3515 | - if (curve->is_empty()) |
3516 | - { |
3517 | - // Connector is invisible because it is clipped to the boundary of |
3518 | - // two overlpapping shapes. |
3519 | - sp_knot_hide(cc->endpt_handle[0]); |
3520 | - sp_knot_hide(cc->endpt_handle[1]); |
3521 | - } |
3522 | - else |
3523 | - { |
3524 | - // Just adjust handle positions. |
3525 | - Geom::Point startpt = *(curve->first_point()) * i2d; |
3526 | - sp_knot_set_position(cc->endpt_handle[0], startpt, 0); |
3527 | - |
3528 | - Geom::Point endpt = *(curve->last_point()) * i2d; |
3529 | - sp_knot_set_position(cc->endpt_handle[1], endpt, 0); |
3530 | - } |
3531 | - |
3532 | - return; |
3533 | - } |
3534 | - |
3535 | - cc->active_conn = item; |
3536 | - |
3537 | - // Remove existing active conn listeners |
3538 | - if (cc->active_conn_repr) { |
3539 | - sp_repr_remove_listener_by_data(cc->active_conn_repr, cc); |
3540 | - Inkscape::GC::release(cc->active_conn_repr); |
3541 | - cc->active_conn_repr = NULL; |
3542 | - } |
3543 | - |
3544 | - // Listen in case the active conn changes |
3545 | - cc->active_conn_repr = SP_OBJECT_REPR(item); |
3546 | - if (cc->active_conn_repr) { |
3547 | - Inkscape::GC::anchor(cc->active_conn_repr); |
3548 | - sp_repr_add_listener(cc->active_conn_repr, &shape_repr_events, cc); |
3549 | - } |
3550 | - |
3551 | - for (int i = 0; i < 2; ++i) { |
3552 | - |
3553 | - // Create the handle if it doesn't exist |
3554 | - if ( cc->endpt_handle[i] == NULL ) { |
3555 | - SPKnot *knot = sp_knot_new(cc->desktop, |
3556 | - _("<b>Connector endpoint</b>: drag to reroute or connect to new shapes")); |
3557 | - |
3558 | - knot->setShape(SP_KNOT_SHAPE_SQUARE); |
3559 | - knot->setSize(7); |
3560 | - knot->setAnchor(GTK_ANCHOR_CENTER); |
3561 | - knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff); |
3562 | - knot->setStroke(0x000000ff, 0x000000ff, 0x000000ff); |
3563 | - sp_knot_update_ctrl(knot); |
3564 | - |
3565 | - // We don't want to use the standard knot handler, |
3566 | - // since we don't want this knot to be draggable. |
3567 | - g_signal_handler_disconnect(G_OBJECT(knot->item), |
3568 | - knot->_event_handler_id); |
3569 | - knot->_event_handler_id = 0; |
3570 | - |
3571 | - gtk_signal_connect(GTK_OBJECT(knot->item), "event", |
3572 | - GTK_SIGNAL_FUNC(cc_generic_knot_handler), knot); |
3573 | - |
3574 | - cc->endpt_handle[i] = knot; |
3575 | - } |
3576 | - |
3577 | - // Remove any existing handlers |
3578 | - if (cc->endpt_handler_id[i]) { |
3579 | - g_signal_handlers_disconnect_by_func( |
3580 | - G_OBJECT(cc->endpt_handle[i]->item), |
3581 | - (void*)G_CALLBACK(endpt_handler), (gpointer) cc ); |
3582 | - cc->endpt_handler_id[i] = 0; |
3583 | - } |
3584 | - |
3585 | - // Setup handlers for connector endpoints, this is |
3586 | - // is as 'after' so that cc_generic_knot_handler is |
3587 | - // triggered first for any endpoint. |
3588 | - cc->endpt_handler_id[i] = g_signal_connect_after( |
3589 | - G_OBJECT(cc->endpt_handle[i]->item), "event", |
3590 | - G_CALLBACK(endpt_handler), cc); |
3591 | - } |
3592 | - |
3593 | - if (curve->is_empty()) |
3594 | - { |
3595 | - // Connector is invisible because it is clipped to the boundary |
3596 | - // of two overlpapping shapes. So, it doesn't need endpoints. |
3597 | - return; |
3598 | - } |
3599 | - |
3600 | - Geom::Point startpt = *(curve->first_point()) * i2d; |
3601 | - sp_knot_set_position(cc->endpt_handle[0], startpt, 0); |
3602 | - |
3603 | - Geom::Point endpt = *(curve->last_point()) * i2d; |
3604 | - sp_knot_set_position(cc->endpt_handle[1], endpt, 0); |
3605 | - |
3606 | - sp_knot_show(cc->endpt_handle[0]); |
3607 | - sp_knot_show(cc->endpt_handle[1]); |
3608 | -} |
3609 | - |
3610 | -void cc_create_connection_point(SPConnectorContext* cc) |
3611 | -{ |
3612 | - if (cc->active_shape && cc->state == SP_CONNECTOR_CONTEXT_IDLE) |
3613 | - { |
3614 | - if (cc->selected_handle) |
3615 | - { |
3616 | - cc_deselect_handle( cc->selected_handle ); |
3617 | - } |
3618 | - SPKnot *knot = sp_knot_new(cc->desktop, 0); |
3619 | - // We do not process events on this knot. |
3620 | - g_signal_handler_disconnect(G_OBJECT(knot->item), |
3621 | - knot->_event_handler_id); |
3622 | - knot->_event_handler_id = 0; |
3623 | - |
3624 | - cc_select_handle( knot ); |
3625 | - cc->selected_handle = knot; |
3626 | - sp_knot_show(cc->selected_handle); |
3627 | - cc->state = SP_CONNECTOR_CONTEXT_NEWCONNPOINT; |
3628 | - } |
3629 | -} |
3630 | - |
3631 | -void cc_remove_connection_point(SPConnectorContext* cc) |
3632 | -{ |
3633 | - if (cc->selected_handle && cc->state == SP_CONNECTOR_CONTEXT_IDLE ) |
3634 | - { |
3635 | - cc->active_shape->avoidRef->deleteConnectionPoint(cc->connpthandles[cc->selected_handle]); |
3636 | - cc->selected_handle = NULL; |
3637 | - } |
3638 | -} |
3639 | - |
3640 | -static bool cc_item_is_shape(SPItem *item) |
3641 | -{ |
3642 | - if (SP_IS_PATH(item)) { |
3643 | - SPCurve *curve = (SP_SHAPE(item))->curve; |
3644 | - if ( curve && !(curve->is_closed()) ) { |
3645 | - // Open paths are connectors. |
3646 | - return false; |
3647 | - } |
3648 | - } |
3649 | - else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { |
3650 | - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
3651 | - if (prefs->getBool("/tools/connector/ignoretext", true)) { |
3652 | - // Don't count text as a shape we can connect connector to. |
3653 | - return false; |
3654 | - } |
3655 | - } |
3656 | - return true; |
3657 | -} |
3658 | - |
3659 | - |
3660 | -bool cc_item_is_connector(SPItem *item) |
3661 | -{ |
3662 | - if (SP_IS_PATH(item)) { |
3663 | - bool closed = SP_PATH(item)->original_curve ? SP_PATH(item)->original_curve->is_closed() : SP_PATH(item)->curve->is_closed(); |
3664 | - if (SP_PATH(item)->connEndPair.isAutoRoutingConn() && !closed) { |
3665 | - // To be considered a connector, an object must be a non-closed |
3666 | - // path that is marked with a "inkscape:connector-type" attribute. |
3667 | - return true; |
3668 | - } |
3669 | - } |
3670 | - return false; |
3671 | -} |
3672 | - |
3673 | - |
3674 | -void cc_selection_set_avoid(bool const set_avoid) |
3675 | -{ |
3676 | - SPDesktop *desktop = inkscape_active_desktop(); |
3677 | - if (desktop == NULL) { |
3678 | - return; |
3679 | - } |
3680 | - |
3681 | - SPDocument *document = sp_desktop_document(desktop); |
3682 | - |
3683 | - Inkscape::Selection *selection = sp_desktop_selection(desktop); |
3684 | - |
3685 | - GSList *l = (GSList *) selection->itemList(); |
3686 | - |
3687 | - int changes = 0; |
3688 | - |
3689 | - while (l) { |
3690 | - SPItem *item = (SPItem *) l->data; |
3691 | - |
3692 | - char const *value = (set_avoid) ? "true" : NULL; |
3693 | - |
3694 | - if (cc_item_is_shape(item)) { |
3695 | - sp_object_setAttribute(item, "inkscape:connector-avoid", |
3696 | - value, false); |
3697 | - item->avoidRef->handleSettingChange(); |
3698 | - changes++; |
3699 | - } |
3700 | - |
3701 | - l = l->next; |
3702 | - } |
3703 | - |
3704 | - if (changes == 0) { |
3705 | - desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
3706 | - _("Select <b>at least one non-connector object</b>.")); |
3707 | - return; |
3708 | - } |
3709 | - |
3710 | - char *event_desc = (set_avoid) ? |
3711 | - _("Make connectors avoid selected objects") : |
3712 | - _("Make connectors ignore selected objects"); |
3713 | - sp_document_done(document, SP_VERB_CONTEXT_CONNECTOR, event_desc); |
3714 | -} |
3715 | - |
3716 | - |
3717 | -static void |
3718 | -cc_selection_changed(Inkscape::Selection *selection, gpointer data) |
3719 | -{ |
3720 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(data); |
3721 | - //SPEventContext *ec = SP_EVENT_CONTEXT(cc); |
3722 | - |
3723 | - SPItem *item = selection->singleItem(); |
3724 | - |
3725 | - if (cc->active_conn == item) |
3726 | - { |
3727 | - // Nothing to change. |
3728 | - return; |
3729 | - } |
3730 | - if (item == NULL) |
3731 | - { |
3732 | - cc_clear_active_conn(cc); |
3733 | - return; |
3734 | - } |
3735 | - |
3736 | - if (cc_item_is_connector(item)) { |
3737 | - cc_set_active_conn(cc, item); |
3738 | - } |
3739 | -} |
3740 | - |
3741 | - |
3742 | -static void |
3743 | -shape_event_attr_deleted(Inkscape::XML::Node */*repr*/, Inkscape::XML::Node *child, |
3744 | - Inkscape::XML::Node */*ref*/, gpointer data) |
3745 | -{ |
3746 | - g_assert(data); |
3747 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(data); |
3748 | - |
3749 | - if (child == cc->active_shape_repr) { |
3750 | - // The active shape has been deleted. Clear active shape. |
3751 | - cc_clear_active_shape(cc); |
3752 | - } |
3753 | -} |
3754 | - |
3755 | - |
3756 | -static void |
3757 | -shape_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, |
3758 | - gchar const */*old_value*/, gchar const */*new_value*/, |
3759 | - bool /*is_interactive*/, gpointer data) |
3760 | -{ |
3761 | - g_assert(data); |
3762 | - SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(data); |
3763 | - |
3764 | - // Look for changes that result in onscreen movement. |
3765 | - if (!strcmp(name, "d") || !strcmp(name, "x") || !strcmp(name, "y") || |
3766 | - !strcmp(name, "width") || !strcmp(name, "height") || |
3767 | - !strcmp(name, "transform")) |
3768 | - { |
3769 | - if (repr == cc->active_shape_repr) { |
3770 | - // Active shape has moved. Clear active shape. |
3771 | - cc_clear_active_shape(cc); |
3772 | - } |
3773 | - else if (repr == cc->active_conn_repr) { |
3774 | - // The active conn has been moved. |
3775 | - // Set it again, which just sets new handle positions. |
3776 | - cc_set_active_conn(cc, cc->active_conn); |
3777 | - } |
3778 | - } |
3779 | - else |
3780 | - if ( !strcmp(name, "inkscape:connection-points") ) |
3781 | - if (repr == cc->active_shape_repr) |
3782 | - // The connection points of the active shape |
3783 | - // have changed. Update them. |
3784 | - cc_set_active_shape(cc, cc->active_shape); |
3785 | -} |
3786 | - |
3787 | - |
3788 | -/* |
3789 | - Local Variables: |
3790 | - mode:c++ |
3791 | - c-file-style:"stroustrup" |
3792 | - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
3793 | - indent-tabs-mode:nil |
3794 | - fill-column:99 |
3795 | - End: |
3796 | -*/ |
3797 | -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : |
3798 | |
3799 | === removed directory '.pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/extension' |
3800 | === removed file '.pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/extension/effect.cpp' |
3801 | --- .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/extension/effect.cpp 2013-07-02 17:25:52 +0000 |
3802 | +++ .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/extension/effect.cpp 1970-01-01 00:00:00 +0000 |
3803 | @@ -1,409 +0,0 @@ |
3804 | -/* |
3805 | - * Authors: |
3806 | - * Ted Gould <ted@gould.cx> |
3807 | - * |
3808 | - * Copyright (C) 2002-2007 Authors |
3809 | - * |
3810 | - * Released under GNU GPL, read the file 'COPYING' for more information |
3811 | - */ |
3812 | - |
3813 | -#include "inkscape-private.h" |
3814 | -#include "helper/action.h" |
3815 | -#include "ui/view/view.h" |
3816 | -#include "desktop-handles.h" |
3817 | -#include "selection.h" |
3818 | -#include "sp-namedview.h" |
3819 | -#include "desktop.h" |
3820 | -#include "implementation/implementation.h" |
3821 | -#include "effect.h" |
3822 | -#include "execution-env.h" |
3823 | -#include "timer.h" |
3824 | - |
3825 | - |
3826 | - |
3827 | -/* Inkscape::Extension::Effect */ |
3828 | - |
3829 | -namespace Inkscape { |
3830 | -namespace Extension { |
3831 | - |
3832 | -Effect * Effect::_last_effect = NULL; |
3833 | -Inkscape::XML::Node * Effect::_effects_list = NULL; |
3834 | -Inkscape::XML::Node * Effect::_filters_list = NULL; |
3835 | - |
3836 | -#define EFFECTS_LIST "effects-list" |
3837 | -#define FILTERS_LIST "filters-list" |
3838 | - |
3839 | -Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp) |
3840 | - : Extension(in_repr, in_imp), |
3841 | - _id_noprefs(Glib::ustring(get_id()) + ".noprefs"), |
3842 | - _name_noprefs(Glib::ustring(get_name()) + _(" (No preferences)")), |
3843 | - _verb(get_id(), get_name(), NULL, NULL, this, true), |
3844 | - _verb_nopref(_id_noprefs.c_str(), _name_noprefs.c_str(), NULL, NULL, this, false), |
3845 | - _menu_node(NULL), _workingDialog(true), |
3846 | - _prefDialog(NULL) |
3847 | -{ |
3848 | - Inkscape::XML::Node * local_effects_menu = NULL; |
3849 | - |
3850 | - // This is a weird hack |
3851 | - if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow")) |
3852 | - return; |
3853 | - |
3854 | - bool hidden = false; |
3855 | - |
3856 | - no_doc = false; |
3857 | - no_live_preview = false; |
3858 | - |
3859 | - if (repr != NULL) { |
3860 | - |
3861 | - for (Inkscape::XML::Node *child = sp_repr_children(repr); child != NULL; child = child->next()) { |
3862 | - if (!strcmp(child->name(), INKSCAPE_EXTENSION_NS "effect")) { |
3863 | - if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "false")) { |
3864 | - no_doc = true; |
3865 | - } |
3866 | - if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) { |
3867 | - no_live_preview = true; |
3868 | - } |
3869 | - for (Inkscape::XML::Node *effect_child = sp_repr_children(child); effect_child != NULL; effect_child = effect_child->next()) { |
3870 | - if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) { |
3871 | - // printf("Found local effects menu in %s\n", this->get_name()); |
3872 | - local_effects_menu = sp_repr_children(effect_child); |
3873 | - if (effect_child->attribute("hidden") && !strcmp(effect_child->attribute("hidden"), "true")) { |
3874 | - hidden = true; |
3875 | - } |
3876 | - } |
3877 | - if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-name") || |
3878 | - !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-name")) { |
3879 | - // printf("Found local effects menu in %s\n", this->get_name()); |
3880 | - _verb.set_name(sp_repr_children(effect_child)->content()); |
3881 | - } |
3882 | - if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-tip") || |
3883 | - !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-tip")) { |
3884 | - // printf("Found local effects menu in %s\n", this->get_name()); |
3885 | - _verb.set_tip(sp_repr_children(effect_child)->content()); |
3886 | - } |
3887 | - } // children of "effect" |
3888 | - break; // there can only be one effect |
3889 | - } // find "effect" |
3890 | - } // children of "inkscape-extension" |
3891 | - } // if we have an XML file |
3892 | - |
3893 | - if (INKSCAPE != NULL) { |
3894 | - if (_effects_list == NULL) |
3895 | - _effects_list = find_menu(inkscape_get_menus(INKSCAPE), EFFECTS_LIST); |
3896 | - if (_filters_list == NULL) |
3897 | - _filters_list = find_menu(inkscape_get_menus(INKSCAPE), FILTERS_LIST); |
3898 | - } |
3899 | - |
3900 | - if ((_effects_list != NULL || _filters_list != NULL)) { |
3901 | - Inkscape::XML::Document *xml_doc; |
3902 | - xml_doc = _effects_list->document(); |
3903 | - _menu_node = xml_doc->createElement("verb"); |
3904 | - _menu_node->setAttribute("verb-id", this->get_id(), false); |
3905 | - |
3906 | - if (!hidden) { |
3907 | - if (_filters_list && |
3908 | - local_effects_menu && |
3909 | - local_effects_menu->attribute("name") && |
3910 | - !strcmp(local_effects_menu->attribute("name"), ("Filters"))) { |
3911 | - merge_menu(_filters_list->parent(), _filters_list, sp_repr_children(local_effects_menu), _menu_node); |
3912 | - } else if (_effects_list) { |
3913 | - merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node); |
3914 | - } |
3915 | - } |
3916 | - } |
3917 | - |
3918 | - return; |
3919 | -} |
3920 | - |
3921 | -void |
3922 | -Effect::merge_menu (Inkscape::XML::Node * base, |
3923 | - Inkscape::XML::Node * start, |
3924 | - Inkscape::XML::Node * patern, |
3925 | - Inkscape::XML::Node * mergee) { |
3926 | - Glib::ustring mergename; |
3927 | - Inkscape::XML::Node * tomerge = NULL; |
3928 | - Inkscape::XML::Node * submenu = NULL; |
3929 | - |
3930 | - /* printf("Merge menu with '%s' '%s' '%s'\n", |
3931 | - base != NULL ? base->name() : "NULL", |
3932 | - patern != NULL ? patern->name() : "NULL", |
3933 | - mergee != NULL ? mergee->name() : "NULL"); */ |
3934 | - |
3935 | - if (patern == NULL) { |
3936 | - // Merge the verb name |
3937 | - tomerge = mergee; |
3938 | - mergename = _(this->get_name()); |
3939 | - } else { |
3940 | - gchar const * menuname = patern->attribute("name"); |
3941 | - if (menuname == NULL) menuname = patern->attribute("_name"); |
3942 | - if (menuname == NULL) return; |
3943 | - |
3944 | - Inkscape::XML::Document *xml_doc; |
3945 | - xml_doc = base->document(); |
3946 | - tomerge = xml_doc->createElement("submenu"); |
3947 | - tomerge->setAttribute("name", menuname, false); |
3948 | - |
3949 | - mergename = _(menuname); |
3950 | - } |
3951 | - |
3952 | - int position = -1; |
3953 | - |
3954 | - if (start != NULL) { |
3955 | - Inkscape::XML::Node * menupass; |
3956 | - for (menupass = start; menupass != NULL && strcmp(menupass->name(), "separator"); menupass = menupass->next()) { |
3957 | - gchar const * compare_char = NULL; |
3958 | - if (!strcmp(menupass->name(), "verb")) { |
3959 | - gchar const * verbid = menupass->attribute("verb-id"); |
3960 | - Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid); |
3961 | - if (verb == NULL) { |
3962 | - g_warning("Unable to find verb '%s' which is referred to in the menus.", verbid); |
3963 | - continue; |
3964 | - } |
3965 | - compare_char = verb->get_name(); |
3966 | - } else if (!strcmp(menupass->name(), "submenu")) { |
3967 | - compare_char = menupass->attribute("name"); |
3968 | - if (compare_char == NULL) |
3969 | - compare_char = menupass->attribute("_name"); |
3970 | - } |
3971 | - |
3972 | - position = menupass->position() + 1; |
3973 | - |
3974 | - /* This will cause us to skip tags we don't understand */ |
3975 | - if (compare_char == NULL) { |
3976 | - continue; |
3977 | - } |
3978 | - |
3979 | - Glib::ustring compare(_(compare_char)); |
3980 | - |
3981 | - if (mergename == compare) { |
3982 | - Inkscape::GC::release(tomerge); |
3983 | - tomerge = NULL; |
3984 | - submenu = menupass; |
3985 | - break; |
3986 | - } |
3987 | - |
3988 | - if (mergename < compare) { |
3989 | - position = menupass->position(); |
3990 | - break; |
3991 | - } |
3992 | - } // for menu items |
3993 | - } // start != NULL |
3994 | - |
3995 | - if (tomerge != NULL) { |
3996 | - base->appendChild(tomerge); |
3997 | - Inkscape::GC::release(tomerge); |
3998 | - if (position != -1) |
3999 | - tomerge->setPosition(position); |
4000 | - } |
4001 | - |
4002 | - if (patern != NULL) { |
4003 | - if (submenu == NULL) |
4004 | - submenu = tomerge; |
4005 | - merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee); |
4006 | - } |
4007 | - |
4008 | - return; |
4009 | -} |
4010 | - |
4011 | -Effect::~Effect (void) |
4012 | -{ |
4013 | - if (get_last_effect() == this) |
4014 | - set_last_effect(NULL); |
4015 | - if (_menu_node) |
4016 | - Inkscape::GC::release(_menu_node); |
4017 | - return; |
4018 | -} |
4019 | - |
4020 | -bool |
4021 | -Effect::check (void) |
4022 | -{ |
4023 | - if (!Extension::check()) { |
4024 | - /** \todo Check to see if parent has this as its only child, |
4025 | - if so, delete it too */ |
4026 | - if (_menu_node != NULL) |
4027 | - sp_repr_unparent(_menu_node); |
4028 | - _menu_node = NULL; |
4029 | - return false; |
4030 | - } |
4031 | - return true; |
4032 | -} |
4033 | - |
4034 | -bool |
4035 | -Effect::prefs (Inkscape::UI::View::View * doc) |
4036 | -{ |
4037 | - if (_prefDialog != NULL) { |
4038 | - _prefDialog->raise(); |
4039 | - return true; |
4040 | - } |
4041 | - |
4042 | - if (param_visible_count() == 0) { |
4043 | - effect(doc); |
4044 | - return true; |
4045 | - } |
4046 | - |
4047 | - if (!loaded()) |
4048 | - set_state(Extension::STATE_LOADED); |
4049 | - if (!loaded()) return false; |
4050 | - |
4051 | - _prefDialog = new PrefDialog(this->get_name(), this->get_help(), NULL, this); |
4052 | - _prefDialog->show(); |
4053 | - |
4054 | - return true; |
4055 | -} |
4056 | - |
4057 | -/** |
4058 | - \brief The function that 'does' the effect itself |
4059 | - \param doc The Inkscape::UI::View::View to do the effect on |
4060 | - |
4061 | - This function first insures that the extension is loaded, and if not, |
4062 | - loads it. It then calls the implemention to do the actual work. It |
4063 | - also resets the last effect pointer to be this effect. Finally, it |
4064 | - executes a \c sp_document_done to commit the changes to the undo |
4065 | - stack. |
4066 | -*/ |
4067 | -void |
4068 | -Effect::effect (Inkscape::UI::View::View * doc) |
4069 | -{ |
4070 | - //printf("Execute effect\n"); |
4071 | - if (!loaded()) |
4072 | - set_state(Extension::STATE_LOADED); |
4073 | - if (!loaded()) return; |
4074 | - |
4075 | - |
4076 | - ExecutionEnv executionEnv(this, doc); |
4077 | - timer->lock(); |
4078 | - executionEnv.run(); |
4079 | - if (executionEnv.wait()) { |
4080 | - executionEnv.commit(); |
4081 | - } else { |
4082 | - executionEnv.cancel(); |
4083 | - } |
4084 | - timer->unlock(); |
4085 | - |
4086 | - return; |
4087 | -} |
4088 | - |
4089 | -/** \brief Sets which effect was called last |
4090 | - \param in_effect The effect that has been called |
4091 | - |
4092 | - This function sets the static variable \c _last_effect and it |
4093 | - ensures that the last effect verb is sensitive. |
4094 | - |
4095 | - If the \c in_effect variable is \c NULL then the last effect |
4096 | - verb is made insesitive. |
4097 | -*/ |
4098 | -void |
4099 | -Effect::set_last_effect (Effect * in_effect) |
4100 | -{ |
4101 | - gchar const * verb_id = in_effect->get_verb()->get_id(); |
4102 | - gchar const * help_id_prefix = "org.inkscape.help."; |
4103 | - |
4104 | - // We don't want these "effects" to register as the last effect, |
4105 | - // this wouldn't be helpful to the user who selects a real effect, |
4106 | - // then goes to the help file (implemented as an effect), then goes |
4107 | - // back to the effect, only to see it written over by the help file |
4108 | - // selection. |
4109 | - |
4110 | - // This snippet should fix this bug: |
4111 | - // https://bugs.launchpad.net/inkscape/+bug/600671 |
4112 | - if (strncmp(verb_id, help_id_prefix, strlen(help_id_prefix)) == 0) return; |
4113 | - |
4114 | - if (in_effect == NULL) { |
4115 | - Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false); |
4116 | - Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false); |
4117 | - } else if (_last_effect == NULL) { |
4118 | - Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true); |
4119 | - Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true); |
4120 | - } |
4121 | - |
4122 | - _last_effect = in_effect; |
4123 | - return; |
4124 | -} |
4125 | - |
4126 | -Inkscape::XML::Node * |
4127 | -Effect::find_menu (Inkscape::XML::Node * menustruct, const gchar *name) |
4128 | -{ |
4129 | - if (menustruct == NULL) return false; |
4130 | - for (Inkscape::XML::Node * child = menustruct; |
4131 | - child != NULL; |
4132 | - child = child->next()) { |
4133 | - if (!strcmp(child->name(), name)) { |
4134 | - return child; |
4135 | - } |
4136 | - Inkscape::XML::Node * firstchild = child->firstChild(); |
4137 | - if (firstchild != NULL) { |
4138 | - Inkscape::XML::Node *found = find_menu (firstchild, name); |
4139 | - if (found) |
4140 | - return found; |
4141 | - } |
4142 | - } |
4143 | - return NULL; |
4144 | -} |
4145 | - |
4146 | - |
4147 | -Gtk::VBox * |
4148 | -Effect::get_info_widget(void) |
4149 | -{ |
4150 | - return Extension::get_info_widget(); |
4151 | -} |
4152 | - |
4153 | -void |
4154 | -Effect::set_pref_dialog (PrefDialog * prefdialog) |
4155 | -{ |
4156 | - _prefDialog = prefdialog; |
4157 | - return; |
4158 | -} |
4159 | - |
4160 | -/** \brief Create an action for a \c EffectVerb |
4161 | - \param view Which view the action should be created for |
4162 | - \return The built action. |
4163 | - |
4164 | - Calls \c make_action_helper with the \c vector. |
4165 | -*/ |
4166 | -SPAction * |
4167 | -Effect::EffectVerb::make_action (Inkscape::UI::View::View * view) |
4168 | -{ |
4169 | - return make_action_helper(view, &vector, static_cast<void *>(this)); |
4170 | -} |
4171 | - |
4172 | -/** \brief Decode the verb code and take appropriate action */ |
4173 | -void |
4174 | -Effect::EffectVerb::perform( SPAction *action, void * data, void */*pdata*/ ) |
4175 | -{ |
4176 | - Inkscape::UI::View::View * current_view = sp_action_get_view(action); |
4177 | -// SPDocument * current_document = current_view->doc; |
4178 | - Effect::EffectVerb * ev = reinterpret_cast<Effect::EffectVerb *>(data); |
4179 | - Effect * effect = ev->_effect; |
4180 | - |
4181 | - if (effect == NULL) return; |
4182 | - if (current_view == NULL) return; |
4183 | - |
4184 | - if (ev->_showPrefs) { |
4185 | - effect->prefs(current_view); |
4186 | - } else { |
4187 | - effect->effect(current_view); |
4188 | - } |
4189 | - |
4190 | - return; |
4191 | -} |
4192 | - |
4193 | -/** |
4194 | - * Action vector to define functions called if a staticly defined file verb |
4195 | - * is called. |
4196 | - */ |
4197 | -SPActionEventVector Effect::EffectVerb::vector = |
4198 | - {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL}; |
4199 | - |
4200 | - |
4201 | -} } /* namespace Inkscape, Extension */ |
4202 | - |
4203 | -/* |
4204 | - Local Variables: |
4205 | - mode:c++ |
4206 | - c-file-style:"stroustrup" |
4207 | - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
4208 | - indent-tabs-mode:nil |
4209 | - fill-column:99 |
4210 | - End: |
4211 | -*/ |
4212 | -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |
4213 | |
4214 | === removed file '.pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/gradient-drag.cpp' |
4215 | --- .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/gradient-drag.cpp 2013-07-02 17:25:52 +0000 |
4216 | +++ .pc/0004-Fix_FTBFS_on_gcc-4.8.patch/src/gradient-drag.cpp 1970-01-01 00:00:00 +0000 |
4217 | @@ -1,2216 +0,0 @@ |
4218 | -/* |
4219 | - * On-canvas gradient dragging |
4220 | - * |
4221 | - * Authors: |
4222 | - * bulia byak <buliabyak@users.sf.net> |
4223 | - * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> |
4224 | - * Jon A. Cruz <jon@joncruz.org> |
4225 | - * |
4226 | - * Copyright (C) 2007 Johan Engelen |
4227 | - * Copyright (C) 2005,2010 Authors |
4228 | - * |
4229 | - * Released under GNU GPL, read the file 'COPYING' for more information |
4230 | - */ |
4231 | - |
4232 | -#ifdef HAVE_CONFIG_H |
4233 | -#include "config.h" |
4234 | -#endif |
4235 | - |
4236 | -#include <glibmm/i18n.h> |
4237 | -#include <cstring> |
4238 | -#include <string> |
4239 | - |
4240 | -#include "desktop-handles.h" |
4241 | -#include "selection.h" |
4242 | -#include "desktop.h" |
4243 | -#include "desktop-style.h" |
4244 | -#include "document.h" |
4245 | -#include "display/sp-ctrlline.h" |
4246 | -#include "display/sp-canvas-util.h" |
4247 | -#include "xml/repr.h" |
4248 | -#include "svg/css-ostringstream.h" |
4249 | -#include "svg/svg.h" |
4250 | -#include "libnr/nr-point-fns.h" |
4251 | -#include "preferences.h" |
4252 | -#include "sp-item.h" |
4253 | -#include "style.h" |
4254 | -#include "knot.h" |
4255 | -#include "sp-linear-gradient.h" |
4256 | -#include "sp-radial-gradient.h" |
4257 | -#include "gradient-chemistry.h" |
4258 | -#include "gradient-drag.h" |
4259 | -#include "sp-stop.h" |
4260 | -#include "snap.h" |
4261 | -#include "sp-namedview.h" |
4262 | -#include "selection-chemistry.h" |
4263 | - |
4264 | -#define GR_KNOT_COLOR_NORMAL 0xffffff00 |
4265 | -#define GR_KNOT_COLOR_MOUSEOVER 0xff000000 |
4266 | -#define GR_KNOT_COLOR_SELECTED 0x0000ff00 |
4267 | - |
4268 | -#define GR_LINE_COLOR_FILL 0x0000ff7f |
4269 | -#define GR_LINE_COLOR_STROKE 0x9999007f |
4270 | - |
4271 | -// screen pixels between knots when they snap: |
4272 | -#define SNAP_DIST 5 |
4273 | - |
4274 | -// absolute distance between gradient points for them to become a single dragger when the drag is created: |
4275 | -#define MERGE_DIST 0.1 |
4276 | - |
4277 | -// knot shapes corresponding to GrPointType enum |
4278 | -SPKnotShapeType gr_knot_shapes [] = { |
4279 | - SP_KNOT_SHAPE_SQUARE, //POINT_LG_BEGIN |
4280 | - SP_KNOT_SHAPE_CIRCLE, //POINT_LG_END |
4281 | - SP_KNOT_SHAPE_DIAMOND, //POINT_LG_MID |
4282 | - SP_KNOT_SHAPE_SQUARE, // POINT_RG_CENTER |
4283 | - SP_KNOT_SHAPE_CIRCLE, // POINT_RG_R1 |
4284 | - SP_KNOT_SHAPE_CIRCLE, // POINT_RG_R2 |
4285 | - SP_KNOT_SHAPE_CROSS, // POINT_RG_FOCUS |
4286 | - SP_KNOT_SHAPE_DIAMOND, //POINT_RG_MID1 |
4287 | - SP_KNOT_SHAPE_DIAMOND //POINT_RG_MID2 |
4288 | -}; |
4289 | - |
4290 | -const gchar *gr_knot_descr [] = { |
4291 | - N_("Linear gradient <b>start</b>"), //POINT_LG_BEGIN |
4292 | - N_("Linear gradient <b>end</b>"), |
4293 | - N_("Linear gradient <b>mid stop</b>"), |
4294 | - N_("Radial gradient <b>center</b>"), |
4295 | - N_("Radial gradient <b>radius</b>"), |
4296 | - N_("Radial gradient <b>radius</b>"), |
4297 | - N_("Radial gradient <b>focus</b>"), // POINT_RG_FOCUS |
4298 | - N_("Radial gradient <b>mid stop</b>"), |
4299 | - N_("Radial gradient <b>mid stop</b>") |
4300 | -}; |
4301 | - |
4302 | -static void |
4303 | -gr_drag_sel_changed(Inkscape::Selection */*selection*/, gpointer data) |
4304 | -{ |
4305 | - GrDrag *drag = (GrDrag *) data; |
4306 | - drag->updateDraggers (); |
4307 | - drag->updateLines (); |
4308 | - drag->updateLevels (); |
4309 | -} |
4310 | - |
4311 | -static void |
4312 | -gr_drag_sel_modified (Inkscape::Selection */*selection*/, guint /*flags*/, gpointer data) |
4313 | -{ |
4314 | - GrDrag *drag = (GrDrag *) data; |
4315 | - if (drag->local_change) { |
4316 | - drag->local_change = false; |
4317 | - } else { |
4318 | - drag->updateDraggers (); |
4319 | - } |
4320 | - drag->updateLines (); |
4321 | - drag->updateLevels (); |
4322 | -} |
4323 | - |
4324 | -/** |
4325 | -When a _query_style_signal is received, check that \a property requests fill/stroke/opacity (otherwise |
4326 | -skip), and fill the \a style with the averaged color of all draggables of the selected dragger, if |
4327 | -any. |
4328 | -*/ |
4329 | -int |
4330 | -gr_drag_style_query (SPStyle *style, int property, gpointer data) |
4331 | -{ |
4332 | - GrDrag *drag = (GrDrag *) data; |
4333 | - |
4334 | - if (property != QUERY_STYLE_PROPERTY_FILL && property != QUERY_STYLE_PROPERTY_STROKE && property != QUERY_STYLE_PROPERTY_MASTEROPACITY) { |
4335 | - return QUERY_STYLE_NOTHING; |
4336 | - } |
4337 | - |
4338 | - if (!drag->selected) { |
4339 | - return QUERY_STYLE_NOTHING; |
4340 | - } else { |
4341 | - int ret = QUERY_STYLE_NOTHING; |
4342 | - |
4343 | - float cf[4]; |
4344 | - cf[0] = cf[1] = cf[2] = cf[3] = 0; |
4345 | - |
4346 | - int count = 0; |
4347 | - |
4348 | - for (GList *i = drag->selected; i != NULL; i = i->next) { // for all selected draggers |
4349 | - GrDragger *d = (GrDragger *) i->data; |
4350 | - for (GSList const* j = d->draggables; j != NULL; j = j->next) { // for all draggables of dragger |
4351 | - GrDraggable *draggable = (GrDraggable *) j->data; |
4352 | - |
4353 | - if (ret == QUERY_STYLE_NOTHING) { |
4354 | - ret = QUERY_STYLE_SINGLE; |
4355 | - } else if (ret == QUERY_STYLE_SINGLE) { |
4356 | - ret = QUERY_STYLE_MULTIPLE_AVERAGED; |
4357 | - } |
4358 | - |
4359 | - guint32 c = sp_item_gradient_stop_query_style (draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke); |
4360 | - cf[0] += SP_RGBA32_R_F (c); |
4361 | - cf[1] += SP_RGBA32_G_F (c); |
4362 | - cf[2] += SP_RGBA32_B_F (c); |
4363 | - cf[3] += SP_RGBA32_A_F (c); |
4364 | - |
4365 | - count ++; |
4366 | - } |
4367 | - } |
4368 | - |
4369 | - if (count) { |
4370 | - cf[0] /= count; |
4371 | - cf[1] /= count; |
4372 | - cf[2] /= count; |
4373 | - cf[3] /= count; |
4374 | - |
4375 | - // set both fill and stroke with our stop-color and stop-opacity |
4376 | - style->fill.clear(); |
4377 | - style->fill.setColor( cf[0], cf[1], cf[2] ); |
4378 | - style->fill.set = TRUE; |
4379 | - style->stroke.clear(); |
4380 | - style->stroke.setColor( cf[0], cf[1], cf[2] ); |
4381 | - style->stroke.set = TRUE; |
4382 | - |
4383 | - style->fill_opacity.value = SP_SCALE24_FROM_FLOAT (1.0); |
4384 | - style->fill_opacity.set = TRUE; |
4385 | - style->stroke_opacity.value = SP_SCALE24_FROM_FLOAT (1.0); |
4386 | - style->stroke_opacity.set = TRUE; |
4387 | - |
4388 | - style->opacity.value = SP_SCALE24_FROM_FLOAT (cf[3]); |
4389 | - style->opacity.set = TRUE; |
4390 | - } |
4391 | - |
4392 | - return ret; |
4393 | - } |
4394 | -} |
4395 | - |
4396 | -Glib::ustring GrDrag::makeStopSafeColor( gchar const *str, bool &isNull ) |
4397 | -{ |
4398 | - Glib::ustring colorStr; |
4399 | - if ( str ) { |
4400 | - isNull = false; |
4401 | - colorStr = str; |
4402 | - Glib::ustring::size_type pos = colorStr.find("url(#"); |
4403 | - if ( pos != Glib::ustring::npos ) { |
4404 | - Glib::ustring targetName = colorStr.substr(pos + 5, colorStr.length() - 6); |
4405 | - const GSList *gradients = sp_document_get_resource_list(desktop->doc(), "gradient"); |
4406 | - for (const GSList *item = gradients; item; item = item->next) { |
4407 | - SPGradient* grad = SP_GRADIENT(item->data); |
4408 | - if ( targetName == grad->getId() ) { |
4409 | - SPGradient *vect = grad->getVector(); |
4410 | - SPStop *firstStop = (vect) ? vect->getFirstStop() : grad->getFirstStop(); |
4411 | - if (firstStop) { |
4412 | - Glib::ustring stopColorStr; |
4413 | - if (firstStop->currentColor) { |
4414 | - stopColorStr = sp_object_get_style_property(firstStop, "color", NULL); |
4415 | - } else { |
4416 | - stopColorStr = firstStop->specified_color.toString(); |
4417 | - } |
4418 | - if ( !stopColorStr.empty() ) { |
4419 | - colorStr = stopColorStr; |
4420 | - } |
4421 | - } |
4422 | - break; |
4423 | - } |
4424 | - } |
4425 | - } |
4426 | - } else { |
4427 | - isNull = true; |
4428 | - } |
4429 | - |
4430 | - return colorStr; |
4431 | -} |
4432 | - |
4433 | -bool GrDrag::styleSet( const SPCSSAttr *css ) |
4434 | -{ |
4435 | - if (!selected) { |
4436 | - return false; |
4437 | - } |
4438 | - |
4439 | - SPCSSAttr *stop = sp_repr_css_attr_new(); |
4440 | - |
4441 | - // See if the css contains interesting properties, and if so, translate them into the format |
4442 | - // acceptable for gradient stops |
4443 | - |
4444 | - // any of color properties, in order of increasing priority: |
4445 | - if (css->attribute("flood-color")) { |
4446 | - sp_repr_css_set_property (stop, "stop-color", css->attribute("flood-color")); |
4447 | - } |
4448 | - |
4449 | - if (css->attribute("lighting-color")) { |
4450 | - sp_repr_css_set_property (stop, "stop-color", css->attribute("lighting-color")); |
4451 | - } |
4452 | - |
4453 | - if (css->attribute("color")) { |
4454 | - sp_repr_css_set_property (stop, "stop-color", css->attribute("color")); |
4455 | - } |
4456 | - |
4457 | - if (css->attribute("stroke") && strcmp(css->attribute("stroke"), "none")) { |
4458 | - sp_repr_css_set_property (stop, "stop-color", css->attribute("stroke")); |
4459 | - } |
4460 | - |
4461 | - if (css->attribute("fill") && strcmp(css->attribute("fill"), "none")) { |
4462 | - sp_repr_css_set_property (stop, "stop-color", css->attribute("fill")); |
4463 | - } |
4464 | - |
4465 | - if (css->attribute("stop-color")) { |
4466 | - sp_repr_css_set_property (stop, "stop-color", css->attribute("stop-color")); |
4467 | - } |
4468 | - |
4469 | - // Make sure the style is allowed for gradient stops. |
4470 | - if ( !sp_repr_css_property_is_unset( stop, "stop-color") ) { |
4471 | - bool stopIsNull = false; |
4472 | - Glib::ustring tmp = makeStopSafeColor( sp_repr_css_property( stop, "stop-color", "" ), stopIsNull ); |
4473 | - if ( !stopIsNull && !tmp.empty() ) { |
4474 | - sp_repr_css_set_property( stop, "stop-color", tmp.c_str() ); |
4475 | - } |
4476 | - } |
4477 | - |
4478 | - |
4479 | - if (css->attribute("stop-opacity")) { // direct setting of stop-opacity has priority |
4480 | - sp_repr_css_set_property(stop, "stop-opacity", css->attribute("stop-opacity")); |
4481 | - } else { // multiply all opacity properties: |
4482 | - gdouble accumulated = 1.0; |
4483 | - accumulated *= sp_svg_read_percentage(css->attribute("flood-opacity"), 1.0); |
4484 | - accumulated *= sp_svg_read_percentage(css->attribute("opacity"), 1.0); |
4485 | - accumulated *= sp_svg_read_percentage(css->attribute("stroke-opacity"), 1.0); |
4486 | - accumulated *= sp_svg_read_percentage(css->attribute("fill-opacity"), 1.0); |
4487 | - |
4488 | - Inkscape::CSSOStringStream os; |
4489 | - os << accumulated; |
4490 | - sp_repr_css_set_property(stop, "stop-opacity", os.str().c_str()); |
4491 | - |
4492 | - if ((css->attribute("fill") && !css->attribute("stroke") && !strcmp(css->attribute("fill"), "none")) || |
4493 | - (css->attribute("stroke") && !css->attribute("fill") && !strcmp(css->attribute("stroke"), "none"))) { |
4494 | - sp_repr_css_set_property(stop, "stop-opacity", "0"); // if a single fill/stroke property is set to none, don't change color, set opacity to 0 |
4495 | - } |
4496 | - } |
4497 | - |
4498 | - if (!stop->attributeList()) { // nothing for us here, pass it on |
4499 | - sp_repr_css_attr_unref(stop); |
4500 | - return false; |
4501 | - } |
4502 | - |
4503 | - for (GList const* sel = selected; sel != NULL; sel = sel->next) { // for all selected draggers |
4504 | - GrDragger* dragger = reinterpret_cast<GrDragger*>(sel->data); |
4505 | - for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger |
4506 | - GrDraggable *draggable = reinterpret_cast<GrDraggable *>(i->data); |
4507 | - |
4508 | - local_change = true; |
4509 | - sp_item_gradient_stop_set_style(draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke, stop); |
4510 | - } |
4511 | - } |
4512 | - |
4513 | - //sp_repr_css_print(stop); |
4514 | - sp_repr_css_attr_unref(stop); |
4515 | - return true; |
4516 | -} |
4517 | - |
4518 | -guint32 GrDrag::getColor() |
4519 | -{ |
4520 | - if (!selected) return 0; |
4521 | - |
4522 | - float cf[4]; |
4523 | - cf[0] = cf[1] = cf[2] = cf[3] = 0; |
4524 | - |
4525 | - int count = 0; |
4526 | - |
4527 | - for (GList *i = selected; i != NULL; i = i->next) { // for all selected draggers |
4528 | - GrDragger *d = (GrDragger *) i->data; |
4529 | - for (GSList const* j = d->draggables; j != NULL; j = j->next) { // for all draggables of dragger |
4530 | - GrDraggable *draggable = (GrDraggable *) j->data; |
4531 | - |
4532 | - guint32 c = sp_item_gradient_stop_query_style (draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke); |
4533 | - cf[0] += SP_RGBA32_R_F (c); |
4534 | - cf[1] += SP_RGBA32_G_F (c); |
4535 | - cf[2] += SP_RGBA32_B_F (c); |
4536 | - cf[3] += SP_RGBA32_A_F (c); |
4537 | - |
4538 | - count ++; |
4539 | - } |
4540 | - } |
4541 | - |
4542 | - if (count) { |
4543 | - cf[0] /= count; |
4544 | - cf[1] /= count; |
4545 | - cf[2] /= count; |
4546 | - cf[3] /= count; |
4547 | - } |
4548 | - |
4549 | - return SP_RGBA32_F_COMPOSE(cf[0], cf[1], cf[2], cf[3]); |
4550 | -} |
4551 | - |
4552 | -SPStop * |
4553 | -GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance) |
4554 | -{ |
4555 | - gfloat offset; // type of SPStop.offset = gfloat |
4556 | - SPGradient *gradient; |
4557 | - bool fill_or_stroke = true; |
4558 | - bool r1_knot = false; |
4559 | - |
4560 | - bool addknot = false; |
4561 | - do { |
4562 | - gradient = sp_item_gradient (item, fill_or_stroke); |
4563 | - if (SP_IS_LINEARGRADIENT(gradient)) { |
4564 | - Geom::Point begin = sp_item_gradient_get_coords(item, POINT_LG_BEGIN, 0, fill_or_stroke); |
4565 | - Geom::Point end = sp_item_gradient_get_coords(item, POINT_LG_END, 0, fill_or_stroke); |
4566 | - |
4567 | - Geom::Point nearest = snap_vector_midpoint (mouse_p, begin, end, 0); |
4568 | - double dist_screen = Geom::L2 (mouse_p - nearest); |
4569 | - if ( dist_screen < tolerance ) { |
4570 | - // add the knot |
4571 | - offset = get_offset_between_points(nearest, begin, end); |
4572 | - addknot = true; |
4573 | - break; // break out of the while loop: add only one knot |
4574 | - } |
4575 | - } else if (SP_IS_RADIALGRADIENT(gradient)) { |
4576 | - Geom::Point begin = sp_item_gradient_get_coords(item, POINT_RG_CENTER, 0, fill_or_stroke); |
4577 | - Geom::Point end = sp_item_gradient_get_coords(item, POINT_RG_R1, 0, fill_or_stroke); |
4578 | - Geom::Point nearest = snap_vector_midpoint (mouse_p, begin, end, 0); |
4579 | - double dist_screen = Geom::L2 (mouse_p - nearest); |
4580 | - if ( dist_screen < tolerance ) { |
4581 | - offset = get_offset_between_points(nearest, begin, end); |
4582 | - addknot = true; |
4583 | - r1_knot = true; |
4584 | - break; // break out of the while loop: add only one knot |
4585 | - } |
4586 | - |
4587 | - end = sp_item_gradient_get_coords(item, POINT_RG_R2, 0, fill_or_stroke); |
4588 | - nearest = snap_vector_midpoint (mouse_p, begin, end, 0); |
4589 | - dist_screen = Geom::L2 (mouse_p - nearest); |
4590 | - if ( dist_screen < tolerance ) { |
4591 | - offset = get_offset_between_points(nearest, begin, end); |
4592 | - addknot = true; |
4593 | - r1_knot = false; |
4594 | - break; // break out of the while loop: add only one knot |
4595 | - } |
4596 | - } |
4597 | - fill_or_stroke = !fill_or_stroke; |
4598 | - } while (!fill_or_stroke && !addknot) ; |
4599 | - |
4600 | - if (addknot) { |
4601 | - SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (gradient, false); |
4602 | - SPStop* prev_stop = vector->getFirstStop(); |
4603 | - SPStop* next_stop = prev_stop->getNextStop(); |
4604 | - guint i = 1; |
4605 | - while ( (next_stop) && (next_stop->offset < offset) ) { |
4606 | - prev_stop = next_stop; |
4607 | - next_stop = next_stop->getNextStop(); |
4608 | - i++; |
4609 | - } |
4610 | - if (!next_stop) { |
4611 | - // logical error: the endstop should have offset 1 and should always be more than this offset here |
4612 | - return NULL; |
4613 | - } |
4614 | - |
4615 | - |
4616 | - SPStop *newstop = sp_vector_add_stop (vector, prev_stop, next_stop, offset); |
4617 | - gradient->ensureVector(); |
4618 | - updateDraggers(); |
4619 | - |
4620 | - return newstop; |
4621 | - } |
4622 | - |
4623 | - return NULL; |
4624 | -} |
4625 | - |
4626 | - |
4627 | -bool |
4628 | -GrDrag::dropColor(SPItem */*item*/, gchar const *c, Geom::Point p) |
4629 | -{ |
4630 | - // Note: not sure if a null pointer can come in for the style, but handle that just in case |
4631 | - bool stopIsNull = false; |
4632 | - Glib::ustring toUse = makeStopSafeColor( c, stopIsNull ); |
4633 | - |
4634 | - // first, see if we can drop onto one of the existing draggers |
4635 | - for (GList *i = draggers; i != NULL; i = i->next) { // for all draggables of dragger |
4636 | - GrDragger *d = (GrDragger *) i->data; |
4637 | - |
4638 | - if (Geom::L2(p - d->point)*desktop->current_zoom() < 5) { |
4639 | - SPCSSAttr *stop = sp_repr_css_attr_new (); |
4640 | - sp_repr_css_set_property( stop, "stop-color", stopIsNull ? 0 : toUse.c_str() ); |
4641 | - sp_repr_css_set_property( stop, "stop-opacity", "1" ); |
4642 | - for (GSList *j = d->draggables; j != NULL; j = j->next) { // for all draggables of dragger |
4643 | - GrDraggable *draggable = (GrDraggable *) j->data; |
4644 | - local_change = true; |
4645 | - sp_item_gradient_stop_set_style (draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke, stop); |
4646 | - } |
4647 | - sp_repr_css_attr_unref(stop); |
4648 | - return true; |
4649 | - } |
4650 | - } |
4651 | - |
4652 | - // now see if we're over line and create a new stop |
4653 | - bool over_line = false; |
4654 | - SPCtrlLine *line = NULL; |
4655 | - if (lines) { |
4656 | - for (GSList *l = lines; (l != NULL) && (!over_line); l = l->next) { |
4657 | - line = (SPCtrlLine*) l->data; |
4658 | - Geom::Point nearest = snap_vector_midpoint (p, line->s, line->e, 0); |
4659 | - double dist_screen = Geom::L2 (p - nearest) * desktop->current_zoom(); |
4660 | - if (line->item && dist_screen < 5) { |
4661 | - SPStop *stop = addStopNearPoint (line->item, p, 5/desktop->current_zoom()); |
4662 | - if (stop) { |
4663 | - SPCSSAttr *css = sp_repr_css_attr_new (); |
4664 | - sp_repr_css_set_property( css, "stop-color", stopIsNull ? 0 : toUse.c_str() ); |
4665 | - sp_repr_css_set_property( css, "stop-opacity", "1" ); |
4666 | - sp_repr_css_change (SP_OBJECT_REPR (stop), css, "style"); |
4667 | - return true; |
4668 | - } |
4669 | - } |
4670 | - } |
4671 | - } |
4672 | - |
4673 | - return false; |
4674 | -} |
4675 | - |
4676 | - |
4677 | -GrDrag::GrDrag(SPDesktop *desktop) : |
4678 | - selected(0), |
4679 | - keep_selection(false), |
4680 | - local_change(false), |
4681 | - desktop(desktop), |
4682 | - hor_levels(), |
4683 | - vert_levels(), |
4684 | - draggers(0), |
4685 | - lines(0), |
4686 | - selection(sp_desktop_selection(desktop)), |
4687 | - sel_changed_connection(), |
4688 | - sel_modified_connection(), |
4689 | - style_set_connection(), |
4690 | - style_query_connection() |
4691 | -{ |
4692 | - sel_changed_connection = selection->connectChanged( |
4693 | - sigc::bind( |
4694 | - sigc::ptr_fun(&gr_drag_sel_changed), |
4695 | - (gpointer)this ) |
4696 | - |
4697 | - ); |
4698 | - sel_modified_connection = selection->connectModified( |
4699 | - sigc::bind( |
4700 | - sigc::ptr_fun(&gr_drag_sel_modified), |
4701 | - (gpointer)this ) |
4702 | - ); |
4703 | - |
4704 | - style_set_connection = desktop->connectSetStyle( sigc::mem_fun(*this, &GrDrag::styleSet) ); |
4705 | - |
4706 | - style_query_connection = desktop->connectQueryStyle( |
4707 | - sigc::bind( |
4708 | - sigc::ptr_fun(&gr_drag_style_query), |
4709 | - (gpointer)this ) |
4710 | - ); |
4711 | - |
4712 | - updateDraggers(); |
4713 | - updateLines(); |
4714 | - updateLevels(); |
4715 | - |
4716 | - if (desktop->gr_item) { |
4717 | - setSelected(getDraggerFor(desktop->gr_item, desktop->gr_point_type, desktop->gr_point_i, desktop->gr_fill_or_stroke)); |
4718 | - } |
4719 | -} |
4720 | - |
4721 | -GrDrag::~GrDrag() |
4722 | -{ |
4723 | - this->sel_changed_connection.disconnect(); |
4724 | - this->sel_modified_connection.disconnect(); |
4725 | - this->style_set_connection.disconnect(); |
4726 | - this->style_query_connection.disconnect(); |
4727 | - |
4728 | - if (this->selected) { |
4729 | - GrDraggable *draggable = (GrDraggable *) ((GrDragger*)this->selected->data)->draggables->data; |
4730 | - desktop->gr_item = draggable->item; |
4731 | - desktop->gr_point_type = draggable->point_type; |
4732 | - desktop->gr_point_i = draggable->point_i; |
4733 | - desktop->gr_fill_or_stroke = draggable->fill_or_stroke; |
4734 | - } else { |
4735 | - desktop->gr_item = NULL; |
4736 | - desktop->gr_point_type = 0; |
4737 | - desktop->gr_point_i = 0; |
4738 | - desktop->gr_fill_or_stroke = true; |
4739 | - } |
4740 | - |
4741 | - deselect_all(); |
4742 | - for (GList *l = this->draggers; l != NULL; l = l->next) { |
4743 | - delete ((GrDragger *) l->data); |
4744 | - } |
4745 | - g_list_free (this->draggers); |
4746 | - this->draggers = NULL; |
4747 | - this->selected = NULL; |
4748 | - |
4749 | - for (GSList *l = this->lines; l != NULL; l = l->next) { |
4750 | - gtk_object_destroy( GTK_OBJECT (l->data)); |
4751 | - } |
4752 | - g_slist_free (this->lines); |
4753 | - this->lines = NULL; |
4754 | -} |
4755 | - |
4756 | -GrDraggable::GrDraggable (SPItem *item, guint point_type, guint point_i, bool fill_or_stroke) |
4757 | -{ |
4758 | - this->item = item; |
4759 | - this->point_type = point_type; |
4760 | - this->point_i = point_i; |
4761 | - this->fill_or_stroke = fill_or_stroke; |
4762 | - |
4763 | - g_object_ref (G_OBJECT (this->item)); |
4764 | -} |
4765 | - |
4766 | -GrDraggable::~GrDraggable () |
4767 | -{ |
4768 | - g_object_unref (G_OBJECT (this->item)); |
4769 | -} |
4770 | - |
4771 | - |
4772 | -SPObject *GrDraggable::getServer() |
4773 | -{ |
4774 | - if (!item) { |
4775 | - return NULL; |
4776 | - } |
4777 | - |
4778 | - SPObject *server = NULL; |
4779 | - if (fill_or_stroke) { |
4780 | - server = item->style->getFillPaintServer(); |
4781 | - }else { |
4782 | - server = item->style->getStrokePaintServer(); |
4783 | - } |
4784 | - |
4785 | - return server; |
4786 | -} |
4787 | - |
4788 | -static |
4789 | -boost::optional<Geom::Point> |
4790 | -get_snap_vector (Geom::Point p, Geom::Point o, double snap, double initial) |
4791 | -{ |
4792 | - double r = L2 (p - o); |
4793 | - if (r < 1e-3) { |
4794 | - return boost::optional<Geom::Point>(); |
4795 | - } |
4796 | - |
4797 | - double angle = atan2 (p - o); |
4798 | - // snap angle to snaps increments, starting from initial: |
4799 | - double a_snapped = initial + floor((angle - initial)/snap + 0.5) * snap; |
4800 | - // calculate the new position and subtract p to get the vector: |
4801 | - return (o + r * Geom::Point(cos(a_snapped), sin(a_snapped)) - p); |
4802 | -} |
4803 | - |
4804 | -static void |
4805 | -gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gpointer data) |
4806 | -{ |
4807 | - GrDragger *dragger = (GrDragger *) data; |
4808 | - GrDrag *drag = dragger->parent; |
4809 | - |
4810 | - Geom::Point p = ppointer; |
4811 | - |
4812 | - SPDesktop *desktop = dragger->parent->desktop; |
4813 | - SnapManager &m = desktop->namedview->snap_manager; |
4814 | - double snap_dist = m.snapprefs.getObjectTolerance() / dragger->parent->desktop->current_zoom(); |
4815 | - |
4816 | - if (state & GDK_SHIFT_MASK) { |
4817 | - // with Shift; unsnap if we carry more than one draggable |
4818 | - if (dragger->draggables && dragger->draggables->next) { |
4819 | - // create a new dragger |
4820 | - GrDragger *dr_new = new GrDragger (dragger->parent, dragger->point, NULL); |
4821 | - dragger->parent->draggers = g_list_prepend (dragger->parent->draggers, dr_new); |
4822 | - // relink to it all but the first draggable in the list |
4823 | - for (GSList const* i = dragger->draggables->next; i != NULL; i = i->next) { |
4824 | - GrDraggable *draggable = (GrDraggable *) i->data; |
4825 | - dr_new->addDraggable (draggable); |
4826 | - } |
4827 | - dr_new->updateKnotShape(); |
4828 | - g_slist_free (dragger->draggables->next); |
4829 | - dragger->draggables->next = NULL; |
4830 | - dragger->updateKnotShape(); |
4831 | - dragger->updateTip(); |
4832 | - } |
4833 | - } else if (!(state & GDK_CONTROL_MASK)) { |
4834 | - // without Shift or Ctrl; see if we need to snap to another dragger |
4835 | - for (GList *di = dragger->parent->draggers; di != NULL; di = di->next) { |
4836 | - GrDragger *d_new = (GrDragger *) di->data; |
4837 | - if (dragger->mayMerge(d_new) && Geom::L2 (d_new->point - p) < snap_dist) { |
4838 | - |
4839 | - // Merge draggers: |
4840 | - for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger |
4841 | - GrDraggable *draggable = (GrDraggable *) i->data; |
4842 | - // copy draggable to d_new: |
4843 | - GrDraggable *da_new = new GrDraggable (draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke); |
4844 | - d_new->addDraggable (da_new); |
4845 | - } |
4846 | - |
4847 | - // unlink and delete this dragger |
4848 | - dragger->parent->draggers = g_list_remove (dragger->parent->draggers, dragger); |
4849 | - delete dragger; |
4850 | - |
4851 | - // update the new merged dragger |
4852 | - d_new->fireDraggables(true, false, true); |
4853 | - d_new->parent->updateLines(); |
4854 | - d_new->parent->setSelected (d_new); |
4855 | - d_new->updateKnotShape (); |
4856 | - d_new->updateTip (); |
4857 | - d_new->updateDependencies(true); |
4858 | - sp_document_done (sp_desktop_document (d_new->parent->desktop), SP_VERB_CONTEXT_GRADIENT, |
4859 | - _("Merge gradient handles")); |
4860 | - return; |
4861 | - } |
4862 | - } |
4863 | - } |
4864 | - |
4865 | - m.setup(desktop); |
4866 | - if (!((state & GDK_SHIFT_MASK) || (state & GDK_CONTROL_MASK))) { |
4867 | - Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE)); |
4868 | - if (s.getSnapped()) { |
4869 | - p = s.getPoint(); |
4870 | - sp_knot_moveto (knot, p); |
4871 | - } |
4872 | - } else if (state & GDK_CONTROL_MASK) { |
4873 | - SnappedConstraints sc; |
4874 | - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
4875 | - unsigned snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12)); |
4876 | - /* 0 means no snapping. */ |
4877 | - |
4878 | - for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { |
4879 | - GrDraggable *draggable = (GrDraggable *) i->data; |
4880 | - |
4881 | - Geom::Point dr_snap(Geom::infinity(), Geom::infinity()); |
4882 | - |
4883 | - if (draggable->point_type == POINT_LG_BEGIN || draggable->point_type == POINT_LG_END) { |
4884 | - for (GList *di = dragger->parent->draggers; di != NULL; di = di->next) { |
4885 | - GrDragger *d_new = (GrDragger *) di->data; |
4886 | - if (d_new == dragger) |
4887 | - continue; |
4888 | - if (d_new->isA (draggable->item, |
4889 | - draggable->point_type == POINT_LG_BEGIN? POINT_LG_END : POINT_LG_BEGIN, |
4890 | - draggable->fill_or_stroke)) { |
4891 | - // found the other end of the linear gradient; |
4892 | - if (state & GDK_SHIFT_MASK) { |
4893 | - // moving linear around center |
4894 | - Geom::Point center = Geom::Point (0.5*(d_new->point + dragger->point)); |
4895 | - dr_snap = center; |
4896 | - } else { |
4897 | - // moving linear around the other end |
4898 | - dr_snap = d_new->point; |
4899 | - } |
4900 | - } |
4901 | - } |
4902 | - } else if (draggable->point_type == POINT_RG_R1 || draggable->point_type == POINT_RG_R2 || draggable->point_type == POINT_RG_FOCUS) { |
4903 | - for (GList *di = dragger->parent->draggers; di != NULL; di = di->next) { |
4904 | - GrDragger *d_new = (GrDragger *) di->data; |
4905 | - if (d_new == dragger) |
4906 | - continue; |
4907 | - if (d_new->isA (draggable->item, |
4908 | - POINT_RG_CENTER, |
4909 | - draggable->fill_or_stroke)) { |
4910 | - // found the center of the radial gradient; |
4911 | - dr_snap = d_new->point; |
4912 | - } |
4913 | - } |
4914 | - } else if (draggable->point_type == POINT_RG_CENTER) { |
4915 | - // radial center snaps to hor/vert relative to its original position |
4916 | - dr_snap = dragger->point_original; |
4917 | - } |
4918 | - |
4919 | - boost::optional<Geom::Point> snap_vector; |
4920 | - if (dr_snap.isFinite()) { |
4921 | - if (state & GDK_MOD1_MASK) { |
4922 | - // with Alt, snap to the original angle and its perpendiculars |
4923 | - snap_vector = get_snap_vector (p, dr_snap, M_PI/2, Geom::atan2 (dragger->point_original - dr_snap)); |
4924 | - } else { |
4925 | - // with Ctrl, snap to M_PI/snaps |
4926 | - snap_vector = get_snap_vector (p, dr_snap, M_PI/snaps, 0); |
4927 | - } |
4928 | - if (snap_vector) { |
4929 | - Inkscape::Snapper::ConstraintLine cl(dr_snap, p + *snap_vector - dr_snap); |
4930 | - Inkscape::SnappedPoint s = m.constrainedSnap(Inkscape::SnapCandidatePoint(p + *snap_vector, Inkscape::SNAPSOURCE_OTHER_HANDLE), cl); |
4931 | - if (s.getSnapped()) { |
4932 | - s.setTransformation(s.getPoint() - p); |
4933 | - sc.points.push_back(s); |
4934 | - } else { |
4935 | - Inkscape::SnappedPoint dummy(p + *snap_vector, Inkscape::SNAPSOURCE_OTHER_HANDLE, 0, Inkscape::SNAPTARGET_CONSTRAINED_ANGLE, Geom::L2(*snap_vector), 10000, true, true, false); |
4936 | - dummy.setTransformation(*snap_vector); |
4937 | - sc.points.push_back(dummy); |
4938 | - } |
4939 | - } |
4940 | - } |
4941 | - } |
4942 | - |
4943 | - Inkscape::SnappedPoint bsp = m.findBestSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE), sc, true); // snap indicator will be displayed if needed |
4944 | - |
4945 | - if (bsp.getSnapped()) { |
4946 | - p += bsp.getTransformation(); |
4947 | - sp_knot_moveto (knot, p); |
4948 | - } |
4949 | - } |
4950 | - |
4951 | - drag->keep_selection = (bool) g_list_find(drag->selected, dragger); |
4952 | - bool scale_radial = (state & GDK_CONTROL_MASK) && (state & GDK_SHIFT_MASK); |
4953 | - |
4954 | - if (drag->keep_selection) { |
4955 | - Geom::Point diff = p - dragger->point; |
4956 | - drag->selected_move_nowrite (diff[Geom::X], diff[Geom::Y], scale_radial); |
4957 | - } else { |
4958 | - dragger->point = p; |
4959 | - dragger->fireDraggables (false, scale_radial); |
4960 | - dragger->updateDependencies(false); |
4961 | - } |
4962 | - |
4963 | -} |
4964 | - |
4965 | - |
4966 | -static void |
4967 | -gr_midpoint_limits(GrDragger *dragger, SPObject *server, Geom::Point *begin, Geom::Point *end, Geom::Point *low_lim, Geom::Point *high_lim, GSList **moving) |
4968 | -{ |
4969 | - |
4970 | - GrDrag *drag = dragger->parent; |
4971 | - // a midpoint dragger can (logically) only contain one GrDraggable |
4972 | - GrDraggable *draggable = (GrDraggable *) dragger->draggables->data; |
4973 | - |
4974 | - // get begin and end points between which dragging is allowed: |
4975 | - // the draglimits are between knot(lowest_i - 1) and knot(highest_i + 1) |
4976 | - *moving = g_slist_append(*moving, dragger); |
4977 | - |
4978 | - guint lowest_i = draggable->point_i; |
4979 | - guint highest_i = draggable->point_i; |
4980 | - GrDragger *lowest_dragger = dragger; |
4981 | - GrDragger *highest_dragger = dragger; |
4982 | - if (dragger->isSelected()) { |
4983 | - GrDragger* d_add; |
4984 | - while ( true ) |
4985 | - { |
4986 | - d_add = drag->getDraggerFor(draggable->item, draggable->point_type, lowest_i - 1, draggable->fill_or_stroke); |
4987 | - if ( d_add && g_list_find(drag->selected, d_add) ) { |
4988 | - lowest_i = lowest_i - 1; |
4989 | - *moving = g_slist_prepend(*moving, d_add); |
4990 | - lowest_dragger = d_add; |
4991 | - } else { |
4992 | - break; |
4993 | - } |
4994 | - } |
4995 | - |
4996 | - while ( true ) |
4997 | - { |
4998 | - d_add = drag->getDraggerFor(draggable->item, draggable->point_type, highest_i + 1, draggable->fill_or_stroke); |
4999 | - if ( d_add && g_list_find(drag->selected, d_add) ) { |
5000 | - highest_i = highest_i + 1; |
The diff has been truncated for viewing.
Thanks. Uploaded.